Rockbox.org home
release
dev builds
extras
themes manual
wiki
device status forums
mailing lists
IRC bugs
patches
dev guide
translations



Rockbox mail archive

Subject: Re: kugel: r29259 - in trunk/apps: . metadata recorder

Re: kugel: r29259 - in trunk/apps: . metadata recorder

From: Jeff Goode <jeffg7_at_gmail.com>
Date: Wed, 09 Feb 2011 15:51:59 -0500

Oh, nice. I look forward to trying this one out!

On 2/9/2011 15:13, mailer_at_svn.rockbox.org wrote:
> Date: 2011-02-09 21:13:13 +0100 (Wed, 09 Feb 2011)
> New Revision: 29259
>
> Log Message:
> Embedded album art support in MP3/ID3v2 tags.
>
> - Support is limited to non-desync jpeg in id3v2 tags. Other formats (hopefully) follow in the future.
> - Embedded album art takes precedence over files in album art files.
> - No additional buffers are used, the jpeg is read directly from the audio file.
>
> Flyspray: FS#11216
> Author: Yoshihisa Uchida and I
>
> Modified:
> trunk/apps/buffering.c
> trunk/apps/metadata.h
> trunk/apps/metadata/id3tags.c
> trunk/apps/playback.c
> trunk/apps/playback.h
> trunk/apps/recorder/jpeg_load.c
> trunk/apps/recorder/jpeg_load.h
>
> Modified: trunk/apps/buffering.c
> ===================================================================
> --- trunk/apps/buffering.c 2011-02-09 09:30:09 UTC (rev 29258)
> +++ trunk/apps/buffering.c 2011-02-09 20:13:13 UTC (rev 29259)
> _at__at_ -52,6 +52,7 _at__at_
> #include "albumart.h"
> #include "jpeg_load.h"
> #include "bmp.h"
> +#include "playback.h"
> #endif
>
> #define GUARD_BUFSIZE (32*1024)
> _at__at_ -908,10 +909,12 _at__at_
> /* Given a file descriptor to a bitmap file, write the bitmap data to the
> buffer, with a struct bitmap and the actual data immediately following.
> Return value is the total size (struct + data). */
> -static int load_image(int fd, const char *path, struct dim *dim)
> +static int load_image(int fd, const char *path, struct bufopen_bitmap_data *data)
> {
> int rc;
> struct bitmap *bmp = (struct bitmap *)&buffer[buf_widx];
> + struct dim *dim = data->dim;
> + struct mp3_albumart *aa = data->embedded_albumart;
>
> /* get the desired image size */
> bmp->width = dim->width, bmp->height = dim->height;
> _at__at_ -928,8 +931,13 _at__at_
> - sizeof(struct bitmap);
>
> #ifdef HAVE_JPEG
> - int pathlen = strlen(path);
> - if (strcmp(path + pathlen - 4, ".bmp"))
> + if (aa != NULL)
> + {
> + lseek(fd, aa->pos, SEEK_SET);
> + rc = clip_jpeg_fd(fd, aa->size, bmp, free, FORMAT_NATIVE|FORMAT_DITHER|
> + FORMAT_RESIZE|FORMAT_KEEP_ASPECT, NULL);
> + }
> + else if (strcmp(path + strlen(path) - 4, ".bmp"))
> rc = read_jpeg_fd(fd, bmp, free, FORMAT_NATIVE|FORMAT_DITHER|
> FORMAT_RESIZE|FORMAT_KEEP_ASPECT, NULL);
> else
> _at__at_ -1010,7 +1018,18 _at__at_
> if (fd< 0)
> return ERR_FILE_ERROR;
>
> - size_t size = filesize(fd);
> + size_t size = 0;
> +#ifdef HAVE_ALBUMART
> + if (type == TYPE_BITMAP)
> + { /* if albumart is embedded, the complete file is not buffered,
> + * but only the jpeg part; filesize() would be wrong */
> + struct bufopen_bitmap_data *aa = (struct bufopen_bitmap_data*)user_data;
> + if (aa->embedded_albumart)
> + size = aa->embedded_albumart->size;
> + }
> +#endif
> + if (size == 0)
> + size = filesize(fd);
> bool can_wrap = type==TYPE_PACKET_AUDIO || type==TYPE_CODEC;
>
> size_t adjusted_offset = offset;
> _at__at_ -1058,7 +1077,7 _at__at_
> /* Bitmap file: we load the data instead of the file */
> int rc;
> mutex_lock(&llist_mod_mutex); /* Lock because load_bitmap yields */
> - rc = load_image(fd, file, (struct dim*)user_data);
> + rc = load_image(fd, file, (struct bufopen_bitmap_data*)user_data);
> mutex_unlock(&llist_mod_mutex);
> if (rc<= 0)
> {
>
> Modified: trunk/apps/metadata/id3tags.c
> ===================================================================
> --- trunk/apps/metadata/id3tags.c 2011-02-09 09:30:09 UTC (rev 29258)
> +++ trunk/apps/metadata/id3tags.c 2011-02-09 20:13:13 UTC (rev 29259)
> _at__at_ -290,6 +290,63 _at__at_
> }
> }
>
> +#ifdef HAVE_ALBUMART
> +/* parse embed albumart */
> +static int parsealbumart( struct mp3entry* entry, char* tag, int bufferpos )
> +{
> + entry->embed_albumart = false;
> +
> + /* we currently don't support unsynchronizing albumart */
> + if (entry->albumart.type == AA_TYPE_UNSYNC)
> + return bufferpos;
> +
> + entry->albumart.type = AA_TYPE_UNKNOWN;
> +
> + char *start = tag;
> + /* skip text encoding */
> + tag += 1;
> +
> + if (memcmp(tag, "image/", 6) == 0)
> + {
> + /* ID3 v2.3+ */
> + tag += 6;
> + if (strcmp(tag, "jpeg") == 0)
> + {
> + entry->albumart.type = AA_TYPE_JPG;
> + tag += 5;
> + }
> + else if (strcmp(tag, "png") == 0)
> + {
> + entry->albumart.type = AA_TYPE_PNG;
> + tag += 4;
> + }
> + }
> + else
> + {
> + /* ID3 v2.2 */
> + if (memcmp(tag, "JPG", 3) == 0)
> + entry->albumart.type = AA_TYPE_JPG;
> + else if (memcmp(tag, "PNG", 3) == 0)
> + entry->albumart.type = AA_TYPE_PNG;
> + tag += 3;
> + }
> +
> + if (entry->albumart.type != AA_TYPE_UNKNOWN)
> + {
> + /* skip picture type */
> + tag += 1;
> + /* skip description */
> + tag = strchr(tag, '\0') + 1;
> + /* fixup offset&size for image data */
> + entry->albumart.pos += tag - start;
> + entry->albumart.size -= tag - start;
> + entry->embed_albumart = true;
> + }
> + /* return bufferpos as we didn't store anything in id3v2buf */
> + return bufferpos;
> +}
> +#endif
> +
> /* parse user defined text, looking for album artist and replaygain
> * information.
> */
> _at__at_ -439,6 +496,10 _at__at_
> { "COM", 3, offsetof(struct mp3entry, comment), NULL, false },
> { "TCON", 4, offsetof(struct mp3entry, genre_string),&parsegenre, false },
> { "TCO", 3, offsetof(struct mp3entry, genre_string),&parsegenre, false },
> +#ifdef HAVE_ALBUMART
> + { "APIC", 4, 0,&parsealbumart, true },
> + { "PIC", 3, 0,&parsealbumart, true },
> +#endif
> { "TXXX", 4, 0,&parseuser, false },
> #if CONFIG_CODEC == SWCODEC
> { "RVA2", 4, 0,&parserva2, true },
> _at__at_ -961,6 +1022,21 _at__at_
> if (ptag&& !*ptag)
> *ptag = tag;
>
> + /* albumart */
> + if ((!entry->embed_albumart)&&
> + ((tr->tag_length == 4&& !memcmp( header, "APIC", 4)) ||
> + (tr->tag_length == 3&& !memcmp( header, "PIC" , 3))))
> + {
> + if (unsynch || (global_unsynch&& version<= ID3_VER_2_3))
> + entry->albumart.type = AA_TYPE_UNSYNC;
> + else
> + {
> + entry->albumart.pos = lseek(fd, 0, SEEK_CUR) - framelen;
> + entry->albumart.size = totframelen;
> + entry->albumart.type = AA_TYPE_UNKNOWN;
> + }
> + }
> +
> if( tr->ppFunc )
> bufferpos = tr->ppFunc(entry, tag, bufferpos);
>
>
> Modified: trunk/apps/metadata.h
> ===================================================================
> --- trunk/apps/metadata.h 2011-02-09 09:30:09 UTC (rev 29258)
> +++ trunk/apps/metadata.h 2011-02-09 20:13:13 UTC (rev 29259)
> _at__at_ -190,6 +190,22 _at__at_
> ID3_VER_2_4
> };
>
> +#ifdef HAVE_ALBUMART
> +enum mp3_aa_type {
> + AA_TYPE_UNSYNC = -1,
> + AA_TYPE_UNKNOWN,
> + AA_TYPE_BMP,
> + AA_TYPE_PNG,
> + AA_TYPE_JPG,
> +};
> +
> +struct mp3_albumart {
> + enum mp3_aa_type type;
> + int size;
> + off_t pos;
> +};
> +#endif
> +
> struct mp3entry {
> char path[MAX_PATH];
> char* title;
> _at__at_ -277,6 +293,11 _at__at_
> long album_peak;
> #endif
>
> +#ifdef HAVE_ALBUMART
> + bool embed_albumart;
> + struct mp3_albumart albumart;
> +#endif
> +
> /* Cuesheet support */
> struct cuesheet *cuesheet;
>
>
> Modified: trunk/apps/playback.c
> ===================================================================
> --- trunk/apps/playback.c 2011-02-09 09:30:09 UTC (rev 29258)
> +++ trunk/apps/playback.c 2011-02-09 20:13:13 UTC (rev 29259)
> _at__at_ -142,6 +142,7 _at__at_
> #define MAX_MULTIPLE_AA SKINNABLE_SCREENS_COUNT
>
> #ifdef HAVE_ALBUMART
> +
> static struct albumart_slot {
> struct dim dim; /* holds width, height of the albumart */
> int used; /* counter, increments if something uses it */
> _at__at_ -228,7 +229,6 _at__at_
> static void audio_reset_buffer(void);
> static void audio_stop_playback(void);
>
> -
> /**************************************/
>
>
> _at__at_ -647,6 +647,7 _at__at_
> }
>
> #ifdef HAVE_ALBUMART
> +
> int playback_current_aa_hid(int slot)
> {
> if (slot< 0)
> _at__at_ -656,13 +657,13 _at__at_
>
> cur_idx = track_ridx + offset;
> cur_idx&= MAX_TRACK_MASK;
> -
> return tracks[cur_idx].aa_hid[slot];
> }
>
> int playback_claim_aa_slot(struct dim *dim)
> {
> int i;
> +
> /* first try to find a slot already having the size to reuse it
> * since we don't want albumart of the same size buffered multiple times */
> FOREACH_ALBUMART(i)
> _at__at_ -693,6 +694,7 _at__at_
> {
> /* invalidate the albumart_slot */
> struct albumart_slot *aa_slot =&albumart_slots[slot];
> +
> if (aa_slot->used> 0)
> aa_slot->used--;
> }
> _at__at_ -1315,19 +1317,37 _at__at_
> {
> int i;
> char aa_path[MAX_PATH];
> +
> FOREACH_ALBUMART(i)
> {
> /* albumart_slots may change during a yield of bufopen,
> * but that's no problem */
> if (tracks[track_widx].aa_hid[i]>= 0 || !albumart_slots[i].used)
> continue;
> +
> + /* we can only decode jpeg for embedded AA */
> + bool embedded_albumart =
> + track_id3->embed_albumart&& track_id3->albumart.type == AA_TYPE_JPG;
> /* find_albumart will error out if the wps doesn't have AA */
> - if (find_albumart(track_id3, aa_path, sizeof(aa_path),
> -&(albumart_slots[i].dim)))
> + if (embedded_albumart || find_albumart(track_id3, aa_path,
> + sizeof(aa_path),&(albumart_slots[i].dim)))
> {
> - int aa_hid = bufopen(aa_path, 0, TYPE_BITMAP,
> -&(albumart_slots[i].dim));
> -
> + int aa_hid;
> + struct bufopen_bitmap_data user_data = {
> + .dim =&(albumart_slots[i].dim),
> + .embedded_albumart = NULL,
> + };
> + if (embedded_albumart)
> + {
> + user_data.embedded_albumart =&(track_id3->albumart);
> + aa_hid = bufopen(track_id3->path, 0,
> + TYPE_BITMAP,&user_data);
> + }
> + else
> + {
> + aa_hid = bufopen(aa_path, 0, TYPE_BITMAP,
> +&user_data);
> + }
> if(aa_hid == ERR_BUFFER_FULL)
> {
> filling = STATE_FULL;
> _at__at_ -1342,7 +1362,6 _at__at_
> tracks[track_widx].aa_hid[i] = aa_hid;
> }
> }
> -
> }
> #endif
>
>
> Modified: trunk/apps/playback.h
> ===================================================================
> --- trunk/apps/playback.h 2011-02-09 09:30:09 UTC (rev 29258)
> +++ trunk/apps/playback.h 2011-02-09 20:13:13 UTC (rev 29259)
> _at__at_ -29,6 +29,7 _at__at_
> #ifdef HAVE_ALBUMART
>
> #include "bmp.h"
> +#include "metadata.h"
> /*
> * Returns the handle id of the buffered albumart for the given slot id
> **/
> _at__at_ -50,6 +51,12 _at__at_
> *
> * Save to call from other threads */
> void playback_release_aa_slot(int slot);
> +
> +struct bufopen_bitmap_data {
> + struct dim *dim;
> + struct mp3_albumart *embedded_albumart;
> +};
> +
> #endif
>
> /* Functions */
>
> Modified: trunk/apps/recorder/jpeg_load.c
> ===================================================================
> --- trunk/apps/recorder/jpeg_load.c 2011-02-09 09:30:09 UTC (rev 29258)
> +++ trunk/apps/recorder/jpeg_load.c 2011-02-09 20:13:13 UTC (rev 29259)
> _at__at_ -75,12 +75,12 _at__at_
> {
> #ifdef JPEG_FROM_MEM
> unsigned char *data;
> - unsigned long len;
> #else
> int fd;
> int buf_left;
> int buf_index;
> #endif
> + unsigned long len;
> unsigned long int bitbuf;
> int bitbuf_bits;
> int marker_ind;
> _at__at_ -888,8 +888,12 _at__at_
> #else
> INLINE void fill_buf(struct jpeg* p_jpeg)
> {
> - p_jpeg->buf_left = read(p_jpeg->fd, p_jpeg->buf, JPEG_READ_BUF_SIZE);
> + p_jpeg->buf_left = read(p_jpeg->fd, p_jpeg->buf,
> + (p_jpeg->len>= JPEG_READ_BUF_SIZE)?
> + 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;
> }
>
> static unsigned char *jpeg_getc(struct jpeg* p_jpeg)
> _at__at_ -1960,7 +1964,9 _at__at_
> *
> *****************************************************************************/
> #ifndef JPEG_FROM_MEM
> -int read_jpeg_file(const char* filename,
> +int clip_jpeg_file(const char* filename,
> + int offset,
> + unsigned long jpeg_size,
> struct bitmap *bm,
> int maxsize,
> int format,
> _at__at_ -1975,11 +1981,20 _at__at_
> DEBUGF("read_jpeg_file: can't open '%s', rc: %d\n", filename, fd);
> return fd * 10 - 1;
> }
> -
> - ret = read_jpeg_fd(fd, bm, maxsize, format, cformat);
> + lseek(fd, offset, SEEK_SET);
> + ret = clip_jpeg_fd(fd, jpeg_size, bm, maxsize, format, cformat);
> close(fd);
> return ret;
> }
> +
> +int read_jpeg_file(const char* filename,
> + struct bitmap *bm,
> + int maxsize,
> + int format,
> + const struct custom_format *cformat)
> +{
> + return clip_jpeg_file(filename, 0, 0, bm, maxsize, format, cformat);
> +}
> #endif
>
> static int calc_scale(int in_size, int out_size)
> _at__at_ -2014,10 +2029,11 _at__at_
> return 0;
> }
>
> -int decode_jpeg_mem(unsigned char *data, unsigned long len,
> +int decode_jpeg_mem(unsigned char *data,
> #else
> -int read_jpeg_fd(int fd,
> +int clip_jpeg_fd(int fd,
> #endif
> + unsigned long len,
> struct bitmap *bm,
> int maxsize,
> int format,
> _at__at_ -2039,11 +2055,13 _at__at_
> return -1;
> #endif
> memset(p_jpeg, 0, sizeof(struct jpeg));
> + p_jpeg->len = len;
> #ifdef JPEG_FROM_MEM
> p_jpeg->data = data;
> - p_jpeg->len = len;
> #else
> p_jpeg->fd = fd;
> + if (p_jpeg->len == 0)
> + p_jpeg->len = filesize(p_jpeg->fd);
> #endif
> status = process_markers(p_jpeg);
> #ifndef JPEG_FROM_MEM
> _at__at_ -2212,4 +2230,13 _at__at_
> return 0;
> }
>
> +int read_jpeg_fd(int fd,
> + struct bitmap *bm,
> + int maxsize,
> + int format,
> + const struct custom_format *cformat)
> +{
> + return clip_jpeg_fd(fd, 0, bm, maxsize, format, cformat);
> +}
> +
> /**************** end JPEG code ********************/
>
> Modified: trunk/apps/recorder/jpeg_load.h
> ===================================================================
> --- trunk/apps/recorder/jpeg_load.h 2011-02-09 09:30:09 UTC (rev 29258)
> +++ trunk/apps/recorder/jpeg_load.h 2011-02-09 20:13:13 UTC (rev 29259)
> _at__at_ -44,4 +44,27 _at__at_
> int format,
> const struct custom_format *cformat);
>
> +/**
> + * read embedded jpeg files as above. Needs an offset and length into
> + * the file
> + **/
> +int clip_jpeg_file(const char* filename,
> + int offset,
> + unsigned long jpeg_size,
> + struct bitmap *bm,
> + int maxsize,
> + int format,
> + const struct custom_format *cformat);
> +
> +/**
> + * read embedded jpeg files as above. Needs an open file descripter, and
> + * assumes the caller has lseek()'d to the start of the jpeg blob
> + **/
> +int clip_jpeg_fd(int fd,
> + unsigned long jpeg_size,
> + struct bitmap *bm,
> + int maxsize,
> + int format,
> + const struct custom_format *cformat);
> +
> #endif /* _JPEG_JPEG_DECODER_H */
>
> _______________________________________________
> rockbox-cvs mailing list
> rockbox-cvs_at_cool.haxx.se
> http://cool.haxx.se/cgi-bin/mailman/listinfo/rockbox-cvs
>
Received on 2011-02-09

Page template was last modified "Tue Sep 7 00:00:02 2021" The Rockbox Crew -- Privacy Policy