mirror of
				https://github.com/Rockbox/rockbox.git
				synced 2025-10-26 23:36:37 -04:00 
			
		
		
		
	metadata: mp3: Support unsync embedded jpeg album art
Support parsing alubm art from id3 metadata with "unsynchronisation scheme": https://id3.org/id3v2.3.0#The_unsynchronisation_scheme Change-Id: I1e2ca4ae0aa967f7e80142a04c9a7d99e38e68b2
This commit is contained in:
		
							parent
							
								
									6649731563
								
							
						
					
					
						commit
						7f4a8891a6
					
				
					 7 changed files with 72 additions and 23 deletions
				
			
		|  | @ -867,7 +867,7 @@ static int load_image(int fd, const char *path, | |||
| #ifdef HAVE_JPEG | ||||
|     if (aa != NULL) { | ||||
|         lseek(fd, aa->pos, SEEK_SET); | ||||
|         rc = clip_jpeg_fd(fd, aa->size, bmp, (int)max_size, format, NULL); | ||||
|         rc = clip_jpeg_fd(fd, aa->type, aa->size, bmp, (int)max_size, format, NULL); | ||||
|     } | ||||
|     else if (strcmp(path + strlen(path) - 4, ".bmp")) | ||||
|         rc = read_jpeg_fd(fd, bmp, (int)max_size, format, NULL); | ||||
|  |  | |||
|  | @ -1922,7 +1922,7 @@ static int audio_load_albumart(struct track_info *infop, | |||
|         /* We can only decode jpeg for embedded AA */ | ||||
|         if (global_settings.album_art != AA_OFF && | ||||
|             hid < 0 && hid != ERR_BUFFER_FULL && | ||||
|             track_id3->has_embedded_albumart && track_id3->albumart.type == AA_TYPE_JPG) | ||||
|             track_id3->has_embedded_albumart && (track_id3->albumart.type & AA_CLEAR_FLAGS_MASK) == AA_TYPE_JPG) | ||||
|         { | ||||
|             if (is_current_track) | ||||
|                 clear_last_folder_album_art(); | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ | |||
| * KIND, either express or implied. | ||||
| * | ||||
| ****************************************************************************/ | ||||
| 
 | ||||
| #include "embedded_metadata.h" | ||||
| #include "plugin.h" | ||||
| #include "debug.h" | ||||
| #include "jpeg_load.h" | ||||
|  | @ -79,6 +79,9 @@ struct jpeg | |||
|     int fd; | ||||
|     int buf_left; | ||||
|     int buf_index; | ||||
| 
 | ||||
|     int (*read_buf)(struct jpeg* p_jpeg, size_t count); | ||||
|     void* custom_param; | ||||
| #endif | ||||
|     unsigned long len; | ||||
|     unsigned long int bitbuf; | ||||
|  | @ -872,11 +875,21 @@ INLINE void jpeg_putc(struct jpeg* p_jpeg) | |||
|     p_jpeg->data--; | ||||
| } | ||||
| #else | ||||
| 
 | ||||
| static int read_buf(struct jpeg* p_jpeg, size_t count) | ||||
| { | ||||
|     return read(p_jpeg->fd, p_jpeg->buf, count); | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
| } | ||||
| 
 | ||||
| INLINE void fill_buf(struct jpeg* p_jpeg) | ||||
| { | ||||
|         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_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; | ||||
|  | @ -1958,7 +1971,7 @@ int clip_jpeg_file(const char* filename, | |||
|         return fd * 10 - 1; | ||||
|     } | ||||
|     lseek(fd, offset, SEEK_SET); | ||||
|     ret = clip_jpeg_fd(fd, jpeg_size, bm, maxsize, format, cformat); | ||||
|     ret = clip_jpeg_fd(fd, 0, jpeg_size, bm, maxsize, format, cformat); | ||||
|     close(fd); | ||||
|     return ret; | ||||
| } | ||||
|  | @ -2007,7 +2020,7 @@ int get_jpeg_dim_mem(unsigned char *data, unsigned long len, | |||
| 
 | ||||
| int decode_jpeg_mem(unsigned char *data, | ||||
| #else | ||||
| int clip_jpeg_fd(int fd, | ||||
| int clip_jpeg_fd(int fd, int flags, | ||||
| #endif | ||||
|                  unsigned long len, | ||||
|                  struct bitmap *bm, | ||||
|  | @ -2038,6 +2051,14 @@ int clip_jpeg_fd(int fd, | |||
|     p_jpeg->fd = fd; | ||||
|     if (p_jpeg->len == 0) | ||||
|         p_jpeg->len = filesize(p_jpeg->fd); | ||||
| 
 | ||||
|     p_jpeg->read_buf = read_buf; | ||||
| 
 | ||||
|     if (flags & AA_FLAG_ID3_UNSYNC) | ||||
|     { | ||||
|         p_jpeg->read_buf = read_buf_id3_unsync; | ||||
|         p_jpeg->custom_param = false; | ||||
|     } | ||||
| #endif | ||||
|     status = process_markers(p_jpeg); | ||||
| #ifndef JPEG_FROM_MEM | ||||
|  | @ -2225,7 +2246,7 @@ int read_jpeg_fd(int fd, | |||
|                  int format, | ||||
|                  const struct custom_format *cformat) | ||||
| { | ||||
|     return clip_jpeg_fd(fd, 0, bm, maxsize, format, cformat); | ||||
|     return clip_jpeg_fd(fd, 0, 0, bm, maxsize, format, cformat); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
|  |  | |||
|  | @ -67,7 +67,7 @@ int clip_jpeg_file(const char* filename, | |||
|  * 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, | ||||
| int clip_jpeg_fd(int fd, int flags, | ||||
|                  unsigned long jpeg_size, | ||||
|                  struct bitmap *bm, | ||||
|                  int maxsize, | ||||
|  |  | |||
							
								
								
									
										23
									
								
								lib/rbcodec/metadata/embedded_metadata.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								lib/rbcodec/metadata/embedded_metadata.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | |||
| /***************************************************************************
 | ||||
|  *             __________               __   ___. | ||||
|  *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___ | ||||
|  *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 | ||||
|  *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  < | ||||
|  *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \ | ||||
|  *                     \/            \/     \/    \/            \/ | ||||
|  * $Id$ | ||||
|  * | ||||
|  * Copyright (C) 2024 Roman Artiukhin | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License | ||||
|  * as published by the Free Software Foundation; either version 2 | ||||
|  * of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||||
|  * KIND, either express or implied. | ||||
|  * | ||||
|  ****************************************************************************/ | ||||
| #include <stdbool.h> | ||||
| 
 | ||||
| int id3_unsynchronize(char* tag, int len, bool *ff_found); | ||||
|  | @ -45,6 +45,7 @@ | |||
| #include "mp3data.h" | ||||
| #include "metadata_common.h" | ||||
| #include "metadata_parsers.h" | ||||
| #include "embedded_metadata.h" | ||||
| #include "misc.h" | ||||
| 
 | ||||
| static unsigned long unsync(unsigned long b0, | ||||
|  | @ -161,7 +162,8 @@ struct tag_resolver { | |||
| 
 | ||||
| static bool global_ff_found; | ||||
| 
 | ||||
| static int unsynchronize(char* tag, int len, bool *ff_found) | ||||
| #define unsynchronize id3_unsynchronize | ||||
| int id3_unsynchronize(char* tag, int len, bool *ff_found) | ||||
| { | ||||
|     int i; | ||||
|     unsigned char c; | ||||
|  | @ -299,9 +301,7 @@ static int parsealbumart( struct mp3entry* entry, char* tag, int bufferpos ) | |||
|     if(entry->has_embedded_albumart) | ||||
|         return bufferpos; | ||||
| 
 | ||||
|     /* we currently don't support unsynchronizing albumart */ | ||||
|     if (entry->albumart.type == AA_TYPE_UNSYNC) | ||||
|         return bufferpos; | ||||
|     bool unsync = entry->albumart.type == AA_FLAG_ID3_UNSYNC; | ||||
| 
 | ||||
|     entry->albumart.type = AA_TYPE_UNKNOWN; | ||||
| 
 | ||||
|  | @ -353,6 +353,10 @@ static int parsealbumart( struct mp3entry* entry, char* tag, int bufferpos ) | |||
|         /* fixup offset&size for image data */ | ||||
|         entry->albumart.pos  += tag - start; | ||||
|         entry->albumart.size -= tag - start; | ||||
|         if (unsync) | ||||
|         { | ||||
|             entry->albumart.type |= AA_FLAG_ID3_UNSYNC; | ||||
|         } | ||||
|         /* check for malformed tag with no picture data */ | ||||
|         entry->has_embedded_albumart = (entry->albumart.size != 0); | ||||
|     } | ||||
|  | @ -1142,14 +1146,11 @@ retry_with_limit: | |||
|                     ((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; | ||||
|                     } | ||||
|                     entry->albumart.pos = lseek(fd, 0, SEEK_CUR) - framelen; | ||||
|                     entry->albumart.size = totframelen; | ||||
|                     entry->albumart.type = (unsynch || (global_unsynch && version <= ID3_VER_2_3)) | ||||
|                                            ? AA_FLAG_ID3_UNSYNC | ||||
|                                            : AA_TYPE_UNKNOWN; | ||||
|                 } | ||||
| #endif | ||||
|                 if( tr->ppFunc ) | ||||
|  |  | |||
|  | @ -196,13 +196,17 @@ enum { | |||
|     ID3_VER_2_4 | ||||
| }; | ||||
| 
 | ||||
| #define AA_FLAGS_SHIFT 4 | ||||
| #define AA_CLEAR_FLAGS_MASK ~(-1 << AA_FLAGS_SHIFT) | ||||
| 
 | ||||
| #ifdef HAVE_ALBUMART | ||||
| enum mp3_aa_type { | ||||
|     AA_TYPE_UNSYNC = -1, | ||||
|     AA_TYPE_UNKNOWN, | ||||
|     AA_TYPE_BMP, | ||||
|     AA_TYPE_PNG, | ||||
|     AA_TYPE_JPG, | ||||
| 
 | ||||
|     AA_FLAG_ID3_UNSYNC = 1 << (AA_FLAGS_SHIFT + 0), | ||||
| }; | ||||
| 
 | ||||
| struct mp3_albumart { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue