꿈소년의 개발 이야기

[Android] MP3 id3 tag 깨짐 현상 본문

Android Development

[Android] MP3 id3 tag 깨짐 현상

꿈소년 2010. 7. 9. 12:47
반응형
안드로이드 Music 보면 id3tag 내의 한글 깨짐 현상 수정.

문제 해결
frameworks 소스

한글이 깨지는  mp3의  경우,

id3tag 내의 정보중에서   encoding에 대한 정보가 없고,   한글은  EUC-KR (완성형) 으로 인코딩 되어 있는 경우임.

id3tag 버전이 올라가면서  각 데이타의 encoding정보를 넣을 수 있음
이 인코딩 정보가 제대로 들어간 경우는  제대로 되는데,  없는 경우가 문제임.

mediascanner mp3 파일 해석
id3tag 내의 정보가  UTF-8 이면  그냥 넣고,
ISO-8859-1  (Lantin-1) 이면  그냥  UTF-8 인코딩만 해서 넣음.


그런데,  영문의 경우는   Latin-1 코드나  UTF-8 이나  코드가 같기 때문에  이렇게 넣어도 아무 문제가 없지만,

한 글 완성형은   Unicode가  아닌데,  인코딩 정보가 없으니까 ,  Latin-1  코드인줄 알고,
그냥 UTF-8 방식으로 바꾸어서 그냥 넣어 버리더군요 ㅡ.ㅡ



즉, 이 문제를 해결하기 위해서는   인코딩 정보가 없는 경우의 기본값을  EUC-KR로 해주면 되더군요.

framework의 버그네요.
froyo 도  그대로 버그가 있구요.


그래서  모토로이 확인해 보았더니,  깨지는 파일들 다 잘 나오네요. ㅡ.ㅡ


음  Open Source 라서 가져다  자기들은 고쳐쓰고, 
버그 리포팅은 하지 않나 보네요.

우리나라 대기업도 그렇겠지요. 



ID3Tag 깨지는 원인은   mediascanner 의  버그 인데요.


void MediaScannerClient::endFile()
{

    if (mLocaleEncoding != kEncodingNone) {
        int size = mNames->size();
        uint32_t encoding = kEncodingAll;

        // compute a bit mask containing all possible encodings
        for (int i = 0; i < mNames->size(); i++)
        {
            encoding &= possibleEncodings(mValues->getEntry(i));
        }
           
        // if the locale encoding matches, then assume we have a native encoding.
        if (encoding & mLocaleEncoding)
            convertValues(mLocaleEncoding);

        // finally, push all name/value pairs to the client
        for (int i = 0; i < mNames->size(); i++) {
            if (!handleStringTag(mNames->getEntry(i), mValues->getEntry(i)))
                break;
        }
    }
    // else addStringTag() has done all the work so we have nothing to do

    delete mNames;
    delete mValues;
    mNames = NULL;
    mValues = NULL;
}


위 소스가  버그가 있는 곳입니다.

MediaScanner  소스를 보면,  ID3tag를  파싱하면   UTF-8 이 아닌것들을   mNames가  mValues에  넣어 두었다가
endFile() 함수에서  locale 인코딩이 필요한지를 판별하여   인코딩을 하고 있답니다.

그런데,

        uint32_t encoding = kEncodingAll;

        // compute a bit mask containing all possible encodings
        for (int i = 0; i < mNames->size(); i++)
        {
            encoding &= possibleEncodings(mValues->getEntry(i));
        }

위 코드에서 보면,    우선  전부 인코딩이 가능한 상태로  encoding변수를 넣어두고,
StringArray 에 들어간 각  값들이  인코딩이 가능한 것인지 확인한 후,


인코딩이  가능한 경우라면,  

     if (encoding & mLocaleEncoding)
            convertValues(mLocaleEncoding);

이와 같이 전부 locale 인코딩을  한답니다.



이게 버그인데요.

예들 들어서,  ID3Tag 값중에서   Title 과 Artist는   한글이 있고,  Album 에는  영문만 있다거나 혹은 인코딩이 필요없는 값만 있다면,

첫번째  for 문을 돌면서,   encoding 값이  0로 바뀌게 되고,

그럼, 아래 if 문에서 locale 인코딩을 그냥 건너 뛰게 된답니다.




그러므로,   이 버그의 수정을 위해서는  possibleEncodings() 함수 호출을   mValues 의 각 값에 따라 개별적으로
비교하여   locale 인코딩을  진행하면,

깨지는 것 없이  잘 나오게 된답니다.