mp3 file album art a little Bit of knowledge(2013-04-22 22:40:09) reprinted
Tags: android mp3 id3 cover it |
Category: Android mechanism |
First of all, the MP3 file's album cover data is encoded in the MP3 file ID3, you need to parse ID3 tag when the compressed data from the MP3 file copy out, write to a file.
Removing the data is done in MP3Extractor.cpp SP Mp3extractor::getmetadata () {size_t datasize; String8 MIME; const void *data = Id3.getalbumart (&datasize, &mime); if (data) {Meta->setdata (Kkeyalbumart, Metadata::type_none, data, datasize); Meta->setcstring (Kkeyalbumartmime, mime.string ()); } return meta; }
As the above code, get to the cover picture in the file of the first address, size and MIME type, with the first two information, you can directly take out. This information is stored directly in the Meta Kkeyalbumart key-value pair, which is used for later removal.
In StagefrightMetadataRetriever.cpp, the GetMetaData function of each extractor is called in its parsemetadata function, and the MP3 function is called above for the GetMetaData file. In the Parsemetadata function, the first address and length of the cover page resolved in the GetMetaData function are copied from the file and saved in memory. void Stagefrightmetadataretriever::p arsemetadata () {const void *data; uint32_t type; size_t DataSize; if (Meta->finddata (Kkeyalbumart, &type, &data, &datasize) && Malbumart = = NULL) {m Albumart = new Mediaalbumart; Malbumart->msize = datasize; Malbumart->mdata = new Uint8_t[datasize]; memcpy (malbumart->mdata, data, datasize); } }
In Stagefrightmetadataretriever's Extractalbumart function, the in-memory cover page data is assigned to the Mediaalbumart object Mediaalbumart * Stagefrightmetadataretriever::extractalbumart () {ALOGV ("Extractalbumart (Extractor:%s)", Mextractor.get ()! = NULL? "YES": "NO"); if (Mextractor = = null) {return null; } if (!mparsedmetadata) {parsemetadata (); Mparsedmetadata = true; } if (Malbumart) {return new Mediaalbumart (*malbumart); A simple buffer to hold binary data} return NULL; }
The Extractalbumart function of Stagefrightmetadataretriever is called All the way by MediaScanner.cpp JNI mediascanner.java de native function. Public native byte[] Extractalbumart (FileDescriptor FD);
Finally, it should be called in the Mediaprovider.java, when the call passed a file fd, this file is the final cover picture data written to the place.
Skip Mediaprovider
Eventually this file will be saved under the/sdcard/android/data/com.android.provider.media/albumthumbnail/path.
So how does MP3 relate to the relative cover?
All MP3 are scanned into the audio table in the Mediaprovider database, which has a field of album_id, which corresponds to the primary key of another table Album_info in the database.
The absolute path of each cover file is recorded in the Album_info table, so any MP3 song can find the corresponding cover file by album_id value, and extracting the decoding generates a bitmap that can be used to display it.
Here you can refer to the following function of the Musicutils.java class in Google music. Get album art for specified album. This method would not try fall back to getting artwork directly from the file, nor would it attempt to Repa IR the database. private static Bitmap Getartworkquick (context context, long album_id, int w, int h) { note:th Ere is in fact a 1 pixel border on the right side in the ImageView used to display this drawable. Take it into the account now, so we don't have the to scale later. W-= 1; Contentresolver res = Context.getcontentresolver (); URI uri = Contenturis.withappendedid (Sartworkuri, album_id); if (uri! = null) { Parcelfiledescriptor FD = null; & nbsp try { FD = Res.openfiledescriptor (URI, "R"); &NBSP int samplesize = 1; Compute the closest Powe R-of-two scale factor and pass this to Sbitmapoptionscache.insamplesize, Which result in faster decoding and better quality &NB Sp sbitmapoptionscache.injustdecodebounds = true; Bitmapfactory.decodefiledescriptor ( &N Bsp fd.getfiledescriptor (), NULL, Sbitmapoptionscache); int nextwidth = sbitmapoptionscache.outwidth >> 1; int nextheight = sbitmapoptionscache.outheight >> 1; while (Nextwidth>w && NextheigHt>h) { samplesize <<= 1 &NB Sp Nextwidth >>= 1; Nextheight >>= 1; }
Sbitmapoptionscache.insamplesize = samplesize; Sbitmapoptionscache.injustdecodebounds = false; Bitmap B = Bitmapfactory.decodefiledescriptor (Fd.getfiledescriptor (), NULL, Sbitmapoptionscache);
if (b! = null) { finally rescale to exactly the size we need if (sBi Tmapoptionscache.outwidth! = W | | Sbitmapoptionscache.outheight! = h) { BITMAP TMP = Bitmap.createscaledbitmap (b, W, H, true); Bitmap.createscaledbitmap () can return the SA Me bitmap if (tmp! = b) b.recycle (); B = tmp; } } return B; } catch (FileNotFoundException e) { } finally { &NB Sp try { if (FD! = null) &N Bsp fd.close (); } catch (IOException e) { &NBSP ; } } } return null; }