|
Rockbox mail archiveSubject: Re: kugel: r29259 - in trunk/apps: . metadata recorderRe: 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 |