1
0
Fork 0
forked from len0rd/rockbox

metadata: opus, vorbis, speex: support embedded jpeg album art

It includes .opus, .ogg, .oga, .spx files

Change-Id: I3d0ee9806b05911fc8c3ce5cb761de87d4166141
This commit is contained in:
Roman Artiukhin 2025-01-14 09:53:06 +02:00
parent 95f4accf45
commit 0847bcc110
8 changed files with 300 additions and 149 deletions

View file

@ -26,7 +26,7 @@
* KIND, either express or implied.
*
****************************************************************************/
#include "embedded_metadata.h"
#include "metadata_common.h"
#include "plugin.h"
#include "debug.h"
#include "jpeg_load.h"
@ -81,6 +81,7 @@ struct jpeg
int buf_index;
int (*read_buf)(struct jpeg* p_jpeg, size_t count);
bool (*skip_bytes_seek)(struct jpeg* p_jpeg);
void* custom_param;
#endif
unsigned long len;
@ -881,22 +882,50 @@ static int read_buf(struct jpeg* p_jpeg, size_t count)
return read(p_jpeg->fd, p_jpeg->buf, count);
}
INLINE void fill_buf(struct jpeg* p_jpeg)
{
p_jpeg->buf_left = p_jpeg->read_buf(p_jpeg, MIN(JPEG_READ_BUF_SIZE, p_jpeg->len));
p_jpeg->buf_index = 0;
if (p_jpeg->buf_left > 0)
p_jpeg->len -= p_jpeg->buf_left;
}
#ifdef HAVE_ALBUMART
static int read_buf_id3_unsync(struct jpeg* p_jpeg, size_t count)
{
count = read(p_jpeg->fd, p_jpeg->buf, count);
return id3_unsynchronize(p_jpeg->buf, count, (bool*) &p_jpeg->custom_param);
}
#endif
INLINE void fill_buf(struct jpeg* p_jpeg)
static int read_buf_vorbis_base64(struct jpeg* p_jpeg, size_t count)
{
p_jpeg->buf_left = p_jpeg->read_buf(p_jpeg, MIN(JPEG_READ_BUF_SIZE, p_jpeg->len));
p_jpeg->buf_index = 0;
if (p_jpeg->buf_left > 0)
p_jpeg->len -= p_jpeg->buf_left;
struct ogg_file* ogg = p_jpeg->custom_param;
unsigned char* buf = p_jpeg->buf;
count = ogg_file_read(ogg, buf, count);
if (count == (size_t) -1)
return 0;
return base64_decode(buf, count, buf);
}
/* when pjpeg->read_buf involves additional data processing (like base64 decoding)
* we can't use lseek and have to call pjpeg->read_buf for proper seek */
static bool skip_bytes_read_buf(struct jpeg* p_jpeg)
{
do
{
int count = -p_jpeg->buf_left;
fill_buf(p_jpeg);
if (p_jpeg->buf_left < 0)
return false;
p_jpeg->buf_left -= count;
p_jpeg->buf_index += count;
} while (p_jpeg->buf_left < 0);
return true;
}
#endif /* HAVE_ALBUMART */
static unsigned char *jpeg_getc(struct jpeg* p_jpeg)
{
if (UNLIKELY(p_jpeg->buf_left < 1))
@ -907,7 +936,7 @@ static unsigned char *jpeg_getc(struct jpeg* p_jpeg)
return (p_jpeg->buf_index++) + p_jpeg->buf;
}
INLINE bool skip_bytes_seek(struct jpeg* p_jpeg)
static bool skip_bytes_seek(struct jpeg* p_jpeg)
{
if (UNLIKELY(lseek(p_jpeg->fd, -p_jpeg->buf_left, SEEK_CUR) < 0))
return false;
@ -919,7 +948,7 @@ static bool skip_bytes(struct jpeg* p_jpeg, int count)
{
p_jpeg->buf_left -= count;
p_jpeg->buf_index += count;
return p_jpeg->buf_left >= 0 || skip_bytes_seek(p_jpeg);
return p_jpeg->buf_left >= 0 || p_jpeg->skip_bytes_seek(p_jpeg);
}
static void jpeg_putc(struct jpeg* p_jpeg)
@ -2055,6 +2084,7 @@ int clip_jpeg_fd(int fd, int flags,
p_jpeg->len = filesize(p_jpeg->fd);
p_jpeg->read_buf = read_buf;
p_jpeg->skip_bytes_seek = skip_bytes_seek;
#ifdef HAVE_ALBUMART
if (flags & AA_FLAG_ID3_UNSYNC)
@ -2062,9 +2092,34 @@ int clip_jpeg_fd(int fd, int flags,
p_jpeg->read_buf = read_buf_id3_unsync;
p_jpeg->custom_param = false;
}
else if (flags & AA_FLAG_VORBIS_BASE64)
{
struct ogg_file* ogg = alloca(sizeof(*ogg));
off_t pic_pos = lseek(fd, 0, SEEK_CUR);
// we need 92 bytes for format probing, reuse some available space
unsigned char* buf_format = (unsigned char*) p_jpeg->quanttable;
int type = get_ogg_format_and_move_to_comments(fd, buf_format);
ogg_file_init(ogg, fd, type, 0);
bool packet_found;
do
{
int seek_from_cur_pos = pic_pos - lseek(fd, 0, SEEK_CUR);
packet_found = seek_from_cur_pos <= ogg->packet_remaining;
if (ogg_file_read(ogg, NULL, packet_found ? seek_from_cur_pos : ogg->packet_remaining) < 0)
return -1;
}
while (!packet_found);
p_jpeg->read_buf = read_buf_vorbis_base64;
p_jpeg->skip_bytes_seek = skip_bytes_read_buf;
p_jpeg->custom_param = ogg;
}
#else
(void)flags;
#endif
#endif /* HAVE_ALBUMART */
#endif
status = process_markers(p_jpeg);
#ifndef JPEG_FROM_MEM