mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-28 08:05:56 -05:00
[artwork] Add ability to rescale Spotify (should improve caching so we don't save too large images)
This commit is contained in:
parent
9a0a390a73
commit
7caf8cc66a
@ -472,8 +472,8 @@ artwork_rescale(struct evbuffer *evbuf, AVFormatContext *src_ctx, int s, int out
|
|||||||
av_free_packet(&pkt);
|
av_free_packet(&pkt);
|
||||||
|
|
||||||
/* Open output file */
|
/* Open output file */
|
||||||
dst_ctx->pb = avio_evbuffer_open(evbuf);
|
dst_ctx->pb = avio_output_evbuffer_open(evbuf);
|
||||||
if (ret < 0)
|
if (!dst_ctx->pb)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_ART, "Could not open artwork destination buffer\n");
|
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
|
static int
|
||||||
source_item_spotify_get(struct artwork_ctx *ctx)
|
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;
|
int ret;
|
||||||
|
|
||||||
ret = spotify_artwork_get(ctx->evbuf, ctx->dbmfi->path, ctx->max_w, ctx->max_h);
|
evbuf = evbuffer_new();
|
||||||
if (ret < 0)
|
if (!evbuf)
|
||||||
return ART_E_NONE;
|
{
|
||||||
|
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;
|
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
|
#else
|
||||||
static int
|
static int
|
||||||
|
@ -38,6 +38,18 @@ struct avio_evbuffer {
|
|||||||
uint8_t *buffer;
|
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
|
static int
|
||||||
avio_evbuffer_write(void *opaque, uint8_t *buf, int size)
|
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;
|
return (ret == 0) ? size : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
AVIOContext *
|
static AVIOContext *
|
||||||
avio_evbuffer_open(struct evbuffer *evbuf)
|
avio_evbuffer_open(struct evbuffer *evbuf, int is_output)
|
||||||
{
|
{
|
||||||
struct avio_evbuffer *ae;
|
struct avio_evbuffer *ae;
|
||||||
AVIOContext *s;
|
AVIOContext *s;
|
||||||
@ -77,7 +89,11 @@ avio_evbuffer_open(struct evbuffer *evbuf)
|
|||||||
|
|
||||||
ae->evbuf = evbuf;
|
ae->evbuf = evbuf;
|
||||||
|
|
||||||
|
if (is_output)
|
||||||
s = avio_alloc_context(ae->buffer, BUFFER_SIZE, 1, ae, NULL, avio_evbuffer_write, NULL);
|
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)
|
if (!s)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_FFMPEG, "Could not allocate AVIOContext\n");
|
DPRINTF(E_LOG, L_FFMPEG, "Could not allocate AVIOContext\n");
|
||||||
@ -92,6 +108,18 @@ avio_evbuffer_open(struct evbuffer *evbuf)
|
|||||||
return s;
|
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
|
void
|
||||||
avio_evbuffer_close(AVIOContext *s)
|
avio_evbuffer_close(AVIOContext *s)
|
||||||
{
|
{
|
||||||
@ -101,7 +129,7 @@ avio_evbuffer_close(AVIOContext *s)
|
|||||||
|
|
||||||
avio_flush(s);
|
avio_flush(s);
|
||||||
|
|
||||||
av_free(ae->buffer);
|
av_free(s->buffer);
|
||||||
free(ae);
|
free(ae);
|
||||||
|
|
||||||
av_free(s);
|
av_free(s);
|
||||||
|
@ -5,7 +5,10 @@
|
|||||||
#include <event2/buffer.h>
|
#include <event2/buffer.h>
|
||||||
|
|
||||||
AVIOContext *
|
AVIOContext *
|
||||||
avio_evbuffer_open(struct evbuffer *evbuf);
|
avio_input_evbuffer_open(struct evbuffer *evbuf);
|
||||||
|
|
||||||
|
AVIOContext *
|
||||||
|
avio_output_evbuffer_open(struct evbuffer *evbuf);
|
||||||
|
|
||||||
void
|
void
|
||||||
avio_evbuffer_close(AVIOContext *s);
|
avio_evbuffer_close(AVIOContext *s);
|
||||||
|
@ -725,7 +725,7 @@ open_output(struct encode_ctx *ctx, struct decode_ctx *src_ctx)
|
|||||||
goto out_fail_evbuf;
|
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)
|
if (!ctx->ofmt_ctx->pb)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_XCODE, "Could not create output avio pb\n");
|
DPRINTF(E_LOG, L_XCODE, "Could not create output avio pb\n");
|
||||||
|
Loading…
Reference in New Issue
Block a user