Home | History | Annotate | Download | only in src
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 /**
     19 * @file pv_id3_parcom_types.cpp
     20 * @brief Type definitions for ID3 Parser-Composer
     21 */
     22 
     23 #ifndef PV_ID3_PARCOM_H_INCLUDED
     24 #include "pv_id3_parcom.h"
     25 #endif
     26 #ifndef PV_ID3_PARCOM_CONSTANTS_H_INCLUDED
     27 #include "pv_id3_parcom_constants.h"
     28 #endif
     29 #ifndef OSCL_SNPRINTF_H_INCLUDED
     30 #include "oscl_snprintf.h"
     31 #endif
     32 #ifndef PVLOGGER_H_INCLUDED
     33 #include "pvlogger.h"
     34 #endif
     35 #ifndef PVMI_KVP_UTIL_H_INCLUDED
     36 #include "pvmi_kvp_util.h"
     37 #endif
     38 #ifndef OSCL_MIME_STRING_UTILS_H
     39 #include "pv_mime_string_utils.h"
     40 #endif
     41 #ifndef OSCL_DLL_H_INCLUDED
     42 #include "oscl_dll.h"
     43 #endif
     44 #ifndef WCHAR_SIZE_UTILS_H_INCLUDED
     45 #include "wchar_size_utils.h"
     46 #endif
     47 
     48 #define LOG_STACK_TRACE(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, m);
     49 #define LOG_DEBUG(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, m);
     50 #define LOG_ERR(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_ERR,m);
     51 
     52 #ifndef NULL_TERM_CHAR
     53 #define NULL_TERM_CHAR '\0'
     54 #endif
     55 
     56 // DLL entry point
     57 OSCL_DLL_ENTRY_POINT_DEFAULT()
     58 
     59 ////////////////////////////////////////////////////////////////////////////
     60 class PVID3ParComKvpCleanupDA : public OsclDestructDealloc
     61 {
     62     public:
     63         PVID3ParComKvpCleanupDA(Oscl_DefAlloc* in_gen_alloc) :
     64                 gen_alloc(in_gen_alloc) {};
     65         virtual ~PVID3ParComKvpCleanupDA() {};
     66 
     67         virtual void destruct_and_dealloc(OsclAny* ptr)
     68         {
     69             // no need to call destructors in this case just dealloc
     70             gen_alloc->deallocate(ptr);
     71         }
     72 
     73     private:
     74         Oscl_DefAlloc* gen_alloc;
     75 };
     76 
     77 ////////////////////////////////////////////////////////////////////////////
     78 OSCL_EXPORT_REF PVID3ParCom::PVID3ParCom()
     79         : iInputFile(NULL),
     80         iTitleFoundFlag(false),
     81         iArtistFoundFlag(false),
     82         iAlbumFoundFlag(false),
     83         iYearFoundFlag(false),
     84         iCommentFoundFlag(false),
     85         iTrackNumberFoundFlag(false),
     86         iGenereFoundFlag(false),
     87         iFileSizeInBytes(0),
     88         iByteOffsetToStartOfAudioFrames(0),
     89         iID3V1Present(false),
     90         iID3V2Present(false),
     91         iVersion(PV_ID3_INVALID_VERSION),
     92         iUseMaxTagSize(false),
     93         iMaxTagSize(0),
     94         iUsePadding(false),
     95         iTagAtBof(false),
     96         iSeekFrameFound(false)
     97 {
     98     iLogger = PVLogger::GetLoggerObject("PVID3ParCom");
     99     iID3TagInfo.iID3V2ExtendedHeaderSize = 0;
    100     iID3TagInfo.iID3V2FrameSize = 0;
    101     iID3TagInfo.iID3V2TagFlagsV2 = 0;
    102     iID3TagInfo.iID3V2TagSize = 0 ;
    103     iID3TagInfo.iFooterPresent = false;
    104 
    105     oscl_memset(&iID3TagInfo.iID3V2FrameFlag, 0, sizeof(iID3TagInfo.iID3V2FrameFlag));
    106 
    107 }
    108 
    109 ////////////////////////////////////////////////////////////////////////////
    110 OSCL_EXPORT_REF PVID3ParCom::~PVID3ParCom()
    111 {
    112     iFrames.clear();
    113 }
    114 
    115 ////////////////////////////////////////////////////////////////////////////
    116 OSCL_EXPORT_REF uint32 PVID3ParCom::GetID3TagSize(PVFile* aFile)
    117 {
    118     if (!aFile)
    119     {
    120         return 0;
    121     }
    122 
    123     iInputFile = aFile;
    124 
    125     if (iInputFile->Seek(0, Oscl_File::SEEKSET) == -1)
    126     {
    127         iFileSizeInBytes = 0;
    128     }
    129     else
    130     {
    131         iInputFile->GetRemainingBytes((uint32&)iFileSizeInBytes);
    132         if (iInputFile->Seek(0, Oscl_File::SEEKSET) == -1)
    133         {
    134             return 0;
    135         }
    136     }
    137 
    138     uint32 buffsize = 100; //number of bytes to search , from the end of file, to look for footer
    139     if (CheckForTagID3V2()
    140             || (LookForV2_4Footer(buffsize, 0) == PVMFSuccess))
    141     {
    142         if (iInputFile->Seek(2, Oscl_File::SEEKCUR) == -1)
    143         {
    144             return 0;
    145         }
    146 
    147         // Read and convert tag flags
    148         uint8 flags = 0;
    149         if (read8(iInputFile, flags) == false)
    150         {
    151             return 0;
    152         }
    153 
    154         // Read and convert tag size
    155         uint32 synchIntTagSize;
    156         if (read32(iInputFile, synchIntTagSize) == false)
    157         {
    158             return 0;
    159         }
    160 
    161         // tagSize will store the file's Id3v2 tag size
    162         uint32 tagSize = SafeSynchIntToInt32(synchIntTagSize) + ID3V2_TAG_NUM_BYTES_HEADER;
    163 
    164         //check if footer is present
    165         if ((iVersion == PV_ID3_V2_4) && (flags & FTR_FLAGMASK))
    166             tagSize += ID3V2_TAG_NUM_BYTES_HEADER; // add 10 bytes for footer
    167 
    168         return tagSize;
    169     }
    170     else
    171     {
    172         if (CheckForTagID3V1())
    173         {
    174             return ID3V1_MAX_NUM_BYTES_TOTAL;
    175         }
    176     }
    177     return 0;
    178 }
    179 
    180 ////////////////////////////////////////////////////////////////////////////
    181 OSCL_EXPORT_REF uint32 PVID3ParCom::GetID3TagSize()
    182 {
    183     uint32 composedTagSize = 0;
    184     switch (iVersion)
    185     {
    186         case PV_ID3_V2_2:
    187         case PV_ID3_V2_3:
    188         case PV_ID3_V2_4:
    189         {
    190             composedTagSize = ID3V2_TAG_NUM_BYTES_HEADER + iID3TagInfo.iID3V2TagSize;
    191 
    192             if (iID3TagInfo.iFooterPresent)
    193                 composedTagSize += ID3V2_TAG_NUM_BYTES_HEADER; //footer is replica of Tag Header
    194         }
    195         break;
    196 
    197         case PV_ID3_V1:
    198         case PV_ID3_V1_1:
    199             composedTagSize =  128; // ID3v1 tag has fix size
    200             break;
    201         default:
    202             composedTagSize = 0;
    203 
    204     }
    205 
    206     return composedTagSize;
    207 }
    208 
    209 ////////////////////////////////////////////////////////////////////////////
    210 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::SetMaxID3TagSize(bool aUseMaxSize, uint32 aMaxSize, bool aUsePadding)
    211 {
    212     switch (iVersion)
    213     {
    214         case PV_ID3_V1:
    215         case PV_ID3_V1_1:
    216         case PV_ID3_INVALID_VERSION:
    217         {
    218             LOG_ERR((0, "PVID3Parcom::SetMaxID3TagSize: Error - Fix size ID3 tag"));
    219             return PVMFErrNotSupported;
    220         }
    221         case PV_ID3_V2_2:
    222             // Minimum for an ID3v2_2 tag is tag header plus 1 frame.  The minimum data length of
    223             // a frame is 1 byte
    224         {
    225             if (aUseMaxSize && aMaxSize < (ID3V2_TAG_NUM_BYTES_HEADER + ID3V2_2_FRAME_NUM_BYTES_HEADER + 1))
    226             {
    227                 LOG_ERR((0, "PVID3ParCom::SetMaxID3TagSize: Error - Minimum tag size is 17 bytes"));
    228                 return PVMFErrArgument;
    229             }
    230         }
    231         break;
    232         case PV_ID3_V2_3:
    233         case PV_ID3_V2_4:
    234             // Minimum for an ID3v2 tag is tag header plus 1 frame.  The minimum data length of
    235             // a frame is 1 byte
    236             if (aUseMaxSize && aMaxSize < (ID3V2_TAG_NUM_BYTES_HEADER + ID3V2_FRAME_NUM_BYTES_HEADER + 1))
    237             {
    238                 LOG_ERR((0, "PVID3ParCom::SetMaxID3TagSize: Error - Minimum tag size is 21 bytes"));
    239                 return PVMFErrArgument;
    240             }
    241     }
    242 
    243     iUseMaxTagSize = aUseMaxSize;
    244     if (iUseMaxTagSize)
    245     {
    246         iMaxTagSize = aMaxSize;
    247         iUsePadding = aUsePadding;
    248     }
    249     else
    250     {
    251         iMaxTagSize = 0;
    252         iUsePadding = false;
    253     }
    254 
    255     return PVMFSuccess;
    256 }
    257 
    258 ////////////////////////////////////////////////////////////////////////////
    259 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::ParseID3Tag(PVFile* aFile, uint32 buffsize)
    260 {
    261     if (!aFile)
    262     {
    263         return PVMFFailure;
    264     }
    265 
    266     iInputFile = aFile;
    267 
    268     int32 currentFilePosn = 0;
    269 
    270     // SEEK TO THE END OF THE FILE AND GET FILE SIZE
    271     currentFilePosn = iInputFile->Tell();
    272     if (currentFilePosn == -1)
    273     {
    274         return PVMFFailure;
    275     }
    276 
    277     if (iInputFile->Seek(0, Oscl_File::SEEKSET) == -1)
    278     {
    279         iFileSizeInBytes = 0;
    280     }
    281     else
    282     {
    283         iInputFile->GetRemainingBytes((uint32&)iFileSizeInBytes);
    284         if (iInputFile->Seek(currentFilePosn, Oscl_File::SEEKSET) == -1)
    285         {
    286             iInputFile = NULL;
    287             return PVMFFailure;
    288         }
    289     }
    290 
    291     bool readTags = false;
    292     //check for ID3 Version 2
    293     if (CheckForTagID3V2() || (LookForV2_4Footer(buffsize, 0) == PVMFSuccess))
    294     {
    295         //Read the header
    296         readTags = ReadHeaderID3V2();
    297 
    298         //check for ID3 Version 1
    299         if (CheckForTagID3V1())
    300         {
    301             iVersion = PV_ID3_V1;
    302             ReadID3V1Tag();
    303         }
    304         if (iInputFile->Seek(currentFilePosn, Oscl_File::SEEKSET) == -1)
    305         {
    306             iInputFile = NULL;
    307             return PVMFFailure;
    308         }
    309     }
    310     else if (!readTags && CheckForTagID3V1())
    311     {
    312         //check for ID3 Version 1
    313         iVersion = PV_ID3_V1;
    314         //Read the header
    315         ReadID3V1Tag();
    316 
    317         iByteOffsetToStartOfAudioFrames = 0;
    318         if (iInputFile->Seek(currentFilePosn, Oscl_File::SEEKSET) == -1)
    319         {
    320             iInputFile = NULL;
    321             return PVMFFailure;
    322         }
    323     }
    324     else
    325     {
    326         return PVMFFailure;
    327     }
    328 
    329     iInputFile = NULL;
    330     return PVMFSuccess;
    331 }
    332 
    333 ////////////////////////////////////////////////////////////////////////////
    334 OSCL_EXPORT_REF PVID3Version PVID3ParCom::GetID3Version() const
    335 {
    336     return iVersion;
    337 }
    338 
    339 ////////////////////////////////////////////////////////////////////////////
    340 OSCL_EXPORT_REF bool PVID3ParCom::IsID3V1Present() const
    341 {
    342     return iID3V1Present;
    343 }
    344 
    345 ////////////////////////////////////////////////////////////////////////////
    346 OSCL_EXPORT_REF bool PVID3ParCom::IsID3V2Present() const
    347 {
    348     return iID3V2Present;
    349 }
    350 
    351 ////////////////////////////////////////////////////////////////////////////
    352 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::GetID3Frames(PvmiKvpSharedPtrVector& aFrames)
    353 {
    354     aFrames = iFrames;
    355     return PVMFSuccess;
    356 }
    357 
    358 ////////////////////////////////////////////////////////////////////////////
    359 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::GetID3Frame(const OSCL_String& aFrameType, PvmiKvpSharedPtrVector& aFrameVector)
    360 {
    361     uint32 i;
    362     for (i = 0; i < iFrames.size(); i++)
    363     {
    364         if (pv_mime_strcmp(iFrames[i]->key, aFrameType.get_str()) == 0)
    365         {
    366             return PushFrameToFrameVector(iFrames[i], aFrameVector);
    367         }
    368     }
    369 
    370     return PVMFSuccess;
    371 }
    372 
    373 ////////////////////////////////////////////////////////////////////////////
    374 OSCL_EXPORT_REF bool PVID3ParCom::IsID3FrameAvailable(const OSCL_String& aFrameType)
    375 {
    376     uint32 i;
    377     for (i = 0; i < iFrames.size(); i++)
    378     {
    379         if (pv_mime_strcmp(iFrames[i]->key, aFrameType.get_str()) == 0)
    380         {
    381             return true;
    382         }
    383     }
    384 
    385     return false;
    386 }
    387 
    388 ////////////////////////////////////////////////////////////////////////////
    389 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::SetID3Version(PVID3Version aVersion)
    390 {
    391     iVersion = aVersion;
    392     return PVMFSuccess;
    393 }
    394 
    395 ////////////////////////////////////////////////////////////////////////////
    396 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::SetID3Frame(const PvmiKvp& aFrame)
    397 {
    398     uint32 i;
    399     OSCL_StackString<4> frameID;
    400     PVID3FrameType newFrameType;
    401     PVID3FrameType existingFrameType;
    402     PVMFStatus status = PVMFSuccess;
    403 
    404     // Find an existing entry in iFrames with matching frame type
    405     status = GetFrameTypeFromKvp(aFrame, frameID, newFrameType);
    406     for (i = 0; status == PVMFSuccess && i < iFrames.size(); i++)
    407     {
    408         status = GetFrameTypeFromKvp(iFrames[i], frameID, existingFrameType);
    409         if (status != PVMFSuccess)
    410         {
    411             LOG_ERR((0, "PVID3ParCom::SetID3Frame: Error - GetFrameTypeFromKvp failed"));
    412             break;
    413         }
    414         if (existingFrameType == newFrameType)
    415         {
    416             iFrames.erase(iFrames.begin() + i);
    417             break;
    418         }
    419 
    420     }
    421 
    422     if (status != PVMFSuccess)
    423     {
    424         return status;
    425     }
    426 
    427     PvmiKvpValueType kvpValueType = GetValTypeFromKeyString(aFrame.key);
    428     OSCL_StackString<128> key = _STRLIT_CHAR(aFrame.key);
    429     uint32 valueSize = 0;
    430     uint32 valueStrLen = 0;
    431     switch (kvpValueType)
    432     {
    433         case PVMI_KVPVALTYPE_CHARPTR:
    434             valueStrLen = oscl_strlen(aFrame.value.pChar_value);
    435             valueSize = valueStrLen + 1;
    436             break;
    437         case PVMI_KVPVALTYPE_WCHARPTR:
    438             valueStrLen = oscl_strlen(aFrame.value.pWChar_value);
    439             valueSize = (valueStrLen + 2) * sizeof(oscl_wchar);
    440             break;
    441         case PVMI_KVPVALTYPE_KSV:
    442             // Comment field
    443             break;
    444         case PVMI_KVPVALTYPE_UINT32:
    445             valueSize = 0;
    446             break;
    447         default:
    448             return PVMFErrNotSupported;
    449     }
    450 
    451     status = PVMFSuccess;
    452     PvmiKvpSharedPtr kvp;
    453     bool truncate = false;
    454     kvp = HandleErrorForKVPAllocation(key, kvpValueType, valueSize, truncate, status);
    455 
    456     if (truncate || (PVMFSuccess != status) || !kvp)
    457     {
    458         return PVMFErrNoMemory;
    459     }
    460 
    461     switch (kvpValueType)
    462     {
    463         case PVMI_KVPVALTYPE_CHARPTR:
    464             oscl_strncpy(kvp->value.pChar_value, aFrame.value.pChar_value, valueStrLen);
    465             kvp->value.pChar_value[valueStrLen] = NULL_TERM_CHAR;
    466             break;
    467         case PVMI_KVPVALTYPE_WCHARPTR:
    468             oscl_strncpy(kvp->value.pWChar_value, aFrame.value.pWChar_value, valueStrLen);
    469             kvp->value.pWChar_value[valueStrLen] = NULL_TERM_CHAR;
    470             break;
    471         case PVMI_KVPVALTYPE_UINT32:
    472             kvp->value.uint32_value = aFrame.value.uint32_value;
    473             break;
    474         case PVMI_KVPVALTYPE_KSV:
    475             // comment field
    476         default:
    477             return PVMFErrNotSupported;
    478     }
    479 
    480 
    481     if (PVMFSuccess != PushFrameToFrameVector(kvp, iFrames))
    482     {
    483         return PVMFErrNoMemory;
    484     }
    485     return PVMFSuccess;
    486 }
    487 
    488 ////////////////////////////////////////////////////////////////////////////
    489 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::RemoveID3Frame(const OSCL_String& aFrameType)
    490 {
    491     uint32 i;
    492     for (i = 0; i < iFrames.size(); i++)
    493     {
    494         if (pv_mime_strcmp(iFrames[i]->key, aFrameType.get_str()) == 0)
    495         {
    496             iFrames.erase(iFrames.begin() + i);
    497             return PVMFSuccess;
    498         }
    499     }
    500 
    501     // Frame of specified type is not found
    502     return PVMFErrArgument;
    503 }
    504 
    505 ////////////////////////////////////////////////////////////////////////////
    506 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::ComposeID3Tag(OsclRefCounterMemFrag& aTag)
    507 {
    508     switch (iVersion)
    509     {
    510         case PV_ID3_V2_2:
    511         case PV_ID3_V2_3:
    512         case PV_ID3_V2_4:
    513             return ComposeID3v2Tag(aTag);
    514         default:
    515             return PVMFErrNotSupported;
    516     }
    517 }
    518 
    519 ////////////////////////////////////////////////////////////////////////////
    520 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::Reset()
    521 {
    522     iFrames.clear();
    523     return PVMFSuccess;
    524 }
    525 
    526 ////////////////////////////////////////////////////////////////////////////
    527 bool PVID3ParCom::CheckForTagID3V1()
    528 {
    529     uint8 tagHeader[ID3V1_TAG_NUM_BYTES_HEADER+1] = {0};
    530 
    531     // Make sure file is big enough to contain a tag
    532     if (iFileSizeInBytes >= ID3V1_MAX_NUM_BYTES_TOTAL)
    533     {
    534         uint32 nBytes = 0;
    535         // Read the value at the tag position
    536 
    537         nBytes = iFileSizeInBytes - ID3V1_MAX_NUM_BYTES_TOTAL;
    538         if (iInputFile->Seek(nBytes, Oscl_File::SEEKSET) == -1)
    539         {
    540             return false;
    541         }
    542 
    543 
    544         if (!readByteData(iInputFile, ID3V1_TAG_NUM_BYTES_HEADER, tagHeader))
    545         {
    546             return false;
    547         }
    548 
    549         // Read in ID3 Tags at the front of the file.
    550         if (oscl_memcmp(ID3_V1_IDENTIFIER, tagHeader, ID3V1_TAG_NUM_BYTES_HEADER) == 0)
    551         {
    552             iID3V1Present = true;
    553             return true;
    554         }
    555     }
    556     return false;
    557 }
    558 
    559 ////////////////////////////////////////////////////////////////////////////
    560 bool PVID3ParCom::CheckForTagID3V2()
    561 {
    562     uint8 id3Header[ID3V2_TAG_NUM_BYTES_HEADER+1] = {0};
    563 
    564     if (!readByteData(iInputFile, ID3V2_TAG_NUM_BYTES_ID, id3Header))
    565     {
    566         return false;
    567     }
    568 
    569     // Read in ID3 Tags at the front of the file.
    570     if (oscl_memcmp(ID3_V2_IDENTIFIER, id3Header, ID3V2_TAG_NUM_BYTES_ID) == 0)
    571     {
    572         iTagAtBof = true;
    573         iID3V2Present = true;
    574         return true;
    575     }
    576     return false;
    577 }
    578 
    579 OSCL_EXPORT_REF bool PVID3ParCom::IsID3V2Present(PVFile* aFile, uint32& aTagSize)
    580 {
    581     iInputFile = aFile;
    582     if (iID3V2Present)
    583     {
    584         // if id3 tag has already been discovered, just return the tag size
    585         aTagSize = iByteOffsetToStartOfAudioFrames;
    586         return true;
    587     }
    588 
    589     if (CheckForTagID3V2())
    590     {
    591         // we dont want to parse the id3 frames, just read the id3 header
    592 
    593         ReadHeaderID3V2(false);
    594         aTagSize = iByteOffsetToStartOfAudioFrames;
    595         return true;
    596     }
    597     return false;
    598 }
    599 
    600 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::LookForV2_4Footer(uint32 aBuffSz, uint32 aFileOffset)
    601 {
    602     if (iTagAtBof)  //already found tag. no need to search from the end.
    603         return PVMFFailure;
    604 
    605     uint32 footer_location = SearchTagV2_4(aBuffSz, aFileOffset);
    606 
    607     if (footer_location == 0)
    608         return PVMFFailure;
    609 
    610     if (iInputFile->Seek(footer_location  + ID3V2_TAG_NUM_BYTES_ID + ID3V2_TAG_NUM_BYTES_VERSION + ID3V2_TAG_NUM_BYTES_FLAG,
    611                          Oscl_File::SEEKSET) == -1)
    612     {
    613         return PVMFFailure;
    614     }
    615 
    616     uint32 tag_size = 0, size = 0;
    617 
    618     if (read32(iInputFile, size) == false)
    619     {
    620         return PVMFFailure;
    621     }
    622 
    623     tag_size = SafeSynchIntToInt32(size);
    624 
    625     if (iInputFile->Seek(-(int32)(tag_size + ID3V2_TAG_NUM_BYTES_HEADER + (ID3V2_TAG_NUM_BYTES_HEADER - ID3V2_TAG_NUM_BYTES_ID)),
    626                          Oscl_File::SEEKCUR) == -1)
    627     {
    628         return PVMFFailure;
    629     }
    630 
    631     return PVMFSuccess;
    632 }
    633 ////////////////////////////////////////////////////////////////////////////
    634 // (if an error is detected, this returns 0)
    635 
    636 uint32 PVID3ParCom::SearchTagV2_4(uint32 aBuffSz, uint32 aFileOffset)
    637 {
    638 
    639     if (iFileSizeInBytes == 0)
    640         return 0;
    641 
    642     uint8 *buff = (uint8 *)oscl_malloc(aBuffSz);
    643     if (! buff)     // malloc might fail
    644         return 0;
    645 
    646     int remaining_bytes = 0;
    647 
    648     int num_bytes_read = aBuffSz + aFileOffset;
    649 
    650     //in case we have almost reached to the begining of file,
    651     //and remaining bytes are less than the buffer size,
    652     //look for ID3 tag in the remaining bytes only.
    653 
    654     if (num_bytes_read > iFileSizeInBytes)
    655         remaining_bytes = iFileSizeInBytes - (num_bytes_read - aBuffSz);
    656 
    657     if (remaining_bytes > 0)
    658     {
    659 
    660         if (iInputFile->Seek(0 , Oscl_File::SEEKSET) == -1)
    661         {
    662             oscl_free(buff);
    663             return 0;
    664         }
    665 
    666         if (readByteData(iInputFile, remaining_bytes, buff) == false)
    667         {
    668             oscl_free(buff);
    669             return 0;
    670         }
    671 
    672         for (int i = 0; i < remaining_bytes; i++)
    673         {
    674             if (oscl_memcmp(buff + i, ID3_V2_4_TAG_FOOTER, ID3V2_TAG_NUM_BYTES_ID) == 0)
    675             {
    676                 oscl_free(buff);
    677                 return i;
    678             }
    679 
    680         }
    681 
    682         oscl_free(buff);
    683         return 0;
    684     }
    685     else
    686     {
    687 
    688         if (iInputFile->Seek((iFileSizeInBytes - (aFileOffset + aBuffSz)), Oscl_File::SEEKSET) == -1)
    689         {
    690             oscl_free(buff);
    691             return 0;
    692         }
    693 
    694         if (readByteData(iInputFile, aBuffSz, buff) == false)
    695         {
    696             oscl_free(buff);
    697             return 0;
    698         }
    699 
    700         for (uint i = 0; i < aBuffSz; i++)
    701         {
    702             if (oscl_memcmp(buff + i, ID3_V2_4_TAG_FOOTER, ID3V2_TAG_NUM_BYTES_ID) == 0)
    703             {
    704                 oscl_free(buff);
    705                 return ((iFileSizeInBytes - ((aFileOffset + aBuffSz) - i)));
    706             }
    707 
    708         }
    709 
    710     }
    711 
    712     oscl_free(buff);
    713     return 0;
    714 }
    715 
    716 ////////////////////////////////////////////////////////////////////////////
    717 void PVID3ParCom::ReadID3V1Tag(void)
    718 {
    719 
    720     PVMFStatus status = PVMFSuccess;
    721     bool truncate = false;
    722 
    723     if (!iTitleFoundFlag)
    724     {
    725         //Title
    726         status = ReadStringValueFrame(PV_ID3_FRAME_TITLE, PV_ID3_CHARSET_ISO88591, ID3V1_MAX_NUM_BYTES_TITLE);
    727         if (status != PVMFSuccess)
    728         {
    729             LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error = ReadStringValueFrame failed for title"));
    730             OSCL_LEAVE(OsclErrGeneral);
    731         }
    732         iTitleFoundFlag = true;
    733     }
    734     else
    735     {
    736 
    737         if (iInputFile->Seek(ID3V1_MAX_NUM_BYTES_TITLE, Oscl_File::SEEKCUR) == -1)
    738         {
    739             return;
    740         }
    741 
    742     }
    743     if (!iArtistFoundFlag)
    744     {
    745         //Artist
    746         status = ReadStringValueFrame(PV_ID3_FRAME_ARTIST, PV_ID3_CHARSET_ISO88591, ID3V1_MAX_NUM_BYTES_ARTIST);
    747         if (status != PVMFSuccess)
    748         {
    749             LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error = ReadStringValueFrame failed for artist"));
    750             OSCL_LEAVE(OsclErrGeneral);
    751         }
    752         iArtistFoundFlag = true;
    753     }
    754     else
    755     {
    756         if (iInputFile->Seek(ID3V1_MAX_NUM_BYTES_ARTIST, Oscl_File::SEEKCUR) == -1)
    757         {
    758             return;
    759         }
    760     }
    761 
    762     if (!iAlbumFoundFlag)
    763     {
    764         // Album
    765         status = ReadStringValueFrame(PV_ID3_FRAME_ALBUM, PV_ID3_CHARSET_ISO88591, ID3V1_MAX_NUM_BYTES_ALBUM);
    766         if (status != PVMFSuccess)
    767         {
    768             LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error = ReadStringValueFrame failed for album"));
    769             OSCL_LEAVE(OsclErrGeneral);
    770         }
    771         iAlbumFoundFlag = true;
    772     }
    773     else
    774     {
    775         if (iInputFile->Seek(ID3V1_MAX_NUM_BYTES_ALBUM, Oscl_File::SEEKCUR) == -1)
    776         {
    777             return;
    778         }
    779     }
    780 
    781     if (!iYearFoundFlag)
    782     {
    783         //Year
    784         status = ReadStringValueFrame(PV_ID3_FRAME_YEAR, PV_ID3_CHARSET_ISO88591, ID3V1_MAX_NUM_BYTES_YEAR);
    785         if (status != PVMFSuccess)
    786         {
    787             LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error = ReadStringValueFrame failed for year"));
    788             OSCL_LEAVE(OsclErrGeneral);
    789         }
    790         iYearFoundFlag = true;
    791     }
    792     else
    793     {
    794         if (iInputFile->Seek(ID3V1_MAX_NUM_BYTES_YEAR, Oscl_File::SEEKCUR) == -1)
    795         {
    796             return;
    797         }
    798     }
    799     OSCL_StackString<128> keyStr;
    800     PvmiKvpSharedPtr kvpPtr;
    801     uint8* frameData = NULL;
    802 
    803     if (!iCommentFoundFlag   || !iTrackNumberFoundFlag)
    804     {
    805         frameData = NULL;
    806         //Comment or Track Number
    807         // Read and convert comment & track number
    808         uint32 frameDataSize = ID3V1_MAX_NUM_BYTES_FIELD_SIZE + 1;
    809         int32 err = OsclErrNone;
    810         frameData = (uint8*) AllocateValueArray(err, PVMI_KVPVALTYPE_UINT8PTR, frameDataSize, &iAlloc);
    811         if (OsclErrNone != err || !frameData)
    812         {
    813             LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - Out of memory"));
    814             OSCL_LEAVE(OsclErrNoMemory);
    815         }
    816         oscl_memset(frameData, 0, frameDataSize);
    817 
    818         if (readByteData(iInputFile, ID3V1_MAX_NUM_BYTES_COMMENT, frameData) == false)
    819         {
    820             iAlloc.deallocate(frameData);
    821             LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - readByteData failed"));
    822             OSCL_LEAVE(OsclErrGeneral);
    823         }
    824 
    825 
    826         if (frameData[ID3V1_MAX_NUM_BYTES_COMMENT-2] == 0 &&
    827                 frameData[ID3V1_MAX_NUM_BYTES_COMMENT-1] != 0)
    828         {
    829             if (!iTrackNumberFoundFlag)
    830             {
    831                 // This would mean its an ID3v1.1 tag and hence has the
    832                 // the track number also, so extract it
    833                 iVersion = PV_ID3_V1_1;
    834 
    835                 if (ConstructKvpKey(keyStr, PV_ID3_FRAME_TRACK_NUMBER, PV_ID3_CHARSET_INVALID) != PVMFSuccess)
    836                 {
    837                     iAlloc.deallocate(frameData);
    838                     LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - ConstructKvpKey failed for tracknumber"));
    839                     OSCL_LEAVE(OsclErrNotSupported);
    840                 }
    841 
    842                 // Allocate key-value pair
    843                 OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_UINT32, 1, truncate););
    844                 if (OsclErrNone != err || !kvpPtr)
    845                 {
    846                     LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - AllocateKvp failed. err=%d", err));
    847                     iAlloc.deallocate(frameData);
    848                     OSCL_LEAVE(OsclErrNoMemory);
    849                     return;
    850                 }
    851 
    852                 if (!truncate)
    853                 {
    854                     kvpPtr->value.uint32_value = (uint32)frameData[ID3V1_MAX_NUM_BYTES_COMMENT - 1];
    855                 }
    856                 OSCL_TRY(err, iFrames.push_back(kvpPtr););
    857                 OSCL_FIRST_CATCH_ANY(err,
    858                                      LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - iFrame.push_back failed"));
    859                                      iAlloc.deallocate(frameData);
    860                                      OSCL_LEAVE(OsclErrNoMemory);
    861                                      return;
    862                                     );
    863                 iTrackNumberFoundFlag = true;
    864             }
    865         }
    866         if (!iCommentFoundFlag)
    867         {
    868 
    869             // Comment frame
    870             frameData[ID3V1_MAX_NUM_BYTES_COMMENT] = 0;
    871             if (ConstructKvpKey(keyStr, PV_ID3_FRAME_COMMENT, PV_ID3_CHARSET_ISO88591) != PVMFSuccess)
    872             {
    873                 LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - ConstructKvpKey failed for tracknumber"));
    874                 iAlloc.deallocate(frameData);
    875                 OSCL_LEAVE(OsclErrNotSupported);
    876             }
    877 
    878             uint32 dataSize = ID3V1_MAX_NUM_BYTES_COMMENT + 1;
    879             // Allocate key-value pair
    880             OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_CHARPTR, dataSize, truncate););
    881             if (OsclErrNone != err || !kvpPtr)
    882             {
    883                 LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - AllocateKvp failed. err=%d", err));
    884                 iAlloc.deallocate(frameData);
    885                 OSCL_LEAVE(OsclErrNoMemory);
    886                 return;
    887             }
    888 
    889             if (!truncate)
    890             {
    891                 uint32 comment_size = oscl_strlen((char*) frameData);
    892                 oscl_strncpy(kvpPtr->value.pChar_value, (char *)frameData, dataSize);
    893                 kvpPtr->value.pChar_value[comment_size] = 0;
    894                 kvpPtr->length = comment_size + 1;
    895             }
    896 
    897             if (PVMFSuccess != PushFrameToFrameVector(kvpPtr, iFrames))
    898             {
    899                 LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - iFrame.push_back failed"));
    900                 iAlloc.deallocate(frameData);
    901                 return ;
    902             }
    903             iCommentFoundFlag = true;
    904 
    905         }
    906         iAlloc.deallocate(frameData);
    907     }
    908     else
    909     {
    910         if (iInputFile->Seek(ID3V1_MAX_NUM_BYTES_FIELD_SIZE, Oscl_File::SEEKCUR) == -1)
    911         {
    912             return;
    913         }
    914     }
    915     if (!iGenereFoundFlag)
    916     {
    917         // Genre frame
    918         uint32 frameDataSize = ID3V1_MAX_NUM_BYTES_GENRE + 1;
    919         int32 err = 0;
    920         frameData = (uint8*) AllocateValueArray(err, PVMI_KVPVALTYPE_UINT8PTR, frameDataSize, &iAlloc);
    921         if (OsclErrNone != err || !frameData)
    922         {
    923             LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - Out of memory"));
    924             OSCL_LEAVE(OsclErrNoMemory);
    925         }
    926         oscl_memset(frameData, 0, frameDataSize);
    927 
    928         if (readByteData(iInputFile, ID3V1_MAX_NUM_BYTES_GENRE, frameData) == false)
    929         {
    930             iAlloc.deallocate(frameData);
    931             LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - readByteData failed"));
    932             OSCL_LEAVE(OsclErrGeneral);
    933         }
    934 
    935         if (ConstructKvpKey(keyStr, PV_ID3_FRAME_GENRE, PV_ID3_CHARSET_INVALID) != PVMFSuccess)
    936         {
    937             iAlloc.deallocate(frameData);
    938             LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - ConstructKvpKey failed for genre"));
    939             OSCL_LEAVE(OsclErrNotSupported);
    940         }
    941 
    942         OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_UINT32, 1, truncate););
    943         if (OsclErrNone != err || !kvpPtr)
    944         {
    945             iAlloc.deallocate(frameData);
    946             LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - AllocateKvp failed. err=%d", err));
    947             OSCL_LEAVE(OsclErrNoMemory);
    948             return;
    949         }
    950 
    951         if (!truncate)
    952         {
    953             kvpPtr->value.uint32_value = (uint32)(frameData[ID3V1_MAX_NUM_BYTES_GENRE - 1]);
    954         }
    955         OSCL_TRY(err, iFrames.push_back(kvpPtr););
    956         OSCL_FIRST_CATCH_ANY(err,
    957                              iAlloc.deallocate(frameData);
    958                              LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - iFrame.push_back failed"));
    959                              OSCL_LEAVE(OsclErrNoMemory);
    960                              return;
    961                             );
    962         iAlloc.deallocate(frameData);
    963         iGenereFoundFlag = true;
    964     }
    965     else
    966     {
    967         if (iInputFile->Seek(ID3V1_MAX_NUM_BYTES_GENRE, Oscl_File::SEEKCUR) == -1)
    968         {
    969             return;
    970         }
    971     }
    972 }
    973 
    974 ////////////////////////////////////////////////////////////////////////////
    975 bool PVID3ParCom::ReadHeaderID3V2(bool aReadTags)
    976 {
    977     bool result = false;
    978 
    979     // Read and convert tag versions, Major and Minor
    980     uint8 ID3V2MajorVer, ID3V2MinorVer;
    981     if (read8(iInputFile, ID3V2MajorVer) == false)
    982     {
    983         return false;
    984     }
    985     if (read8(iInputFile, ID3V2MinorVer) == false)
    986     {
    987         return false;
    988     }
    989 
    990     switch (ID3V2MajorVer)
    991     {
    992         case PV_ID3_V2_2:
    993             iVersion = PV_ID3_V2_2;
    994             break;
    995         case PV_ID3_V2_3:
    996             iVersion = PV_ID3_V2_3;
    997             break;
    998         case PV_ID3_V2_4:
    999             iVersion = PV_ID3_V2_4;
   1000             break;
   1001     }
   1002 
   1003 BEGIN_V2:
   1004     // Read and convert tag flags
   1005     if (read8(iInputFile, iID3TagInfo.iID3V2TagFlagsV2) == false)
   1006     {
   1007         return false;
   1008     }
   1009 
   1010     uint32 tagsize = 0;
   1011 
   1012     // Read and convert tag size
   1013     if (read32(iInputFile, tagsize) == false)
   1014     {
   1015         return false;
   1016     }
   1017 
   1018     // Now check if an extended header exists
   1019     bool extHeaderFlag = false;
   1020     if (iID3TagInfo.iID3V2TagFlagsV2 & EXT_FLAGMASK)
   1021     {
   1022         if (iVersion == PV_ID3_V2_2)
   1023         {
   1024             // Since no compression scheme has been decided yet, just ignore the entire tag
   1025             LOG_ERR((0, "PVID3ParCom::ReadHeaderID3V2(): Error - cannot process a compressed tag"));
   1026             OSCL_LEAVE(OsclErrGeneral);
   1027         }
   1028 
   1029         extHeaderFlag = true;
   1030         //read extended header data
   1031         if (!ReadExtendedHeader())
   1032             return false;
   1033     }
   1034 
   1035     //check if footer is present.
   1036     if (iID3TagInfo.iID3V2TagFlagsV2 & FTR_FLAGMASK)
   1037     {
   1038         iID3TagInfo.iFooterPresent = true;
   1039     }
   1040 
   1041     // tagSize will store the file's Id3v2 tag size
   1042     iID3TagInfo.iID3V2TagSize = SafeSynchIntToInt32(tagsize);
   1043 
   1044     //calculate start of audio frame.
   1045     if (iTagAtBof)
   1046     {
   1047         // set iByteOffsetToStartOfAudioFrames and it must account for the frame header
   1048         iByteOffsetToStartOfAudioFrames =
   1049             iID3TagInfo.iID3V2TagSize + ID3V2_TAG_NUM_BYTES_HEADER;
   1050 
   1051         if (iID3TagInfo.iFooterPresent)
   1052             iByteOffsetToStartOfAudioFrames += ID3V2_TAG_NUM_BYTES_HEADER; //header & footer are of same size.
   1053     }
   1054     else
   1055     {
   1056         iByteOffsetToStartOfAudioFrames = 0;
   1057     }
   1058 
   1059     // Header read is completed, now check whether we need to read the tags or not
   1060     if (!aReadTags)
   1061     {
   1062         return false;
   1063     }
   1064     else
   1065     {
   1066         int count = ReadTagID3V2(iVersion);
   1067         if (count > 0)
   1068         {
   1069             // we found some tags
   1070             result = true;
   1071         }
   1072 
   1073         if (iSeekFrameFound)
   1074         {
   1075             //jump to the new tag location skipping 5 bytes of tag ID and version.
   1076             uint32 seek_size = iID3TagInfo.iID3V2TagSize + ID3V2_TAG_NUM_BYTES_HEADER + (iID3TagInfo.iFooterPresent ? ID3V2_TAG_NUM_BYTES_HEADER : 0);
   1077             if (iInputFile->Seek(seek_size, Oscl_File::SEEKSET) == -1)
   1078             {
   1079                 return false;
   1080             }
   1081 
   1082             //skip 5 bytes of tag ID and version.
   1083             if (iInputFile->Seek(iID3TagInfo.iID3V2SeekOffset, Oscl_File::SEEKCUR) == -1)
   1084             {
   1085                 return false;
   1086             }
   1087 
   1088             if (!CheckForTagID3V2())
   1089                 return false;
   1090 
   1091             if (read8(iInputFile, ID3V2MajorVer) == false)
   1092             {
   1093                 return false;
   1094             }
   1095 
   1096             if (read8(iInputFile, ID3V2MinorVer) == false)
   1097             {
   1098                 return false;
   1099             }
   1100 
   1101             if (ID3V2MajorVer != PV_ID3_V2_4)
   1102                 return false;
   1103 
   1104             //parse new tag, located at the seek offset.
   1105             iSeekFrameFound = false;
   1106             goto BEGIN_V2;
   1107         }
   1108     }
   1109     return result;
   1110 }
   1111 
   1112 /////////////////////////////////////////////////////////////////////////////////
   1113 bool PVID3ParCom::ReadExtendedHeader()
   1114 {
   1115 
   1116     uint32 extsize = 0;
   1117     if (read32(iInputFile, extsize) == false)
   1118     {
   1119         return false;
   1120     }
   1121 
   1122     // Calculate the length of the extended header.
   1123     iID3TagInfo.iID3V2ExtendedHeaderSize = SafeSynchIntToInt32(extsize);
   1124 
   1125 
   1126     if (iVersion == PV_ID3_V2_4)
   1127     {
   1128         //subtract "ext hdr size" field size from the header size.
   1129         iID3TagInfo.iID3V2ExtendedHeaderSize = iID3TagInfo.iID3V2ExtendedHeaderSize - ID3V2_TAG_EXTENDED_HEADER_SIZE;
   1130 
   1131         //check if this tag is an update of previous tag.
   1132         uint8 flgsize = 0, exthdrflg = 0;
   1133         // Read and ext hdr flg size tag flags
   1134         if (read8(iInputFile, flgsize) == false)
   1135         {
   1136             return false;
   1137         }
   1138         if (flgsize > 0x01) //flg size should be 1 byte in V2.4
   1139             return false ;
   1140         // Read tag flags
   1141         if (read8(iInputFile, exthdrflg) == false)
   1142         {
   1143             return false;
   1144         }
   1145         //if this tag is not an update flag, ignore any tag found before this one
   1146         if (!(exthdrflg & EXTHDR_UPDMASK) && (iFrames.size() > 0))
   1147         {
   1148             while (iFrames.size() > 0)
   1149                 iFrames.pop_back();
   1150         }
   1151 
   1152         //subtract 2 bytes for flg size and flg from ext hdr size.
   1153         iID3TagInfo.iID3V2ExtendedHeaderSize = iID3TagInfo.iID3V2ExtendedHeaderSize - 2;
   1154     }
   1155 
   1156     if (iVersion == PV_ID3_V2_3)
   1157     {
   1158         //V2.3 extended hdr size field does not include 6 byte size of the header
   1159         iID3TagInfo.iID3V2ExtendedHeaderSize += ID3V2_TAG_EXTENDED_HEADER_TOTAL_SIZE;
   1160     }
   1161 
   1162     return true;
   1163 }
   1164 
   1165 /////////////////////////////////////////////////////////////////////////////////
   1166 int PVID3ParCom::ReadTagID3V2(PVID3Version aVersion)
   1167 {
   1168     PVID3FrameType frameType = PV_ID3_FRAME_EEND;
   1169     uint32 i = 0;
   1170     uint32 currFrameLength = 0;
   1171     uint32 current_file_pos = iInputFile->Tell();
   1172     uint32 data_len_indicator_size = 0;
   1173     uint32 count = 0;
   1174 
   1175     if (iID3TagInfo.iID3V2ExtendedHeaderSize > 0)
   1176         i += iID3TagInfo.iID3V2ExtendedHeaderSize ;
   1177 
   1178     while (i <= (iID3TagInfo.iID3V2TagSize))
   1179     {
   1180         // Read the frame header
   1181         if (iInputFile->Seek(current_file_pos + i, Oscl_File::SEEKSET) == -1)
   1182         {
   1183             return count;
   1184         }
   1185 
   1186         ReadFrameHeaderID3V2(aVersion);
   1187 
   1188         currFrameLength = iID3TagInfo.iID3V2FrameSize;
   1189         frameType = FrameSupportedID3V2(aVersion);
   1190 
   1191         if ((frameType != PV_ID3_FRAME_SEEK) && (currFrameLength > iID3TagInfo.iID3V2TagSize))
   1192         {
   1193             break;
   1194         }
   1195         // handle the frame header
   1196 
   1197         uint32 frame_header_size = 0;
   1198         if (aVersion == PV_ID3_V2_2)
   1199             frame_header_size = ID3V2_2_FRAME_NUM_BYTES_HEADER;
   1200         else
   1201             frame_header_size = ID3V2_FRAME_NUM_BYTES_HEADER;
   1202 
   1203 
   1204         if ((currFrameLength == 0) && (frameType != PV_ID3_FRAME_EEND))
   1205         {
   1206             i += frame_header_size;
   1207             continue;
   1208         }
   1209         if (aVersion == PV_ID3_V2_3)
   1210         {
   1211             if (iID3TagInfo.iID3V2FrameFlag[1] & ENCR_COMP_3_FLAGMASK)
   1212                 frameType = PV_ID3_FRAME_UNRECOGNIZED;
   1213         }
   1214         else if (aVersion == PV_ID3_V2_4)
   1215         {
   1216             if (iID3TagInfo.iID3V2FrameFlag[1] & ENCR_COMP_4_FLAGMASK)
   1217                 frameType = PV_ID3_FRAME_UNRECOGNIZED;
   1218         }
   1219 
   1220         if (frameType == PV_ID3_FRAME_SEEK)
   1221         {
   1222             iSeekFrameFound = true;
   1223             iID3TagInfo.iID3V2SeekOffset = iID3TagInfo.iID3V2FrameSize;
   1224             return count;
   1225         }
   1226 
   1227         // Check if data length indicator is present
   1228         if (aVersion == PV_ID3_V2_4 && (iID3TagInfo.iID3V2FrameFlag[1] & FRAME_LENGTH_INDICATOR_FLAGMASK))
   1229         {
   1230             uint32 temp = 0;
   1231             // Read data length indicator
   1232             if (read32(iInputFile, temp) == false)
   1233             {
   1234                 return count;
   1235             }
   1236             // stored as syncsafe integer
   1237             currFrameLength = SafeSynchIntToInt32(temp);
   1238 
   1239             data_len_indicator_size = ID3V2_4_DATA_LENGTH_INDICATOR_SIZE;
   1240         }
   1241 
   1242         if (((currFrameLength > 1) && (frameType != PV_ID3_FRAME_UNRECOGNIZED
   1243                                        && frameType != PV_ID3_FRAME_INVALID
   1244                                        && frameType != PV_ID3_FRAME_EEND
   1245                                        && frameType != PV_ID3_FRAME_CANDIDATE)))
   1246         {
   1247             uint8 unicodeCheck;
   1248 
   1249             if (read8(iInputFile, unicodeCheck) == false)
   1250             {
   1251                 return count;
   1252             }
   1253 
   1254             if ((frameType == PV_ID3_FRAME_LYRICS) || (frameType == PV_ID3_FRAME_COMMENT))
   1255             {
   1256                 ReadLyricsCommFrame(unicodeCheck, currFrameLength - 1, frameType);
   1257 
   1258             }
   1259             else if ((frameType == PV_ID3_FRAME_APIC) || (frameType == PV_ID3_FRAME_PIC))
   1260             {
   1261                 if (currFrameLength > 3000000)
   1262                 {
   1263                     // TODO: scale down album art to something manageable right here
   1264                     LOG_DEBUG((0, "PVID3ParCom::ReadTagID3V2: skipping > 3MB album art"));
   1265                 }
   1266                 else
   1267                 {
   1268                     if (ReadAlbumArtFrame(frameType, unicodeCheck, currFrameLength)  != PVMFSuccess)
   1269                     {
   1270                         LOG_ERR((0, "PVID3ParCom::ReadTagID3V2: Error - ReadAPICFrame failed"));
   1271                         return count;
   1272                     }
   1273                 }
   1274             }
   1275             else if (unicodeCheck < PV_ID3_CHARSET_END)
   1276             {
   1277 
   1278                 if (!ReadFrameData(unicodeCheck, frameType,
   1279                                    current_file_pos + i + frame_header_size + data_len_indicator_size + 1,
   1280                                    currFrameLength))
   1281                 {
   1282                     return count;
   1283                 }
   1284             }
   1285             else
   1286             {
   1287                 // This case is when no text type is defined in the frame.
   1288                 HandleID3V2FrameDataASCII(frameType, i + frame_header_size + data_len_indicator_size, currFrameLength);
   1289             }
   1290             count++;
   1291         }
   1292         else
   1293         {
   1294             if (frameType == PV_ID3_FRAME_EEND ||
   1295                     frameType == PV_ID3_FRAME_INVALID)
   1296             {
   1297                 i = iID3TagInfo.iID3V2TagSize + 1;
   1298             }
   1299             else if (frameType == PV_ID3_FRAME_UNRECOGNIZED ||
   1300                      frameType == PV_ID3_FRAME_CANDIDATE) // handle candidate frames as we do unsupported
   1301             {
   1302                 if (i < iID3TagInfo.iID3V2TagSize)
   1303                 {
   1304                     HandleID3V2FrameUnsupported(frameType,
   1305                                                 current_file_pos + i,
   1306                                                 currFrameLength + frame_header_size + data_len_indicator_size);
   1307                 }
   1308             }
   1309         }
   1310 
   1311         i += iID3TagInfo.iID3V2FrameSize + frame_header_size;
   1312     }
   1313     return count;
   1314 }
   1315 
   1316 bool PVID3ParCom::ValidateFrameV2_4(PVID3FrameType& frameType, bool bUseSyncSafeFrameSize)
   1317 {
   1318     // Initialize OUT param
   1319     frameType = PV_ID3_FRAME_INVALID;
   1320 
   1321     uint8 frameid[ID3V2_FRAME_NUM_BYTES_ID + 1] = {0};
   1322     // read frame id for next frame
   1323     if (readByteData(iInputFile, ID3V2_FRAME_NUM_BYTES_ID, frameid) == false)
   1324     {
   1325         return false;
   1326     }
   1327     frameid[ID3V2_FRAME_NUM_BYTES_ID] = 0;
   1328 
   1329     // Get frame type from frame ID
   1330     frameType = FrameSupportedID3V2(PV_ID3_V2_4, frameid);
   1331     if (PV_ID3_FRAME_INVALID == frameType ||
   1332             PV_ID3_FRAME_EEND == frameType)
   1333     {
   1334         return false;
   1335     }
   1336     else
   1337     {
   1338         uint32 frameSize = 0;
   1339         uint8 frameflags[ID3V2_FRAME_NUM_BYTES_FLAG] = {0};
   1340 
   1341         // Validate frame size and flags
   1342 
   1343         if (read32(iInputFile, frameSize) == false)
   1344         {
   1345             return false;
   1346         }
   1347         if (bUseSyncSafeFrameSize)
   1348         {
   1349             frameSize = SafeSynchIntToInt32(frameSize);
   1350         }
   1351 
   1352         if (readByteData(iInputFile, ID3V2_FRAME_NUM_BYTES_FLAG, frameflags) == false)
   1353         {
   1354             return false;
   1355         }
   1356 
   1357         if ((0 == frameSize ||
   1358                 (frameSize + ID3V2_FRAME_NUM_BYTES_HEADER) > iID3TagInfo.iID3V2TagSize) ||
   1359                 ((frameflags[0] & ID3V2_4_MASK_FRAME_FLAG_VERIFICATION) ||
   1360                  (frameflags[1] & ID3V2_4_MASK_FRAME_FLAG_VERIFICATION)))
   1361         {
   1362             // validation for frame size or flags failed
   1363             return false;
   1364         }
   1365         else
   1366         {
   1367             return true;
   1368         }
   1369     }
   1370 }
   1371 
   1372 uint32 PVID3ParCom::ValidateFrameLengthV2_4(uint32 aFrameSize)
   1373 {
   1374     int32 currFilePos = iInputFile->Tell();
   1375     int32 errCode = -1;
   1376     int32 actualFrameLen = 0;
   1377 
   1378     // we have already read the complete current frame header
   1379 
   1380     do
   1381     {
   1382         // Assuming syncsafe frame size
   1383         actualFrameLen = SafeSynchIntToInt32(aFrameSize);
   1384 
   1385         //
   1386         /* validate frame using syncsafe size */
   1387         //
   1388 
   1389         // Seek to next frame boundary with syncsafe size
   1390         errCode = iInputFile->Seek(actualFrameLen, Oscl_File::SEEKCUR);
   1391         if (-1 == errCode)
   1392         {
   1393             // proceed with default syncsafe handling
   1394             break;
   1395         }
   1396 
   1397         bool bIsSyncSafeFrameValid = false;
   1398         PVID3FrameType frameTypeUsingSyncSafeSize = PV_ID3_FRAME_INVALID;
   1399         // Get the validation status and frame type
   1400         bIsSyncSafeFrameValid = ValidateFrameV2_4(frameTypeUsingSyncSafeSize);
   1401 
   1402         //
   1403         /* validate frame using non-syncsafe size */
   1404         //
   1405 
   1406         // FrameSize is not even stored as non-syncsafe
   1407         if ((aFrameSize + ID3V2_FRAME_NUM_BYTES_HEADER) > iID3TagInfo.iID3V2TagSize)
   1408         {
   1409             // proceed with syncsafe, as non-syncsafe length not valid
   1410             break;
   1411         }
   1412 
   1413         // Seek back
   1414         errCode = iInputFile->Seek(currFilePos, Oscl_File::SEEKSET);
   1415         if (-1 == errCode)
   1416         {
   1417             LOG_ERR((0, "PVID3ParCom::ValidateFrameLengthV2_4: Error - iInputFile->Seek failed"));
   1418             OSCL_LEAVE(OsclErrGeneral);
   1419         }
   1420         // Seek to next frame boundary with non-syncsafe size
   1421         errCode = iInputFile->Seek(aFrameSize, Oscl_File::SEEKCUR);
   1422         if (-1 == errCode)
   1423         {
   1424             // proceed with default syncsafe handling
   1425             break;
   1426         }
   1427 
   1428         bool bIsNonSyncSafeFrameValid = false;
   1429         PVID3FrameType frameTypeUsingNonSyncSafeSize = PV_ID3_FRAME_INVALID;
   1430         // Get the validation status and frame type
   1431         bIsNonSyncSafeFrameValid = ValidateFrameV2_4(frameTypeUsingNonSyncSafeSize, false);
   1432 
   1433         // - Give more priority to non-syncsafe VALID frame ID,
   1434         //      than syncsafe candidate frame ID (frame validation is true for both)
   1435         // - In case, we have frame validation true for both syncsafe and non-syncsafe size,
   1436         //      we will use default syncsafe representation
   1437         // - In case, we have frame validation false for both syncsafe and non-syncsafe size,
   1438         //      we will use default syncsafe representation
   1439         if (bIsSyncSafeFrameValid && frameTypeUsingSyncSafeSize != PV_ID3_FRAME_CANDIDATE)
   1440         {
   1441             // syncsafe representation
   1442         }
   1443         else if (bIsNonSyncSafeFrameValid && frameTypeUsingNonSyncSafeSize != PV_ID3_FRAME_CANDIDATE)
   1444         {
   1445             // non-syncsafe representation
   1446             actualFrameLen = aFrameSize;
   1447         }
   1448         else if (!bIsSyncSafeFrameValid && bIsNonSyncSafeFrameValid)
   1449         {
   1450             // non-syncsafe representation
   1451             actualFrameLen = aFrameSize;
   1452         }
   1453         else
   1454         {
   1455             // consider rest all syncsafe representation
   1456         }
   1457 
   1458     }
   1459     while (false);
   1460 
   1461     // Seek back
   1462     errCode = iInputFile->Seek(currFilePos, Oscl_File::SEEKSET);
   1463     if (-1 == errCode)
   1464     {
   1465         LOG_ERR((0, "PVID3ParCom::ValidateFrameLengthV2_4: Error - iInputFile->Seek failed"));
   1466         OSCL_LEAVE(OsclErrGeneral);
   1467     }
   1468 
   1469     return actualFrameLen;
   1470 }
   1471 
   1472 //////////////////////////////////////////////////////////////////////////
   1473 bool  PVID3ParCom::ReadFrameData(uint8 unicodeCheck, PVID3FrameType frameType, uint32 pos, uint32 currFrameLength)
   1474 {
   1475     if (unicodeCheck == PV_ID3_CHARSET_ISO88591)
   1476     {
   1477         // This frame contains normal ASCII text strings. (ISO-8859-1)
   1478         iID3TagInfo.iTextType = PV_ID3_CHARSET_ISO88591;
   1479         HandleID3V2FrameDataASCII(frameType, pos, currFrameLength - 1);
   1480     }
   1481     else if (unicodeCheck == PV_ID3_CHARSET_UTF16)
   1482     {
   1483         uint16 endianCheck;
   1484 
   1485         if (read16(iInputFile, endianCheck) == false)
   1486         {
   1487             return false;
   1488         }
   1489 
   1490         // This frame's text strings are Unicode and the frame
   1491         // does include a BOM value. (UTF-16)
   1492         iID3TagInfo.iTextType = PV_ID3_CHARSET_UTF16;
   1493         uint32 endianType;
   1494         if (endianCheck == UNICODE_LITTLE_ENDIAN_INDICATOR_FULL)
   1495         {
   1496             endianType = UNICODE_LITTLE_ENDIAN;
   1497         }
   1498         else if (endianCheck == UNICODE_BIG_ENDIAN_INDICATOR_FULL)
   1499         {
   1500             endianType = UNICODE_BIG_ENDIAN;
   1501         }
   1502         else
   1503         {
   1504             return false;
   1505         }
   1506 
   1507         // value of 2 is for BOM Character
   1508         HandleID3V2FrameDataUnicode16(frameType, pos + 2, currFrameLength - 3, endianType);
   1509     }
   1510     else if (unicodeCheck == PV_ID3_CHARSET_UTF16BE)
   1511     {
   1512         // This frame's text strings are Unicode but the frame
   1513         // does not contain a BOM(byte order mark) (UTF-16BE)
   1514         iID3TagInfo.iTextType = PV_ID3_CHARSET_UTF16BE;
   1515         // Default ID3V2 endian type to Big Endian
   1516         uint32 endianType = UNICODE_BIG_ENDIAN;
   1517         // Big Endian is assumed since the frame did not specify the endian type.
   1518         HandleID3V2FrameDataUnicode16(frameType, pos, currFrameLength - 1, endianType);
   1519     }
   1520     else if (unicodeCheck == PV_ID3_CHARSET_UTF8)
   1521     {
   1522         // This frame's text strings are Unicode (UTF-8)
   1523         iID3TagInfo.iTextType = PV_ID3_CHARSET_UTF8;
   1524         HandleID3V2FrameDataUTF8(frameType, pos, currFrameLength - 1);
   1525     }
   1526     return true;
   1527 }
   1528 
   1529 ////////////////////////////////////////////////////////////////////////////
   1530 void PVID3ParCom::ReadFrameHeaderID3V2(PVID3Version aVersion)
   1531 {
   1532     if (aVersion == PV_ID3_V2_2)
   1533     {
   1534         ReadFrameHeaderID3V2_2();
   1535     }
   1536     else
   1537     {
   1538         // Read frame ID
   1539         if (readByteData(iInputFile, ID3V2_FRAME_NUM_BYTES_ID, iID3TagInfo.iID3V2FrameID) == false)
   1540         {
   1541             return;
   1542         }
   1543         iID3TagInfo.iID3V2FrameID[ID3V2_FRAME_NUM_BYTES_ID] = 0;
   1544         // Read frame size
   1545         if (read32(iInputFile, iID3TagInfo.iID3V2FrameSize) == false)
   1546         {
   1547             return;
   1548         }
   1549         // Read frame flag
   1550         if (readByteData(iInputFile, ID3V2_FRAME_NUM_BYTES_FLAG, iID3TagInfo.iID3V2FrameFlag) == false)
   1551         {
   1552             return;
   1553         }
   1554 
   1555         if (PV_ID3_V2_4 == aVersion)
   1556         {
   1557             if (iID3TagInfo.iID3V2FrameSize > MAX_SYNCSAFE_LEN)
   1558             {
   1559                 // Verify whether frame length is SyncSafe or Non-SyncSafe
   1560                 iID3TagInfo.iID3V2FrameSize = ValidateFrameLengthV2_4(iID3TagInfo.iID3V2FrameSize);
   1561             }
   1562         }
   1563     }
   1564     return;
   1565 }
   1566 
   1567 ////////////////////////////////////////////////////////////////////////////
   1568 void PVID3ParCom::ReadFrameHeaderID3V2_2()
   1569 {
   1570     if (readByteData(iInputFile, ID3V2_2_FRAME_NUM_BYTES_ID, iID3TagInfo.iID3V2FrameID) == false)
   1571     {
   1572         return;
   1573     }
   1574     iID3TagInfo.iID3V2FrameID[ID3V2_2_FRAME_NUM_BYTES_ID] = 0;
   1575     if (read24(iInputFile, iID3TagInfo.iID3V2FrameSize) == false)
   1576     {
   1577         return;
   1578     }
   1579 
   1580     return;
   1581 }
   1582 
   1583 //////////////////////////////////////////////////////////////////////////////
   1584 void PVID3ParCom::HandleID3V2FrameDataASCII(PVID3FrameType aFrameType,
   1585         uint32         aPos,
   1586         uint32         aSize)
   1587 {
   1588     OSCL_StackString<128> keyStr;
   1589     PvmiKvpSharedPtr kvpPtr;
   1590     PVMFStatus status = PVMFSuccess;
   1591     if (iInputFile->Seek(aPos, Oscl_File::SEEKSET) == -1)
   1592     {
   1593         LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataASCII: Error - iInputFile->Seek failed"));
   1594         OSCL_LEAVE(OsclErrGeneral);
   1595     }
   1596 
   1597     switch (aFrameType)
   1598     {
   1599         case PV_ID3_FRAME_TRACK_LENGTH:
   1600             status = ReadTrackLengthFrame(aSize, PV_ID3_CHARSET_ISO88591);
   1601             if (status != PVMFSuccess)
   1602             {
   1603                 LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataASCII: Error - ReadTrackLengthFrame failed. status=%d", status));
   1604                 OSCL_LEAVE(OsclErrGeneral);
   1605             }
   1606             break;
   1607         case PV_ID3_FRAME_TITLE:
   1608         case PV_ID3_FRAME_ARTIST:
   1609         case PV_ID3_FRAME_ALBUM:
   1610         case PV_ID3_FRAME_YEAR:
   1611         case PV_ID3_FRAME_TRACK_NUMBER:
   1612         case PV_ID3_FRAME_GENRE:
   1613         case PV_ID3_FRAME_COPYRIGHT:
   1614         case PV_ID3_FRAME_DATE:
   1615         case PV_ID3_FRAME_RECORDING_TIME:
   1616 //new frames support
   1617         case PV_ID3_FRAME_AUTHOR:
   1618         case PV_ID3_FRAME_COMPOSER:
   1619         case PV_ID3_FRAME_DESCRIPTION:
   1620         case PV_ID3_FRAME_VERSION:
   1621         case PV_ID3_FRAME_PART_OF_SET:
   1622 
   1623             status = ReadStringValueFrame(aFrameType, PV_ID3_CHARSET_ISO88591, aSize);
   1624             if (status != PVMFSuccess)
   1625             {
   1626                 LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataASCII: Error - ReadStringValueFrame failed. status=%d", status));
   1627                 OSCL_LEAVE(OsclErrGeneral);
   1628             }
   1629             if (aFrameType == PV_ID3_FRAME_TITLE)
   1630                 iTitleFoundFlag = true;
   1631             if (aFrameType == PV_ID3_FRAME_ARTIST)
   1632                 iArtistFoundFlag = true;
   1633             if (aFrameType == PV_ID3_FRAME_ALBUM)
   1634                 iAlbumFoundFlag = true;
   1635             if (aFrameType == PV_ID3_FRAME_YEAR)
   1636                 iYearFoundFlag = true;
   1637             if (aFrameType == PV_ID3_FRAME_TRACK_NUMBER)
   1638                 iTrackNumberFoundFlag = true;
   1639             if (aFrameType == PV_ID3_FRAME_GENRE)
   1640                 iGenereFoundFlag = true;
   1641 
   1642             break;
   1643 
   1644         default:
   1645             break;
   1646     }
   1647 }
   1648 
   1649 void PVID3ParCom::HandleID3V2FrameUnsupported(PVID3FrameType aFrameType,
   1650         uint32         aPos,
   1651         uint32         aSize)
   1652 {
   1653 // In Android, don't try to read unsupported metadata, because a) we don't
   1654 // know what to do with it anyway, and b) we end up here for corrupted files
   1655 // too, in which case the size is likely bogus and will result in running
   1656 // out of RAM.
   1657 #ifndef ANDROID
   1658     OSCL_StackString<128> keyStr;
   1659     PvmiKvpSharedPtr kvpPtr;
   1660     PVMFStatus status = PVMFSuccess;
   1661     if (iInputFile->Seek(aPos, Oscl_File::SEEKSET) == -1)
   1662     {
   1663         LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataASCII: Error - iInputFile->Seek failed"));
   1664         OSCL_LEAVE(OsclErrGeneral);
   1665     }
   1666 
   1667     status = ReadFrame(aFrameType, aSize);
   1668     if (status != PVMFSuccess)
   1669     {
   1670         LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataASCII: Error - ReadStringValueFrame failed. status=%d", status));
   1671         OSCL_LEAVE(OsclErrGeneral);
   1672     }
   1673 #endif
   1674 }
   1675 
   1676 ////////////////////////////////////////////////////////////////////////////
   1677 void PVID3ParCom::HandleID3V2FrameDataUnicode16(PVID3FrameType aFrameType,
   1678         uint32 aPos,
   1679         uint32 aSize,
   1680         uint32 aEndianType)
   1681 {
   1682     // seek to the beginning of the current frame data
   1683     if (iInputFile->Seek(aPos, Oscl_File::SEEKSET) == -1)
   1684     {
   1685         LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUnicode16: Error - iInputFile->Seek failed"));
   1686         OSCL_LEAVE(OsclErrGeneral);
   1687         return;
   1688     }
   1689 
   1690     PVMFStatus status = PVMFSuccess;
   1691     PVID3CharacterSet charSet;
   1692     if (aEndianType == UNICODE_BIG_ENDIAN)
   1693         charSet = PV_ID3_CHARSET_UTF16BE;
   1694     else
   1695         charSet = PV_ID3_CHARSET_UTF16;
   1696 
   1697     switch (aFrameType)
   1698     {
   1699 
   1700         case PV_ID3_FRAME_TRACK_LENGTH:
   1701             //is a numeric string and does not depend on text encoding.
   1702             status = ReadTrackLengthFrame(aSize, charSet);
   1703             if (status != PVMFSuccess)
   1704             {
   1705                 LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUnicode16: Error - ReadTrackLengthFrame failed. status=%d", status));
   1706                 OSCL_LEAVE(OsclErrGeneral);
   1707                 return;
   1708             }
   1709             break;
   1710         case PV_ID3_FRAME_TITLE:
   1711         case PV_ID3_FRAME_ARTIST:
   1712         case PV_ID3_FRAME_ALBUM:
   1713         case PV_ID3_FRAME_YEAR:
   1714         case PV_ID3_FRAME_TRACK_NUMBER:
   1715         case PV_ID3_FRAME_GENRE:
   1716         case PV_ID3_FRAME_COPYRIGHT:
   1717         case PV_ID3_FRAME_DATE:
   1718         case PV_ID3_FRAME_RECORDING_TIME:
   1719 //new frames support
   1720         case PV_ID3_FRAME_AUTHOR:
   1721         case PV_ID3_FRAME_COMPOSER:
   1722         case PV_ID3_FRAME_DESCRIPTION:
   1723         case PV_ID3_FRAME_VERSION:
   1724         case PV_ID3_FRAME_PART_OF_SET:
   1725 
   1726             status = ReadStringValueFrame(aFrameType, charSet, aSize);
   1727             if (status != PVMFSuccess)
   1728             {
   1729                 LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUnicode16: Error - ReadStringValueFrame failed. status=%d", status));
   1730                 OSCL_LEAVE(OsclErrGeneral);
   1731                 return;
   1732             }
   1733             if (aFrameType == PV_ID3_FRAME_TITLE)
   1734                 iTitleFoundFlag = true;
   1735             if (aFrameType == PV_ID3_FRAME_ARTIST)
   1736                 iArtistFoundFlag = true;
   1737             if (aFrameType == PV_ID3_FRAME_ALBUM)
   1738                 iAlbumFoundFlag = true;
   1739             if (aFrameType == PV_ID3_FRAME_YEAR)
   1740                 iYearFoundFlag = true;
   1741             if (aFrameType == PV_ID3_FRAME_TRACK_NUMBER)
   1742                 iTrackNumberFoundFlag = true;
   1743             if (aFrameType == PV_ID3_FRAME_GENRE)
   1744                 iGenereFoundFlag = true;
   1745 
   1746             break;
   1747 
   1748         default:
   1749             break;
   1750     }
   1751 }
   1752 
   1753 ////////////////////////////////////////////////////////////////////////////
   1754 void PVID3ParCom::HandleID3V2FrameDataUTF8(PVID3FrameType aFrameType,
   1755         uint32         aPos,
   1756         uint32         aSize)
   1757 {
   1758     if (iInputFile->Seek(aPos, Oscl_File::SEEKSET) == -1)
   1759     {
   1760         LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUTF8: Error - iInputFile->Seek failed"));
   1761         OSCL_LEAVE(OsclErrGeneral);
   1762     }
   1763 
   1764     PVMFStatus status = PVMFSuccess;
   1765     switch (aFrameType)
   1766     {
   1767 
   1768         case PV_ID3_FRAME_TRACK_LENGTH:
   1769             status = ReadTrackLengthFrame(aSize, PV_ID3_CHARSET_UTF8);
   1770             if (status != PVMFSuccess)
   1771             {
   1772                 LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUTF8: Error - ReadTrackLengthFrame failed. status=%d", status));
   1773                 OSCL_LEAVE(OsclErrGeneral);
   1774             }
   1775             break;
   1776 
   1777         case PV_ID3_FRAME_TITLE:
   1778         case PV_ID3_FRAME_ARTIST:
   1779         case PV_ID3_FRAME_ALBUM:
   1780         case PV_ID3_FRAME_YEAR:
   1781         case PV_ID3_FRAME_TRACK_NUMBER:
   1782         case PV_ID3_FRAME_GENRE:
   1783         case PV_ID3_FRAME_COPYRIGHT:
   1784         case PV_ID3_FRAME_DATE:
   1785         case PV_ID3_FRAME_RECORDING_TIME:
   1786 //new frames support
   1787         case PV_ID3_FRAME_AUTHOR:
   1788         case PV_ID3_FRAME_COMPOSER:
   1789         case PV_ID3_FRAME_DESCRIPTION:
   1790         case PV_ID3_FRAME_VERSION:
   1791         case PV_ID3_FRAME_PART_OF_SET:
   1792 
   1793             status = ReadStringValueFrame(aFrameType, PV_ID3_CHARSET_UTF8, aSize);
   1794             if (status != PVMFSuccess)
   1795             {
   1796                 LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUTF8: Error - ReadStringValueFrame failed. status=%d", status));
   1797                 OSCL_LEAVE(OsclErrGeneral);
   1798             }
   1799             if (aFrameType == PV_ID3_FRAME_TITLE)
   1800                 iTitleFoundFlag = true;
   1801             if (aFrameType == PV_ID3_FRAME_ARTIST)
   1802                 iArtistFoundFlag = true;
   1803             if (aFrameType == PV_ID3_FRAME_ALBUM)
   1804                 iAlbumFoundFlag = true;
   1805             if (aFrameType == PV_ID3_FRAME_YEAR)
   1806                 iYearFoundFlag = true;
   1807             if (aFrameType == PV_ID3_FRAME_TRACK_NUMBER)
   1808                 iTrackNumberFoundFlag = true;
   1809             if (aFrameType == PV_ID3_FRAME_GENRE)
   1810                 iGenereFoundFlag = true;
   1811 
   1812             break;
   1813 
   1814         default:
   1815             break;
   1816     }
   1817 }
   1818 
   1819 //----------------------------------------------------------------------------
   1820 // FUNCTION NAME: PVID3ParCom::FrameSupportedID3V2(PVID3Version)
   1821 //----------------------------------------------------------------------------
   1822 // INPUT AND OUTPUT DEFINITIONS
   1823 //
   1824 //  Inputs: None
   1825 //
   1826 //  Outputs: None
   1827 //
   1828 //  Returns:
   1829 //    ID3V2FrameTypeReturnValue - The value that describes the current frame.
   1830 //                                of type enum TID3V2FrameType
   1831 //
   1832 //  Global Variables Used:
   1833 //    TID3V2FrameType - The enum table containing the supported frame types
   1834 //
   1835 //----------------------------------------------------------------------------
   1836 // FUNCTION DESCRIPTION
   1837 //
   1838 //  This function detects the ID3V2FrameType and returns the enum value that
   1839 //  corresponds to the current frame.
   1840 //
   1841 //------------------------------------------------------------------------------
   1842 
   1843 PVID3ParCom::PVID3FrameType PVID3ParCom::FrameSupportedID3V2(PVID3Version aVersion, uint8* aframeid)
   1844 {
   1845     PVID3FrameType ID3V2FrameTypeReturnValue;
   1846     uint8* pFrameID = (aframeid) ? aframeid : iID3TagInfo.iID3V2FrameID;
   1847 
   1848     if (0xff == pFrameID[0])
   1849     {
   1850         //possibly start of mp3 frame. Stop further parsing.
   1851         return PV_ID3_FRAME_EEND;
   1852     }
   1853 
   1854     if (aVersion == PV_ID3_V2_2)
   1855     {
   1856         ID3V2FrameTypeReturnValue = FrameSupportedID3V2_2();
   1857     }
   1858     else    //for v2.3 & v2.4
   1859     {
   1860         uint8 endTestBuf[ID3V2_FRAME_NUM_BYTES_ID] = {0};
   1861 
   1862         if (oscl_memcmp(pFrameID, ID3_FRAME_ID_TITLE, ID3V2_FRAME_NUM_BYTES_ID) == 0)
   1863         {
   1864             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_TITLE;
   1865             iTitleFoundFlag = true;
   1866         }
   1867         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_ARTIST, ID3V2_FRAME_NUM_BYTES_ID) == 0)
   1868         {
   1869             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_ARTIST;
   1870             iArtistFoundFlag = true;
   1871         }
   1872         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_PART_OF_SET, ID3V2_FRAME_NUM_BYTES_ID) == 0)
   1873         {
   1874             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_PART_OF_SET;
   1875         }
   1876         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_ALBUM, ID3V2_FRAME_NUM_BYTES_ID) == 0)
   1877         {
   1878             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_ALBUM;
   1879             iAlbumFoundFlag = true;
   1880         }
   1881         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_COPYRIGHT, ID3V2_FRAME_NUM_BYTES_ID) == 0)
   1882         {
   1883             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_COPYRIGHT;
   1884         }
   1885         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_GENRE, ID3V2_FRAME_NUM_BYTES_ID) == 0)
   1886         {
   1887             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_GENRE;
   1888             iGenereFoundFlag = true;
   1889         }
   1890         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_TRACK_NUMBER, ID3V2_FRAME_NUM_BYTES_ID) == 0)
   1891         {
   1892             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_TRACK_NUMBER;
   1893             iTrackNumberFoundFlag = true;
   1894         }
   1895         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_TRACK_LENGTH, ID3V2_FRAME_NUM_BYTES_ID) == 0)
   1896         {
   1897             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_TRACK_LENGTH;
   1898         }
   1899         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_COMMENT, ID3V2_FRAME_NUM_BYTES_ID) == 0)
   1900         {
   1901             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_COMMENT;
   1902             iCommentFoundFlag = true;
   1903         }
   1904         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_YEAR, ID3V2_FRAME_NUM_BYTES_ID) == 0)
   1905         {
   1906             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_YEAR;
   1907             iYearFoundFlag = true;
   1908         }
   1909         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_RECORDING_TIME, ID3V2_FRAME_NUM_BYTES_ID) == 0)
   1910         {
   1911             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_RECORDING_TIME;
   1912             iYearFoundFlag = true;
   1913         }
   1914         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_DATE, ID3V2_FRAME_NUM_BYTES_ID) == 0)
   1915         {
   1916             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_DATE;
   1917         }
   1918 
   1919         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_ALBUMART, ID3V2_FRAME_NUM_BYTES_ID) == 0)
   1920         {
   1921             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_APIC;
   1922         }
   1923         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_LYRICIST, ID3V2_FRAME_NUM_BYTES_ID) == 0)
   1924         {
   1925             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_LYRICS;
   1926         }
   1927 
   1928         // For the seek frame.
   1929         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_SEEK, ID3V2_FRAME_NUM_BYTES_ID) == 0)
   1930         {
   1931             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_SEEK;
   1932         }
   1933         //new frames support
   1934         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_AUTHOR, ID3V2_FRAME_NUM_BYTES_ID) == 0)
   1935         {
   1936             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_AUTHOR;
   1937         }
   1938         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_COMPOSER, ID3V2_FRAME_NUM_BYTES_ID) == 0)
   1939         {
   1940             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_COMPOSER;
   1941         }
   1942         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_DESCRIPTION, ID3V2_FRAME_NUM_BYTES_ID) == 0)
   1943         {
   1944             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_DESCRIPTION;
   1945         }
   1946         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_VERSION, ID3V2_FRAME_NUM_BYTES_ID) == 0)
   1947         {
   1948             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_VERSION;
   1949         }
   1950         else if (oscl_memcmp(pFrameID, endTestBuf, ID3V2_FRAME_NUM_BYTES_ID) == 0)
   1951         {
   1952             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_EEND;
   1953         }
   1954         else if (oscl_memcmp(pFrameID, endTestBuf, ID3V2_FRAME_NUM_BYTES_ID) == 0)
   1955         {
   1956             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_EEND;
   1957         }
   1958         else
   1959         {
   1960             // Find whether frame is invalid or unsupported
   1961             ID3V2FrameTypeReturnValue = FrameValidatedID3V2_4(pFrameID);
   1962         }
   1963     }
   1964     return ID3V2FrameTypeReturnValue;
   1965 }
   1966 
   1967 //----------------------------------------------------------------------------
   1968 // FUNCTION NAME: PVID3ParCom::FrameSupportedID3V2_2(void)
   1969 //----------------------------------------------------------------------------
   1970 // INPUT AND OUTPUT DEFINITIONS
   1971 //
   1972 //  Inputs: None
   1973 //
   1974 //  Outputs: None
   1975 //
   1976 //  Returns:
   1977 //    ID3V2_2FrameTypeReturnValue - The value that describes the current frame.
   1978 //                                of type enum TID3V2FrameType
   1979 //
   1980 //  Global Variables Used:
   1981 //    TID3V2_2FrameType - The enum table containing the supported frame types
   1982 //
   1983 //----------------------------------------------------------------------------
   1984 // FUNCTION DESCRIPTION
   1985 //
   1986 //  This function detects the ID3V2_2FrameType and returns the enum value that
   1987 //  corresponds to the current frame.
   1988 //
   1989 //------------------------------------------------------------------------------
   1990 
   1991 PVID3ParCom::PVID3FrameType PVID3ParCom::FrameSupportedID3V2_2(void)
   1992 {
   1993     uint8 endTestBuf[ID3V2_2_FRAME_NUM_BYTES_ID] = {0};
   1994     PVID3FrameType ID3V2_2FrameTypeReturnValue;
   1995 
   1996     if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_TITLE, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
   1997     {
   1998         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_TITLE;
   1999         iTitleFoundFlag = true;
   2000     }
   2001     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_ARTIST, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
   2002     {
   2003         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_ARTIST;
   2004         iArtistFoundFlag = true;
   2005     }
   2006     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_PART_OF_SET, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
   2007     {
   2008         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_PART_OF_SET;
   2009     }
   2010     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_ALBUM, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
   2011     {
   2012         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_ALBUM;
   2013         iAlbumFoundFlag = true;
   2014     }
   2015     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_COPYRIGHT, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
   2016     {
   2017         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_COPYRIGHT;
   2018     }
   2019     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_GENRE, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
   2020     {
   2021         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_GENRE;
   2022         iGenereFoundFlag = true;
   2023     }
   2024     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_TRACK_NUMBER, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
   2025     {
   2026         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_TRACK_NUMBER;
   2027         iTrackNumberFoundFlag = true;
   2028     }
   2029     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_TRACK_LENGTH, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
   2030     {
   2031         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_TRACK_LENGTH;
   2032     }
   2033     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_COMMENT, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
   2034     {
   2035         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_COMMENT;
   2036         iCommentFoundFlag = true;
   2037     }
   2038     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_YEAR, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
   2039     {
   2040         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_YEAR;
   2041         iYearFoundFlag = true;
   2042     }
   2043     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_DATE, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
   2044     {
   2045         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_DATE;
   2046     }
   2047     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_ALBUMART, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
   2048     {
   2049         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_PIC;
   2050     }
   2051     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_LYRICIST, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
   2052     {
   2053         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_LYRICS;
   2054     }
   2055 //new frames support
   2056     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_AUTHOR, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
   2057     {
   2058         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_AUTHOR;
   2059     }
   2060     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_COMPOSER, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
   2061     {
   2062         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_COMPOSER;
   2063     }
   2064     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_DESCRIPTION, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
   2065     {
   2066         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_DESCRIPTION;
   2067     }
   2068     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_VERSION, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
   2069     {
   2070         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_VERSION;
   2071     }
   2072 
   2073     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, endTestBuf, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
   2074     {
   2075         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_EEND;
   2076     }
   2077 
   2078     else
   2079     {
   2080         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_UNRECOGNIZED;
   2081     }
   2082 
   2083     return ID3V2_2FrameTypeReturnValue;
   2084 }
   2085 
   2086 //----------------------------------------------------------------------------
   2087 // FUNCTION NAME: PVID3ParCom::EightBitToWideCharBufferTransfer(
   2088 //                                               const TPtr8& aPtrFrameData8,
   2089 //                                               uint32         aSize,
   2090 //                                               uint32         aEndianType,
   2091 //                                               TPtr16&      aPtrFrameData16)
   2092 //----------------------------------------------------------------------------
   2093 // INPUT AND OUTPUT DEFINITIONS
   2094 //
   2095 //  Inputs:
   2096 //    aPtrFrameData8  - pointer to intput string format of either big
   2097 //                      or little endian.
   2098 //    aSize           - number of character elements in aPtrFrameData8
   2099 //    aEndianType     - This describes if the encoded Unicode text in the
   2100 //                      aPtrFrameData8 buffer is in big or little endian.
   2101 //  Outputs:
   2102 //    aPtrFrameDataWCBase - pointer to the output string in unicode format.
   2103 //
   2104 //  Returns: size of data in aPtrFrameDataWCBase
   2105 //
   2106 //  Global Variables Used: None
   2107 //
   2108 //----------------------------------------------------------------------------
   2109 // FUNCTION DESCRIPTION
   2110 //
   2111 //  This function moves unicode data sotred in uint8 buffer to wchar buffer.
   2112 //  The endian is taken care of by this function as well.
   2113 //
   2114 //------------------------------------------------------------------------------
   2115 uint32 PVID3ParCom::EightBitToWideCharBufferTransfer(const uint8 * aPtrFrameData8,
   2116         uint32        aSize,
   2117         uint32        aEndianType,
   2118         oscl_wchar  * aPtrFrameDataWCBase)
   2119 {
   2120     if (aPtrFrameData8 == NULL || aPtrFrameDataWCBase == NULL)
   2121     {
   2122         return 0;
   2123     }
   2124 
   2125     oscl_wchar * aPtrFrameDataWC = aPtrFrameDataWCBase;
   2126     uint16 tempFrameData16;
   2127     oscl_wchar tempFrameDataWC = 0;
   2128     uint32 index = 0;
   2129     uint32 z = 0, x = 0;
   2130     uint8 tempByteOne, tempByteTwo;
   2131     if (aEndianType != UNICODE_BIG_ENDIAN)
   2132         // Indication check of big-endian vs. little endian
   2133     {
   2134         z = 0;
   2135         for (x = 0; x < (aSize >> 1); x++)
   2136         {
   2137             z = x << 1;
   2138             tempByteOne = aPtrFrameData8[z];
   2139             tempByteTwo = aPtrFrameData8[z + 1];
   2140             if ((tempByteOne == 0) && (tempByteTwo == 0))
   2141             {
   2142                 x++;
   2143                 // End of string here and skip to start of next string.
   2144                 aPtrFrameDataWC[index++] = ((oscl_wchar)'\0');
   2145             }
   2146             else
   2147             {
   2148                 tempFrameData16 = (uint16)((((uint16)(tempByteTwo << 8)) | tempByteOne));
   2149                 tempFrameDataWC = tempFrameData16;
   2150                 aPtrFrameDataWC[index++] = tempFrameDataWC;
   2151             }
   2152         }
   2153     }
   2154     else
   2155     {
   2156         z = 0;
   2157         for (x = 0; x < (aSize >> 1); x++)
   2158         {
   2159             z = x << 1;
   2160             tempByteOne = aPtrFrameData8[z];
   2161             tempByteTwo = aPtrFrameData8[z + 1];
   2162             if ((tempByteTwo == 0) && (tempByteOne == 0))
   2163             {
   2164                 x++;
   2165                 // End of string here and skip to start of next string.
   2166                 aPtrFrameDataWC[index++] = ((oscl_wchar)'\0');
   2167             }
   2168             else
   2169             {
   2170                 tempFrameData16 = (uint16)((((uint16)(tempByteOne << 8)) | tempByteTwo));
   2171                 int32 l = sizeof(oscl_wchar);
   2172                 if (l == 4)
   2173                     tempFrameDataWC = (tempFrameData16 << 16) && 0xff00;
   2174                 else if (l == 2)
   2175                     tempFrameDataWC = tempFrameData16;
   2176                 else
   2177                     return 0;
   2178                 aPtrFrameDataWC[index++] = tempFrameDataWC;
   2179             }
   2180         }
   2181     }
   2182     return (index);
   2183 }
   2184 
   2185 uint32 PVID3ParCom::ConvertToSyncSafeInt(uint32 src)
   2186 {
   2187     uint32  dest = (src & 0x0FE00000) << 3;
   2188     dest |= (src & 0x001FC000) << 2;
   2189     dest |= (src & 0x00003f80) << 1;
   2190     dest |= (src & 0x0000007f);
   2191 
   2192     return dest;
   2193 }
   2194 
   2195 ////////////////////////////////////////////////////////////////////////////
   2196 uint32 PVID3ParCom::SafeSynchIntToInt32(uint32 aSafeSynchInteger)
   2197 {
   2198     uint8 * pBuf = (uint8 *) & (aSafeSynchInteger);
   2199     uint8 tmpByte = 0;
   2200     int32 i = 0;
   2201     uint32 integer = 0;
   2202 
   2203     // This loop will calculate the correct size from the bytes designated for size
   2204     // It is stored as a SynchSafe Integer. This means the 8th bit is reserved in
   2205     // each byte and not used for integer precision.. The number is effectively 28
   2206     // bits in length/precision.
   2207     // Assumes: sizeof(uint32) = 4 Bytes
   2208     for (i = 0; i < 4; i++)
   2209     {
   2210 #if (OSCL_BYTE_ORDER_LITTLE_ENDIAN)
   2211         tmpByte = (uint8)(pBuf[i] & MASK127);
   2212 #elif (OSCL_BYTE_ORDER_BIG_ENDIAN)
   2213         tmpByte = pBuf[4-i-1] & MASK127;
   2214 #else
   2215 #error "Must Specify ENDIANNESS"
   2216 #endif
   2217         // now shift the data to it's correct place
   2218         integer += tmpByte << VALID_BITS_IN_SYNC_SAFE_BYTE * i;
   2219     }
   2220 
   2221     return integer;
   2222 }
   2223 
   2224 ////////////////////////////////////////////////////////////////////////////
   2225 bool PVID3ParCom::readByteData(PVFile* aInputFile, uint32 length, uint8 *aData)
   2226 {
   2227     if (length > 0)
   2228     {
   2229         uint32 bytesRead;
   2230         bytesRead = aInputFile->Read(aData, 1, length);
   2231 
   2232         if (bytesRead < (uint32)length) // read byte data failed
   2233         {
   2234             return false;
   2235         }
   2236     }
   2237     return true;
   2238 }
   2239 
   2240 ////////////////////////////////////////////////////////////////////////////
   2241 bool PVID3ParCom::read32(PVFile* aInputFile, uint32 &aData)
   2242 {
   2243     const int32 N = 4;
   2244     uint8 bytes[N];
   2245     aData = 0;
   2246 
   2247     int32 retVal = (int32)(aInputFile->Read((void*)bytes, 1, N));
   2248 
   2249     if (retVal < N)
   2250         return false;
   2251 
   2252     for (int32 i = 0; i < N; i++)
   2253         aData = (aData << 8) | bytes[i];
   2254 
   2255     return true;
   2256 }
   2257 ////////////////////////////////////////////////////////////////////////////
   2258 bool PVID3ParCom::read16(PVFile* aInputFile, uint16 &aData)
   2259 {
   2260     const int32 N = 2;
   2261     uint8 bytes[N];
   2262     aData = 0;
   2263 
   2264     int32 retVal = (int32)(aInputFile->Read((void*)bytes, 1, N));
   2265 
   2266     if (retVal < N)
   2267         return false;
   2268 
   2269     for (int32 i = 0; i < N; i++)
   2270         aData = (uint16)((aData << 8) | bytes[i]);
   2271 
   2272     return true;
   2273 }
   2274 
   2275 ////////////////////////////////////////////////////////////////////////////
   2276 bool PVID3ParCom::read24(PVFile* aInputFile, uint32 &aData)
   2277 {
   2278     const int32 N = 3;
   2279     uint8 bytes[N];
   2280     aData = 0;
   2281 
   2282     int32 retVal = (int32)(aInputFile->Read((void*)bytes, 1, N));
   2283 
   2284     if (retVal < N)
   2285         return false;
   2286 
   2287     for (int32 i = 0; i < N; i++)
   2288         aData = (aData << 8) | bytes[i];
   2289 
   2290     return true;
   2291 }
   2292 
   2293 ////////////////////////////////////////////////////////////////////////////
   2294 bool PVID3ParCom::read8(PVFile* aInputFile, uint8 &aData)
   2295 {
   2296     aData = 0;
   2297 
   2298     int32 retVal = (int32)(aInputFile->Read((void*) & aData, 1, 1));
   2299 
   2300     if (retVal < 1)
   2301         return false;
   2302 
   2303     return true;
   2304 }
   2305 
   2306 ////////////////////////////////////////////////////////////////////////////
   2307 
   2308 PvmiKvpSharedPtr PVID3ParCom::AllocateKvp(OSCL_String& aKey, PvmiKvpValueType aValueType, uint32 aValueSize, bool &truncate)
   2309 {
   2310     uint8* myPtr = NULL;
   2311     OsclRefCounter* refCounter;
   2312 
   2313     uint aligned_refcnt_size = oscl_mem_aligned_size(sizeof(OsclRefCounterDA));
   2314     uint aligned_cleanup_size = oscl_mem_aligned_size(sizeof(PVID3ParComKvpCleanupDA));
   2315     uint aligned_kvp_size = oscl_mem_aligned_size(sizeof(PvmiKvp));
   2316     uint32 key_size = oscl_mem_aligned_size(aKey.get_size() + 1);
   2317     uint32 total_size = aligned_refcnt_size + aligned_cleanup_size +
   2318                         aligned_kvp_size + key_size + aValueSize;
   2319 
   2320     int32 error = 0;
   2321     myPtr = (uint8*) AllocateValueArray(error, PVMI_KVPVALTYPE_UINT8PTR, total_size, &iAlloc);
   2322     if ((error != OsclErrNone) || (!myPtr) || (total_size < aValueSize))
   2323     {
   2324         if (myPtr)
   2325         {
   2326             iAlloc.deallocate(myPtr);
   2327         }
   2328 
   2329         char str_data_len[MAX_RANGE_INT_SIZE + 1] = {0};
   2330         oscl_snprintf(str_data_len, MAX_RANGE_INT_SIZE + 1, "%d", aValueSize);
   2331         aKey += SEMI_COLON;
   2332         aKey += KVP_VALTYPE_REQSIZE;
   2333         aKey += _STRLIT_CHAR((char *)str_data_len);
   2334         uint32 new_key_size = oscl_mem_aligned_size(aKey.get_size() + 1);
   2335         error = OsclErrNone;
   2336         total_size = aligned_refcnt_size + aligned_cleanup_size + aligned_kvp_size + new_key_size;
   2337         myPtr = (uint8*) AllocateValueArray(error, PVMI_KVPVALTYPE_UINT8PTR, total_size, &iAlloc);
   2338         truncate = true;
   2339         if (OsclErrNone != error)
   2340         {
   2341             OSCL_LEAVE(OsclErrNoMemory);
   2342         }
   2343     }
   2344     oscl_memset(myPtr, 0, total_size);
   2345 
   2346     PVID3ParComKvpCleanupDA* kvpCleanup = OSCL_PLACEMENT_NEW(myPtr + aligned_refcnt_size, PVID3ParComKvpCleanupDA(&iAlloc));
   2347     refCounter = OSCL_PLACEMENT_NEW(myPtr, OsclRefCounterDA(myPtr, kvpCleanup));
   2348     myPtr += aligned_refcnt_size + aligned_cleanup_size;
   2349 
   2350     PvmiKvp* kvp = OSCL_STATIC_CAST(PvmiKvp *, myPtr) ;
   2351     myPtr += aligned_kvp_size;
   2352 
   2353     kvp->key = OSCL_STATIC_CAST(char* , myPtr);
   2354     myPtr += key_size;
   2355     oscl_strncpy(kvp->key, aKey.get_cstr(), key_size);
   2356     if (!truncate)
   2357     {
   2358         switch (aValueType)
   2359         {
   2360             case PVMI_KVPVALTYPE_WCHARPTR:
   2361                 kvp->value.pWChar_value = OSCL_STATIC_CAST(oscl_wchar*, myPtr);
   2362                 break;
   2363             case PVMI_KVPVALTYPE_CHARPTR:
   2364                 kvp->value.pChar_value = OSCL_STATIC_CAST(char* , myPtr);
   2365                 break;
   2366             case PVMI_KVPVALTYPE_UINT8PTR:
   2367                 kvp->value.pUint8_value = OSCL_STATIC_CAST(uint8*, myPtr);
   2368                 break;
   2369             case PVMI_KVPVALTYPE_INT32PTR:
   2370                 kvp->value.pInt32_value = OSCL_STATIC_CAST(int32*, myPtr);
   2371                 break;
   2372             case PVMI_KVPVALTYPE_UINT32PTR:
   2373                 kvp->value.pUint32_value = OSCL_STATIC_CAST(uint32*, myPtr);
   2374                 break;
   2375             case PVMI_KVPVALTYPE_INT64PTR:
   2376                 kvp->value.pInt64_value = OSCL_STATIC_CAST(int64* , myPtr);
   2377                 break;
   2378             case PVMI_KVPVALTYPE_UINT64PTR:
   2379                 kvp->value.pUint64_value = OSCL_STATIC_CAST(uint64* , myPtr);
   2380                 break;
   2381             case PVMI_KVPVALTYPE_FLOATPTR:
   2382                 kvp->value.pFloat_value = OSCL_STATIC_CAST(float* , myPtr);
   2383                 break;
   2384             case PVMI_KVPVALTYPE_DOUBLEPTR:
   2385                 kvp->value.pDouble_value = OSCL_STATIC_CAST(double*, myPtr);
   2386                 break;
   2387             case PVMI_KVPVALTYPE_KSV:
   2388                 kvp->value.key_specific_value = OSCL_STATIC_CAST(OsclAny*, myPtr);
   2389             default:
   2390                 break;
   2391         }
   2392         kvp->length = aValueSize;
   2393         kvp->capacity = aValueSize;
   2394     }
   2395     else
   2396     {
   2397         kvp->length = 0;
   2398         kvp->capacity = 0;
   2399 
   2400     }
   2401     PvmiKvpSharedPtr sharedPtr(kvp, refCounter);
   2402     return sharedPtr;
   2403 }
   2404 
   2405 ////////////////////////////////////////////////////////////////////////////
   2406 PVMFStatus PVID3ParCom::ConstructKvpKey(OSCL_String& aKey, PVID3FrameType aType, PVID3CharacterSet aCharSet)
   2407 {
   2408     aKey = _STRLIT_CHAR("");
   2409 
   2410     switch (aType)
   2411     {
   2412         case PV_ID3_FRAME_TITLE:
   2413             aKey += _STRLIT_CHAR(KVP_KEY_TITLE);
   2414             break;
   2415         case PV_ID3_FRAME_ARTIST:
   2416             aKey += _STRLIT_CHAR(KVP_KEY_ARTIST);
   2417             break;
   2418         case PV_ID3_FRAME_PART_OF_SET:
   2419             aKey += _STRLIT_CHAR(KVP_KEY_PART_OF_SET);
   2420             break;
   2421         case PV_ID3_FRAME_ALBUM:
   2422             aKey += _STRLIT_CHAR(KVP_KEY_ALBUM);
   2423             break;
   2424         case PV_ID3_FRAME_COPYRIGHT:
   2425             aKey += _STRLIT_CHAR(KVP_KEY_COPYRIGHT);
   2426             break;
   2427         case PV_ID3_FRAME_GENRE:
   2428             aKey += _STRLIT_CHAR(KVP_KEY_GENRE);
   2429             if (aCharSet == PV_ID3_CHARSET_INVALID)
   2430             {
   2431                 // ID3 V1 genre is a uint32 value
   2432                 aKey += SEMI_COLON;
   2433                 aKey += _STRLIT_CHAR(PVMI_KVPVALTYPE_STRING);
   2434                 aKey += _STRLIT_CHAR(PVMI_KVPVALTYPE_UINT32_STRING);
   2435                 aKey += SEMI_COLON;
   2436                 aKey += _STRLIT_CHAR(KVP_FORMAT_ID3V1);
   2437                 return PVMFSuccess;
   2438             }
   2439             break;
   2440         case PV_ID3_FRAME_TRACK_NUMBER:
   2441             aKey += _STRLIT_CHAR(KVP_KEY_TRACKINFO_TRACK_NUMBER);
   2442             if (aCharSet == PV_ID3_CHARSET_INVALID)
   2443             {
   2444                 // ID3 V1 track number is a uint32 value
   2445                 aKey += SEMI_COLON;
   2446                 aKey += _STRLIT_CHAR(PVMI_KVPVALTYPE_STRING);
   2447                 aKey += _STRLIT_CHAR(PVMI_KVPVALTYPE_UINT32_STRING);
   2448                 return PVMFSuccess;
   2449             }
   2450             break;
   2451         case PV_ID3_FRAME_YEAR:
   2452             aKey += _STRLIT_CHAR(KVP_KEY_YEAR);
   2453             break;
   2454         case PV_ID3_FRAME_DATE:
   2455             aKey += _STRLIT_CHAR(KVP_KEY_DATE);
   2456             break;
   2457         case PV_ID3_FRAME_RECORDING_TIME:
   2458             aKey += _STRLIT_CHAR(KVP_KEY_RECORDING_TIME);
   2459             break;
   2460 //new frames support
   2461         case PV_ID3_FRAME_AUTHOR:
   2462             aKey += _STRLIT_CHAR(KVP_KEY_AUTHOR);
   2463             break;
   2464         case PV_ID3_FRAME_COMPOSER:
   2465             aKey += _STRLIT_CHAR(KVP_KEY_COMPOSER);
   2466             break;
   2467         case PV_ID3_FRAME_DESCRIPTION:
   2468             aKey += _STRLIT_CHAR(KVP_KEY_DESCRIPTION);
   2469             break;
   2470         case PV_ID3_FRAME_VERSION:
   2471             aKey += _STRLIT_CHAR(KVP_KEY_VERSION);
   2472             break;
   2473         case PV_ID3_FRAME_COMMENT:
   2474             aKey += _STRLIT_CHAR(KVP_KEY_COMMENT);
   2475             if ((iVersion != PV_ID3_V1_1) && (iVersion != PV_ID3_V1))
   2476             {
   2477                 aKey += SEMI_COLON;
   2478                 aKey += KVP_VALTYPE_LYRICS;
   2479             }
   2480             break;
   2481         case PV_ID3_FRAME_TRACK_LENGTH:
   2482             aKey += _STRLIT_CHAR(KVP_KEY_ID3DURATION);
   2483             aKey += SEMI_COLON;
   2484             aKey += _STRLIT_CHAR(KVP_VALTYPE_DURATION);
   2485             return PVMFSuccess; // No character set for track length
   2486         case PV_ID3_FRAME_PIC:
   2487         case PV_ID3_FRAME_APIC:
   2488             aKey += _STRLIT_CHAR(KVP_KEY_ALBUMART);
   2489             aKey += SEMI_COLON;
   2490             return PVMFSuccess;
   2491         case PV_ID3_FRAME_LYRICS:
   2492             aKey += _STRLIT_CHAR(KVP_KEY_LYRICS);
   2493             aKey += SEMI_COLON;
   2494             aKey += KVP_VALTYPE_LYRICS;
   2495             break;
   2496         case PV_ID3_FRAME_UNRECOGNIZED:
   2497         case PV_ID3_FRAME_CANDIDATE:
   2498             aKey += _STRLIT_CHAR(KVP_ID3V2_VALUE);
   2499             aKey += FORWARD_SLASH;
   2500             aKey += _STRLIT_CHAR((char *)iID3TagInfo.iID3V2FrameID);
   2501             aKey += SEMI_COLON;
   2502             aKey += _STRLIT_CHAR(KVP_VALTYPE_UINT8PTR_STRING);
   2503             return PVMFSuccess;
   2504             break;
   2505         default:
   2506             return PVMFErrNotSupported;
   2507     }
   2508 
   2509 
   2510     //add language code to lyrics key
   2511     if ((aType == PV_ID3_FRAME_LYRICS) || (aType == PV_ID3_FRAME_COMMENT))
   2512     {
   2513         //not valid for id3 v1
   2514         if ((iVersion != PV_ID3_V1_1) && (iVersion != PV_ID3_V1))
   2515         {
   2516             aKey += SEMI_COLON;
   2517             aKey += _STRLIT_CHAR(KVP_PARAM_LANGUAGE_CODE);
   2518             aKey += _STRLIT_CHAR((char*)iID3TagInfo.iID3V2LanguageID);
   2519             return PVMFSuccess;
   2520         }
   2521     }
   2522     aKey += SEMI_COLON;
   2523     switch (aCharSet)
   2524     {
   2525         case PV_ID3_CHARSET_ISO88591:
   2526             aKey += _STRLIT_CHAR(KVP_VALTYPE_ISO88591_CHAR);
   2527             break;
   2528         case PV_ID3_CHARSET_UTF16:
   2529             aKey += _STRLIT_CHAR(KVP_VALTYPE_UTF16_WCHAR);
   2530             break;
   2531         case PV_ID3_CHARSET_UTF16BE:
   2532             aKey += _STRLIT_CHAR(KVP_VALTYPE_UTF16BE_WCHAR);
   2533             break;
   2534         case PV_ID3_CHARSET_UTF8:
   2535             aKey += _STRLIT_CHAR(KVP_VALTYPE_UTF8_CHAR);
   2536             break;
   2537         default:
   2538             return PVMFErrNotSupported;
   2539     }
   2540 
   2541     aKey += NULL_CHARACTER;
   2542 
   2543     return PVMFSuccess;
   2544 }
   2545 
   2546 ////////////////////////////////////////////////////////////////////////////
   2547 PVMFStatus PVID3ParCom::ReadStringValueFrame(PVID3FrameType aFrameType, PVID3CharacterSet aCharSet, uint32 aValueSize)
   2548 {
   2549     // Construct key string
   2550     OSCL_StackString<128> keyStr;
   2551     if (ConstructKvpKey(keyStr, aFrameType, aCharSet) != PVMFSuccess)
   2552     {
   2553         LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - ConstructKvpKey failed"));
   2554         return PVMFErrNotSupported;
   2555     }
   2556 
   2557     // Allocate key-value pair
   2558     int32 err = OsclErrNone;
   2559     PvmiKvpSharedPtr kvpPtr;
   2560     bool truncate = false;
   2561     switch (aCharSet)
   2562     {
   2563         case PV_ID3_CHARSET_ISO88591:
   2564         case PV_ID3_CHARSET_UTF8:
   2565             OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_CHARPTR, aValueSize + 1, truncate););
   2566             if (OsclErrNone != err || !kvpPtr)
   2567             {
   2568                 LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - AllocateKvp failed. err=%d", err));
   2569                 return PVMFErrNoMemory;
   2570             }
   2571 
   2572             if (truncate)
   2573             {
   2574                 iInputFile->Seek(aValueSize, Oscl_File::SEEKCUR);
   2575                 kvpPtr->length = 0;
   2576             }
   2577             else
   2578             {
   2579                 if (readByteData(iInputFile, aValueSize, (uint8*)kvpPtr->value.pChar_value) == false)
   2580                 {
   2581                     LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - readByteData failed"));
   2582                     return PVMFFailure;
   2583                 }
   2584 
   2585                 int32 valueLen = aValueSize;
   2586                 valueLen = oscl_strlen((char*)kvpPtr->value.pChar_value);
   2587 
   2588                 kvpPtr->value.pChar_value[valueLen] = NULL_TERM_CHAR;
   2589                 kvpPtr->length = valueLen + 1;
   2590             }
   2591             // Add to frame vector
   2592             OSCL_TRY(err, iFrames.push_back(kvpPtr););
   2593             OSCL_FIRST_CATCH_ANY(err,
   2594                                  LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - iFrames.push_back failed. err=%d", err));
   2595                                  return PVMFErrNoMemory;
   2596                                 );
   2597             break;
   2598 
   2599         case PV_ID3_CHARSET_UTF16:
   2600         case PV_ID3_CHARSET_UTF16BE:
   2601         {
   2602             // create buffers to store frame data
   2603             uint8* ptrFrameData = NULL;
   2604             ptrFrameData = (uint8*) AllocateValueArray(err, PVMI_KVPVALTYPE_UINT8PTR, aValueSize + 2, &iAlloc);
   2605             if (OsclErrNone != err || !ptrFrameData)
   2606             {
   2607                 LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - frameData allocation failed"));
   2608                 return PVMFErrNoMemory;
   2609             }
   2610             oscl_memset(ptrFrameData, 0, aValueSize + 2);
   2611             uint32 wchar_size = sizeof(oscl_wchar); //for platforms where wchar is 4 bytes.
   2612             // Allocate key-value pair
   2613             OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_WCHARPTR, (wchar_size / 2) * (aValueSize + 2), truncate););
   2614             if (OsclErrNone != err || !kvpPtr)
   2615             {
   2616                 LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - AllocateKvp failed. err=%d", err));
   2617                 return PVMFErrNoMemory;
   2618             }
   2619 
   2620             if (truncate)
   2621             {
   2622                 iAlloc.deallocate(ptrFrameData);
   2623                 iInputFile->Seek(aValueSize, Oscl_File::SEEKCUR);
   2624                 kvpPtr->length = 0;
   2625             }
   2626             else
   2627             {
   2628                 if (readByteData(iInputFile, aValueSize, ptrFrameData) == false)
   2629                 {
   2630                     iAlloc.deallocate(ptrFrameData);
   2631                     LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - readByteData failed"));
   2632                     return PVMFFailure;
   2633                 }
   2634                 ptrFrameData[aValueSize] = 0;
   2635                 ptrFrameData[aValueSize+1] = 0;
   2636 
   2637                 uint32 endianType = UNICODE_LITTLE_ENDIAN;
   2638                 if (aCharSet == PV_ID3_CHARSET_UTF16BE)
   2639                 {
   2640                     endianType = UNICODE_BIG_ENDIAN;
   2641                 }
   2642 
   2643                 uint32 wcSize = EightBitToWideCharBufferTransfer(ptrFrameData, aValueSize, endianType, kvpPtr->value.pWChar_value);
   2644                 kvpPtr->value.pWChar_value[wcSize] = NULL_TERM_CHAR;
   2645                 iAlloc.deallocate(ptrFrameData);
   2646                 kvpPtr->length = wcSize;
   2647             }
   2648             OSCL_TRY(err, iFrames.push_back(kvpPtr););
   2649             OSCL_FIRST_CATCH_ANY(err,
   2650                                  LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - iFrame.push_back failed"));
   2651                                  iAlloc.deallocate((OsclAny*)ptrFrameData);
   2652                                  return PVMFErrNoMemory;
   2653                                 );
   2654         }
   2655         break;
   2656         default:
   2657             return PVMFFailure;
   2658     }
   2659 
   2660     return PVMFSuccess;
   2661 }
   2662 
   2663 
   2664 ////////////////////////////////////////////////////////////////////////////
   2665 PVMFStatus PVID3ParCom::ReadFrame(PVID3FrameType aFrameType, uint32 aValueSize)
   2666 {
   2667 
   2668     // Construct key string
   2669     OSCL_StackString<128> keyStr;
   2670     if (ConstructKvpKey(keyStr, aFrameType, PV_ID3_CHARSET_INVALID) != PVMFSuccess)
   2671     {
   2672         LOG_ERR((0, "PVID3ParCom::ReadFrame: Error - ConstructKvpKey failed"));
   2673         return PVMFErrNotSupported;
   2674     }
   2675 
   2676     // Allocate key-value pair
   2677     int32 err = OsclErrNone;
   2678     PvmiKvpSharedPtr kvpPtr;
   2679     bool truncate = false;
   2680     OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_CHARPTR, aValueSize + 1 + VERSION_SIZE, truncate););
   2681     if (OsclErrNone != err || !kvpPtr)
   2682     {
   2683         LOG_ERR((0, "PVID3ParCom::ReadFrame: Error - AllocateKvp failed. err=%d", err));
   2684         return PVMFErrNoMemory;
   2685     }
   2686 
   2687     if (truncate)
   2688     {
   2689         iInputFile->Seek(aValueSize, Oscl_File::SEEKCUR);
   2690         kvpPtr->length = 0;
   2691     }
   2692     else
   2693     {
   2694         kvpPtr->value.pUint8_value[0] = (uint8)iVersion;
   2695         kvpPtr->value.pUint8_value[1] = 0;
   2696 
   2697         if (readByteData(iInputFile, aValueSize, (uint8*)kvpPtr->value.pUint8_value + VERSION_SIZE) == false)
   2698         {
   2699             LOG_ERR((0, "PVID3ParCom::ReadFrame: Error - readByteData failed"));
   2700             return PVMFFailure;
   2701         }
   2702         kvpPtr->value.pUint8_value[aValueSize+VERSION_SIZE] = 0;
   2703         kvpPtr->length = aValueSize + VERSION_SIZE;
   2704     }
   2705     // Add to frame vector
   2706     OSCL_TRY(err, iFrames.push_back(kvpPtr););
   2707     OSCL_FIRST_CATCH_ANY(err,
   2708                          LOG_ERR((0, "PVID3ParCom::ReadFrame: Error - iFrames.push_back failed. err=%d", err));
   2709                          return PVMFErrNoMemory;
   2710                         );
   2711 
   2712 
   2713     return PVMFSuccess;
   2714 }
   2715 
   2716 
   2717 ////////////////////////////////////////////////////////////////////////////
   2718 
   2719 // Read in a NULL terminated UNICODE string byte by byte and take most significant byte first
   2720 PVMFStatus
   2721 PVID3ParCom::readNullTerminatedUnicodeString(PVFile* aInputFile, OSCL_wHeapString<OsclMemAllocator> &aData, uint32 &bomSz)
   2722 {
   2723     uint8 buff[ID3_MAX_STRING_FRAME_LEN];
   2724     uint32 index = 0;
   2725     uint16 endianCheck;
   2726     if (read16(aInputFile, endianCheck) == false)
   2727     {
   2728         return PVMFFailure;
   2729     }
   2730 
   2731     iID3TagInfo.iTextType = PV_ID3_CHARSET_UTF16;
   2732     uint32 endianType = 0;
   2733 
   2734     //some id3 tools does not add BOM with null strings.
   2735     if (endianCheck != 0)
   2736     {
   2737         bomSz = UNICODE_BOM_SIZE;
   2738         // This frame's text strings are Unicode and the frame
   2739         // does include a BOM value. (UTF-16)
   2740         if (endianCheck == UNICODE_LITTLE_ENDIAN_INDICATOR_FULL)
   2741         {
   2742             endianType = UNICODE_LITTLE_ENDIAN;
   2743         }
   2744         else if (endianCheck == UNICODE_BIG_ENDIAN_INDICATOR_FULL)
   2745         {
   2746             endianType = UNICODE_BIG_ENDIAN;
   2747         }
   2748         //read frame data from file
   2749         bool more = true;
   2750         while (more && (index < ID3_MAX_STRING_FRAME_LEN))
   2751         {
   2752             if (read8(iInputFile, buff[index]) == false)
   2753                 return PVMFFailure;
   2754 
   2755             if ((index > 0) && (buff[index] == 0) && (buff[index -1] == 0))
   2756                 more = false;
   2757             index++;
   2758         }
   2759 
   2760         //read remaining characters if any.
   2761         if (more)
   2762         {
   2763             uint16 temp = 1;
   2764             while (temp != 0)
   2765                 if (read16(iInputFile, temp) == false)
   2766                     return PVMFFailure;
   2767         }
   2768 
   2769     }
   2770     else
   2771     {
   2772         buff[0] = 0;
   2773         buff[1] = 0;
   2774         bomSz = 0;
   2775         index = 2;
   2776     }
   2777 
   2778     int32 err = OsclErrNone;
   2779     oscl_wchar *tmpData = NULL;
   2780     tmpData = (oscl_wchar*) AllocateValueArray(err, PVMI_KVPVALTYPE_WCHARPTR, index);
   2781     if (OsclErrNone != err || !tmpData)
   2782     {
   2783         LOG_ERR((0, "PVID3ParCom::readNullTerminatedUnicodeString: Error - allocation failed"));
   2784         return PVMFErrNoMemory;
   2785     }
   2786 
   2787     uint32 wcSize = EightBitToWideCharBufferTransfer(buff, index, endianType, tmpData);
   2788     tmpData[wcSize] = 0;
   2789     aData = tmpData;
   2790     OSCL_ARRAY_DELETE(tmpData);
   2791     return PVMFSuccess;
   2792 }
   2793 
   2794 bool
   2795 PVID3ParCom::readNullTerminatedAsciiString(PVFile* aInputFile, OSCL_HeapString<OsclMemAllocator> &aData)
   2796 {
   2797     uint8 buf[256];
   2798     int32 index = 0;
   2799 
   2800     if (!read8(aInputFile, buf[index]))
   2801         return PVMFFailure;
   2802 
   2803     bool nextChar = (buf[index] == 0) ? false : true;
   2804 
   2805     while (nextChar && (index < 256))
   2806     {
   2807         index++;
   2808 
   2809         if (!read8(aInputFile, buf[index]))
   2810             return PVMFFailure;
   2811 
   2812         nextChar = (buf[index] == 0) ? false : true;
   2813     }
   2814 
   2815     OSCL_HeapString<OsclMemAllocator> temp((const char *)buf);
   2816     aData = temp;
   2817     return true;
   2818 }
   2819 
   2820 PVMFStatus PVID3ParCom::ReadAlbumArtFrame(PVID3FrameType aFrameType, uint8 unicode, uint32 aFrameSize)
   2821 {
   2822     PvmfApicStruct* aApicStruct = NULL;
   2823     uint8   picType;
   2824     uint32  dataLen;
   2825     OSCL_HeapString<OsclMemAllocator> ImageFormat;
   2826     bool pic_as_url = false;
   2827     bool truncate = false;
   2828     int32 err = OsclErrNone;
   2829     PvmiKvpSharedPtr kvpPtr;
   2830     OSCL_StackString<128> keyStr;
   2831 
   2832     if (ConstructKvpKey(keyStr, PV_ID3_FRAME_APIC, PV_ID3_CHARSET_INVALID) != PVMFSuccess)
   2833     {
   2834         LOG_ERR((0, "PVID3ParCom::ReadAlbumArtFrame: Error - ConstructKvpKey failed"));
   2835         return PVMFErrNotSupported;
   2836     }
   2837 
   2838     switch (unicode)
   2839     {
   2840         case PV_ID3_CHARSET_ISO88591:
   2841         case PV_ID3_CHARSET_UTF8:
   2842         {
   2843             OSCL_HeapString<OsclMemAllocator> description;
   2844 
   2845             if (GetAlbumArtInfo(aFrameType, aFrameSize, ImageFormat, picType, description, dataLen) != PVMFSuccess)
   2846                 return PVMFFailure;
   2847 
   2848             if (!oscl_strcmp(ImageFormat.get_cstr(), "-->"))
   2849             {
   2850                 pic_as_url = true;
   2851                 break;
   2852             }
   2853 
   2854             keyStr += KVP_FORMAT_ALBUMART;
   2855             keyStr += SEMI_COLON;
   2856             keyStr += KVP_VALTYPE_ALBUMART;
   2857 
   2858             //description and image format are stored as wchar.
   2859             uint32 rfs = aFrameSize - (ImageFormat.get_size() + description.get_size());
   2860             uint32 wchar_size = sizeof(oscl_wchar); //for platforms that store wchar as 4 bytes.
   2861             uint32 total_size = sizeof(PvmfApicStruct) + rfs + ((wchar_size) * (ImageFormat.get_size() + description.get_size())) + 2 * sizeof(oscl_wchar) ;
   2862 
   2863             // Allocate key-value pair
   2864             OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_KSV, total_size, truncate););
   2865             if (OsclErrNone != err || !kvpPtr)
   2866             {
   2867                 LOG_ERR((0, "PVID3ParCom::ReadAlbumArtFrame: Error - AllocateKvp failed. err=%d", err));
   2868                 return PVMFFailure;
   2869             }
   2870 
   2871             if (truncate)
   2872             {
   2873                 iInputFile->Seek(dataLen, Oscl_File::SEEKCUR);
   2874                 kvpPtr->capacity = 0;
   2875                 kvpPtr->length = 0;
   2876 
   2877                 OSCL_TRY(err, iFrames.push_back(kvpPtr););
   2878                 OSCL_FIRST_CATCH_ANY(err,
   2879                                      LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - iFrame.push_back failed"));
   2880                                      return PVMFErrNoMemory;);
   2881 
   2882                 return PVMFSuccess;
   2883 
   2884             }
   2885 
   2886             kvpPtr->capacity = total_size;
   2887             kvpPtr->length = total_size;
   2888 
   2889             //convert raw data to struct
   2890             PVMFStatus status;
   2891             status = ConvertAsciiDataToApic(ImageFormat.get_str(), description.get_str(), picType,
   2892                                             dataLen, kvpPtr->value.key_specific_value, total_size);
   2893         }
   2894         break;
   2895 
   2896 
   2897         case PV_ID3_CHARSET_UTF16:
   2898         case PV_ID3_CHARSET_UTF16BE:
   2899         {
   2900             OSCL_wHeapString<OsclMemAllocator> description;
   2901             if (GetAlbumArtInfo(aFrameType, aFrameSize, ImageFormat, picType, description, dataLen) != PVMFSuccess)
   2902                 return PVMFFailure;
   2903 
   2904             if (!oscl_strcmp(ImageFormat.get_cstr(), "-->"))
   2905             {
   2906                 pic_as_url = true;
   2907                 break;
   2908             }
   2909 
   2910             keyStr += KVP_FORMAT_ALBUMART;
   2911             keyStr += SEMI_COLON;
   2912             keyStr += KVP_VALTYPE_ALBUMART;
   2913 
   2914             //image format is stored as wchar.
   2915             uint32 rfs = aFrameSize - (ImageFormat.get_size() + (2 * oscl_strlen(description.get_str())));
   2916             uint32 wchar_size = sizeof(oscl_wchar); //for platforms that store wchar as 4 bytes.
   2917             uint32 total_size = sizeof(PvmfApicStruct) + rfs + (wchar_size * (ImageFormat.get_size() + description.get_size())) + (2 * wchar_size);
   2918 
   2919             // Allocate key-value pair
   2920             OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_KSV, total_size, truncate););
   2921             if (OsclErrNone != err || !kvpPtr)
   2922             {
   2923                 LOG_ERR((0, "PVID3ParCom::ReadAlbumArtFrame: Error - AllocateKvp failed. err=%d", err));
   2924                 return PVMFFailure;
   2925             }
   2926 
   2927             if (truncate)
   2928             {
   2929                 iInputFile->Seek(dataLen, Oscl_File::SEEKCUR);
   2930                 kvpPtr->capacity = 0;
   2931                 kvpPtr->length = 0;
   2932 
   2933                 OSCL_TRY(err, iFrames.push_back(kvpPtr););
   2934                 OSCL_FIRST_CATCH_ANY(err,
   2935                                      LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - iFrame.push_back failed"));
   2936                                      return PVMFErrNoMemory;);
   2937 
   2938                 return PVMFSuccess;
   2939 
   2940             }
   2941 
   2942             kvpPtr->capacity = total_size;
   2943             kvpPtr->length = total_size;
   2944 
   2945             //convert raw data to struct
   2946             PVMFStatus status;
   2947             status = ConvertUnicodeDataToApic(ImageFormat.get_str(), description.get_str(), picType,
   2948                                               dataLen , kvpPtr->value.key_specific_value, total_size);
   2949         }
   2950         break;
   2951         default:
   2952             return PVMFFailure;
   2953 
   2954     }
   2955 
   2956     if (pic_as_url)
   2957     {
   2958 
   2959         keyStr += KVP_VALTYPE_ISO88591_CHAR;
   2960         bool truncate = false;
   2961         // Allocate key-value pair
   2962         OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_CHARPTR, dataLen, truncate););
   2963         if (OsclErrNone != err || !kvpPtr)
   2964         {
   2965             LOG_ERR((0, "PVID3ParCom::ReadAlbumArtFrame: Error - AllocateKvp failed. err=%d", err));
   2966             return PVMFFailure;
   2967         }
   2968 
   2969         if (truncate)
   2970         {
   2971             iInputFile->Seek(dataLen, Oscl_File::SEEKCUR);
   2972             kvpPtr->length = 0;
   2973 
   2974             OSCL_TRY(err, iFrames.push_back(kvpPtr););
   2975             OSCL_FIRST_CATCH_ANY(err,
   2976                                  LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - iFrame.push_back failed"));
   2977                                  return PVMFErrNoMemory;);
   2978 
   2979             return PVMFSuccess;
   2980 
   2981         }
   2982         else
   2983         {
   2984             if (readByteData(iInputFile, dataLen, (uint8 *)kvpPtr->value.pChar_value) == false)
   2985                 return PVMFFailure;
   2986             kvpPtr->value.pChar_value[dataLen] = NULL_TERM_CHAR;
   2987             kvpPtr->length = dataLen;
   2988         }
   2989     }
   2990     else
   2991     {
   2992         aApicStruct = OSCL_STATIC_CAST(PvmfApicStruct *, kvpPtr->value.key_specific_value);
   2993         if (readByteData(iInputFile, dataLen, aApicStruct->iGraphicData) == false)
   2994             return PVMFFailure;
   2995     }
   2996 
   2997 
   2998     OSCL_TRY(err, iFrames.push_back(kvpPtr););
   2999     OSCL_FIRST_CATCH_ANY(err,
   3000                          LOG_ERR((0, "PVID3ParCom::ReadAlbumArtFrame: Error - iFrame.push_back failed"));
   3001                          return PVMFErrNoMemory;
   3002                         );
   3003 
   3004     return PVMFSuccess;
   3005 }
   3006 
   3007 PVMFStatus PVID3ParCom::ReadLyricsCommFrame(uint8 unicodeCheck, uint32 aFramesize, PVID3FrameType aFrameType)
   3008 {
   3009 
   3010     uint32 framesize = aFramesize;
   3011     bool truncate = false;
   3012     if (readByteData(iInputFile, ID3V2_LANGUAGE_SIZE, iID3TagInfo.iID3V2LanguageID) == false)
   3013     {
   3014         return PVMFFailure;
   3015     }
   3016 
   3017     iID3TagInfo.iID3V2LanguageID[ID3V2_LANGUAGE_SIZE] = 0;
   3018 
   3019     //subtract 3 bytes of language from the frame size.
   3020     framesize = aFramesize - ID3V2_LANGUAGE_SIZE ;
   3021     if ((framesize == 0) || (framesize > aFramesize))
   3022     {
   3023         return PVMFFailure;
   3024     }
   3025     //construct kvp for lyrics frame
   3026     OSCL_StackString<128> keyStr;
   3027     if (ConstructKvpKey(keyStr, aFrameType, (PVID3ParCom::PVID3CharacterSet)unicodeCheck) != PVMFSuccess)
   3028     {
   3029         LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - ConstructKvpKey failed"));
   3030         return PVMFErrNotSupported;
   3031     }
   3032 
   3033     int32 err = OsclErrNone;
   3034     PvmiKvpSharedPtr kvpPtr;
   3035     uint32 wchar_size = sizeof(oscl_wchar); //for platforms where wchar is 4 bytes.
   3036     uint32 total_size = (wchar_size * framesize) + sizeof(PvmfLyricsCommStruct) + (2 * wchar_size) ;
   3037     uint32 used_size = 0;
   3038     // Allocate key-value pair
   3039     OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_KSV, total_size , truncate););
   3040     if (OsclErrNone != err || !kvpPtr)
   3041     {
   3042         LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - AllocateKvp failed. err=%d", err));
   3043         return PVMFFailure;
   3044     }
   3045 
   3046     if (truncate)
   3047     {
   3048         iInputFile->Seek(framesize, Oscl_File::SEEKCUR);
   3049         kvpPtr->capacity = 0;
   3050         kvpPtr->length = 0;
   3051 
   3052         OSCL_TRY(err, iFrames.push_back(kvpPtr););
   3053         OSCL_FIRST_CATCH_ANY(err,
   3054                              LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - iFrame.push_back failed"));
   3055                              return PVMFErrNoMemory;);
   3056 
   3057         return PVMFSuccess;
   3058 
   3059     }
   3060 
   3061     PvmfLyricsCommStruct *lcStruct = NULL;
   3062     uint8 *ptr = NULL;
   3063     lcStruct = OSCL_STATIC_CAST(PvmfLyricsCommStruct *, kvpPtr->value.key_specific_value);
   3064     ptr = (uint8 *)kvpPtr->value.key_specific_value;
   3065     if (!ptr)
   3066     {
   3067         return PVMFFailure;
   3068     }
   3069 
   3070     ptr += sizeof(PvmfLyricsCommStruct);
   3071     used_size += sizeof(PvmfLyricsCommStruct);
   3072 
   3073     switch (unicodeCheck)
   3074     {
   3075         case PV_ID3_CHARSET_ISO88591:
   3076         case PV_ID3_CHARSET_UTF8:
   3077         {
   3078             OSCL_HeapString<OsclMemAllocator> descriptor;
   3079 
   3080             if (readNullTerminatedAsciiString(iInputFile, descriptor) == false)
   3081             {
   3082                 iAlloc.deallocate(lcStruct);
   3083                 return PVMFFailure;
   3084             }
   3085 
   3086             uint32 desc_sz = descriptor.get_size();
   3087             framesize = framesize - desc_sz - 1 ; //subtract 1 for null character
   3088 
   3089             if ((framesize > aFramesize) || (framesize == 0))
   3090             {
   3091                 lcStruct->iDescription = NULL;
   3092                 lcStruct->iData = NULL;
   3093                 break;
   3094             }
   3095 
   3096             lcStruct->iDescription = OSCL_STATIC_CAST(oscl_wchar *, ptr);
   3097             ptr += wchar_size * (desc_sz + 1); //1 for null char
   3098 
   3099             used_size += wchar_size * (desc_sz + 1);
   3100             if (used_size > total_size)
   3101                 return PVMFErrOverflow;
   3102             if (desc_sz > 0)
   3103             {
   3104                 uint32 sz = desc_sz + 1;
   3105                 oscl_UTF8ToUnicode((const char *)descriptor.get_cstr(), descriptor.get_size(), lcStruct->iDescription,  sz);
   3106                 lcStruct->iDescription[sz] = 0;
   3107             }
   3108             else
   3109             {
   3110                 lcStruct->iDescription[desc_sz] = 0;
   3111             }
   3112 
   3113             uint8 *data = NULL;
   3114             uint32 datasz = framesize + 1;
   3115             OSCL_TRY(err, data = (uint8*)iAlloc.allocate(datasz););
   3116 
   3117             if (OsclErrNone != err || !(data))
   3118             {
   3119                 LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - allocation failed"));
   3120                 iInputFile->Seek(framesize, Oscl_File::SEEKCUR);
   3121 
   3122             }
   3123 
   3124             else
   3125             {
   3126 
   3127                 if ((readByteData(iInputFile, framesize, data) == false))
   3128                 {
   3129                     iAlloc.deallocate(data);
   3130                     return PVMFFailure;
   3131                 }
   3132 
   3133                 lcStruct->iData = OSCL_STATIC_CAST(oscl_wchar *, ptr);
   3134                 used_size += datasz;
   3135 
   3136                 if (used_size > total_size)
   3137                     return PVMFErrOverflow;
   3138                 oscl_UTF8ToUnicode((const char *)data, framesize, lcStruct->iData,  datasz);
   3139                 lcStruct->iData[datasz] = 0;
   3140 
   3141                 iAlloc.deallocate(data);
   3142             }
   3143         }
   3144 
   3145         break;
   3146 
   3147         case PV_ID3_CHARSET_UTF16:
   3148         case PV_ID3_CHARSET_UTF16BE:
   3149         {
   3150 
   3151             uint32 bomSize = 0;
   3152             OSCL_wHeapString<OsclMemAllocator> description ;
   3153 
   3154             if (readNullTerminatedUnicodeString(iInputFile, description, bomSize) == false)
   3155             {
   3156                 return PVMFFailure;
   3157             }
   3158 
   3159             uint32 desc_len = oscl_strlen(description.get_str()) ;
   3160             framesize = framesize - (2 * desc_len) - 2 - bomSize; // description(2 byte unicode in id3 tag), null char, bom
   3161             if ((framesize > aFramesize) || (framesize == 0))
   3162             {
   3163                 lcStruct->iDescription = NULL;
   3164                 lcStruct->iData = NULL;
   3165                 break;
   3166             }
   3167 
   3168             lcStruct->iDescription = OSCL_STATIC_CAST(oscl_wchar *, ptr);
   3169             ptr += wchar_size * (desc_len + 1); //1 for null char
   3170 
   3171             used_size += wchar_size * (desc_len + 1);
   3172             if (used_size > total_size)
   3173                 return PVMFErrOverflow;
   3174 
   3175             if (desc_len > 0)
   3176             {
   3177                 oscl_strncpy(lcStruct->iDescription, description.get_str(), desc_len);
   3178                 lcStruct->iDescription[desc_len + 1] = 0;
   3179             }
   3180             else
   3181             {
   3182                 lcStruct->iDescription[desc_len] = 0;
   3183             }
   3184 
   3185 
   3186             uint16 endianCheck = 0;
   3187             //check endian type
   3188             if (read16(iInputFile, endianCheck) == false)
   3189             {
   3190 
   3191                 return PVMFFailure;
   3192             }
   3193 
   3194             // This frame's text strings are Unicode and the frame
   3195             // does include a BOM value. (UTF-16)
   3196             iID3TagInfo.iTextType = PV_ID3_CHARSET_UTF16;
   3197             uint32 endianType = 0;
   3198 
   3199             if (endianCheck == UNICODE_LITTLE_ENDIAN_INDICATOR_FULL)
   3200             {
   3201                 endianType = UNICODE_LITTLE_ENDIAN;
   3202             }
   3203             else if (endianCheck == UNICODE_BIG_ENDIAN_INDICATOR_FULL)
   3204             {
   3205                 endianType = UNICODE_BIG_ENDIAN;
   3206             }
   3207 
   3208             framesize -= UNICODE_BOM_SIZE;
   3209             if ((framesize > aFramesize) || (framesize == 0))
   3210             {
   3211                 lcStruct->iDescription = NULL;
   3212                 lcStruct->iData = NULL;
   3213                 break;
   3214             }
   3215 
   3216             uint8 *data = NULL;
   3217             uint32 datasz = framesize + 2;
   3218             int32 err = OsclErrNone;
   3219             OSCL_TRY(err, data = (uint8*)iAlloc.allocate(datasz););
   3220             if (OsclErrNone != err || !(data))
   3221             {
   3222                 LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - allocation failed"));
   3223                 truncate = true;
   3224             }
   3225             else
   3226             {
   3227 
   3228                 oscl_memset(data, 0, datasz);
   3229                 if ((readByteData(iInputFile, framesize, data) == false))
   3230                 {
   3231                     iAlloc.deallocate(data);
   3232                     return PVMFFailure;
   3233                 }
   3234                 lcStruct->iData = OSCL_STATIC_CAST(oscl_wchar *, ptr);
   3235 
   3236                 used_size += wchar_size * (framesize / 2);  //UCS-2 unicode
   3237                 if (used_size > total_size)
   3238                     return PVMFErrOverflow;
   3239 
   3240                 uint32 sz = EightBitToWideCharBufferTransfer(data, framesize, endianType , lcStruct->iData);
   3241                 lcStruct->iData[sz] = 0;
   3242 
   3243                 iAlloc.deallocate(data);
   3244             }
   3245         }
   3246         break;
   3247 
   3248         default:
   3249             return PVMFFailure;
   3250 
   3251     }
   3252 
   3253     kvpPtr->capacity = (aFramesize - ID3V2_LANGUAGE_SIZE) + sizeof(PvmfLyricsCommStruct) ;
   3254     kvpPtr->length = (aFramesize - ID3V2_LANGUAGE_SIZE) + sizeof(PvmfLyricsCommStruct) ;
   3255 
   3256     OSCL_TRY(err, iFrames.push_back(kvpPtr););
   3257     OSCL_FIRST_CATCH_ANY(err,
   3258                          LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - iFrame.push_back failed"));
   3259                          return PVMFErrNoMemory;
   3260                         );
   3261 
   3262 
   3263     return PVMFSuccess;
   3264 }
   3265 
   3266 PVMFStatus PVID3ParCom::ConvertAsciiDataToApic(char* aMimeTypeID3, char* aDescriptionID3,
   3267         uint8 aGraphicType, uint32 aGraphicDataLen,
   3268         void *key_specific_value, uint32 total_size)
   3269 {
   3270     uint32 used_size = 0;
   3271     uint8 *ptr = (uint8 *)key_specific_value;
   3272     PvmfApicStruct* aAPICStruct = OSCL_STATIC_CAST(PvmfApicStruct*, key_specific_value);
   3273     uint32 mime_string_size;
   3274     uint32 description_size;
   3275     mime_string_size = oscl_strlen(aMimeTypeID3) + 1;
   3276     description_size = oscl_strlen(aDescriptionID3) + 1;
   3277     ptr += sizeof(PvmfApicStruct);
   3278     used_size += sizeof(PvmfApicStruct);
   3279     if (used_size > total_size)
   3280         return PVMFErrOverflow;
   3281     aAPICStruct->iGraphicMimeType = OSCL_STATIC_CAST(oscl_wchar *, ptr);
   3282     ptr += sizeof(oscl_wchar) * (mime_string_size);
   3283     used_size += sizeof(oscl_wchar) * (mime_string_size);
   3284     if (used_size > total_size)
   3285         return PVMFErrOverflow;
   3286     aAPICStruct->iGraphicDescription = OSCL_STATIC_CAST(oscl_wchar *, ptr);
   3287     ptr += sizeof(oscl_wchar) * (description_size);
   3288     used_size += sizeof(oscl_wchar) * (description_size);
   3289     if (used_size > total_size)
   3290         return PVMFErrOverflow;
   3291 
   3292     oscl_memset(aAPICStruct->iGraphicDescription, 0 , description_size);
   3293     oscl_memset(aAPICStruct->iGraphicMimeType , 0 ,  mime_string_size);
   3294     oscl_UTF8ToUnicode((const char *)aDescriptionID3, description_size , aAPICStruct->iGraphicDescription,  description_size);
   3295     oscl_UTF8ToUnicode((const char *)aMimeTypeID3, mime_string_size, aAPICStruct->iGraphicMimeType, mime_string_size);
   3296 
   3297     //push the data to PvmfApicStruct
   3298     aAPICStruct->iGraphicType = aGraphicType;
   3299 
   3300     aAPICStruct->iGraphicData = OSCL_STATIC_CAST(uint8 *, ptr);
   3301 
   3302     aAPICStruct->iGraphicDataLen = aGraphicDataLen;
   3303 
   3304     used_size += aGraphicDataLen;
   3305     if (used_size > total_size)
   3306         return PVMFErrOverflow;
   3307     return PVMFSuccess;
   3308 }
   3309 
   3310 PVMFStatus PVID3ParCom::ConvertUnicodeDataToApic(char* aMimeTypeID3, oscl_wchar* aDescriptionID3,
   3311         uint8 aGraphicType, uint32 aGraphicDataLen,
   3312         void *key_specific_value, uint32 total_size)
   3313 {
   3314     uint32 used_size = 0;
   3315     uint8 *ptr = (uint8 *)key_specific_value;
   3316     PvmfApicStruct* aAPICStruct = OSCL_STATIC_CAST(PvmfApicStruct*, key_specific_value);
   3317     uint32 mime_string_size;
   3318     uint32 description_size;
   3319 
   3320     mime_string_size = oscl_strlen(aMimeTypeID3) + 1;
   3321     description_size = oscl_strlen(aDescriptionID3) + 1;
   3322 
   3323     ptr += sizeof(PvmfApicStruct);
   3324     used_size += sizeof(PvmfApicStruct);
   3325     if (used_size > total_size)
   3326         return PVMFErrOverflow;
   3327 
   3328     aAPICStruct->iGraphicMimeType = OSCL_STATIC_CAST(oscl_wchar *, ptr);
   3329     ptr += sizeof(oscl_wchar) * mime_string_size;
   3330     used_size += sizeof(oscl_wchar) * mime_string_size;
   3331     if (used_size > total_size)
   3332         return PVMFErrOverflow;
   3333     aAPICStruct->iGraphicDescription = OSCL_STATIC_CAST(oscl_wchar *, ptr);
   3334     ptr += sizeof(oscl_wchar) * description_size;
   3335     used_size += sizeof(oscl_wchar) * description_size;
   3336     if (used_size > total_size)
   3337         return PVMFErrOverflow;
   3338     //push the data to PvmfApicStruct
   3339     oscl_memset(aAPICStruct->iGraphicDescription, '\0', sizeof(oscl_wchar)*description_size);
   3340     oscl_memset(aAPICStruct->iGraphicMimeType , '\0', sizeof(oscl_wchar)*mime_string_size);
   3341     oscl_UTF8ToUnicode((const char *)aMimeTypeID3, mime_string_size - 1, aAPICStruct->iGraphicMimeType, mime_string_size);
   3342     aAPICStruct->iGraphicMimeType[mime_string_size] = 0;
   3343 
   3344     oscl_strncpy(aAPICStruct->iGraphicDescription, aDescriptionID3, description_size);
   3345     aAPICStruct->iGraphicDescription[description_size] = 0;
   3346     aAPICStruct->iGraphicType = aGraphicType;
   3347     aAPICStruct->iGraphicDataLen = aGraphicDataLen;
   3348     aAPICStruct->iGraphicData = OSCL_STATIC_CAST(uint8 *, ptr);
   3349     used_size += aGraphicDataLen;
   3350     if (used_size > total_size)
   3351         return PVMFErrOverflow;
   3352 
   3353     return PVMFSuccess;
   3354 }
   3355 
   3356 PVMFStatus PVID3ParCom::GetAlbumArtInfo(PVID3FrameType aFrameType, uint32 aFrameSize, OSCL_HeapString<OsclMemAllocator> &aImageFormat,
   3357                                         uint8 &aPicType, OSCL_HeapString<OsclMemAllocator> &aDescription,   uint32 &aDataLen)
   3358 {
   3359     uint8 image_format[4] = {0};
   3360     PVMFStatus status = 0;
   3361     uint32 size = 0;
   3362     uint32 currentfilepos = 0 ;
   3363     if (aFrameType == PV_ID3_FRAME_PIC)
   3364     {
   3365         if (readByteData(iInputFile, ID3V2_IMAGE_FORMAT_SIZE, image_format) == false)
   3366         {
   3367             return PVMFFailure;
   3368         }
   3369         else
   3370         {
   3371             aImageFormat = (char *)image_format;
   3372         }
   3373         if (read8(iInputFile, aPicType) == false)
   3374         {
   3375             return PVMFFailure;
   3376         }
   3377 
   3378         currentfilepos = iInputFile->Tell();
   3379         //read description from file
   3380         status = readNullTerminatedAsciiString(iInputFile, aDescription);
   3381         if (status != PVMFSuccess)
   3382         {
   3383             iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
   3384             return PVMFFailure;
   3385         }
   3386         //get the graphic data len
   3387         size = aDescription.get_size() + 1 ; // 1 byte for null char
   3388         aDataLen = aFrameSize - (ID3V2_PIC_CONST_SIZE + size);
   3389         if (aDataLen > aFrameSize)
   3390         {
   3391             iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
   3392             aDataLen = 0;
   3393             return PVMFFailure;
   3394         }
   3395 
   3396 
   3397 
   3398     }
   3399     else if (aFrameType == PV_ID3_FRAME_APIC)
   3400     {
   3401         uint32 mimeSize;
   3402         uint32 desSize;
   3403 
   3404         currentfilepos = iInputFile->Tell();
   3405         status = readNullTerminatedAsciiString(iInputFile, aImageFormat);
   3406         if (status != PVMFSuccess)
   3407         {
   3408             iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
   3409             return PVMFFailure;
   3410         }
   3411         if (read8(iInputFile, aPicType) == false)
   3412         {
   3413             return PVMFFailure;
   3414         }
   3415         currentfilepos = iInputFile->Tell();
   3416         status = readNullTerminatedAsciiString(iInputFile, aDescription);
   3417         if (status != PVMFSuccess)
   3418         {
   3419             iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
   3420             return status;
   3421         }
   3422 
   3423         //get the graphic data len
   3424         mimeSize = aImageFormat.get_size() + 1; //for null string
   3425         desSize = aDescription.get_size() + 1; //for null string
   3426 
   3427         aDataLen = aFrameSize - (ID3V2_APIC_CONST_SIZE + mimeSize + desSize);
   3428 
   3429         if (aDataLen > aFrameSize)
   3430         {
   3431             iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
   3432             aDataLen = 0;
   3433             return PVMFFailure;
   3434         }
   3435 
   3436 
   3437     }
   3438     return PVMFSuccess;
   3439 }
   3440 
   3441 PVMFStatus PVID3ParCom::GetAlbumArtInfo(PVID3FrameType aFrameType, uint32 aFrameSize, OSCL_HeapString<OsclMemAllocator> &aImageFormat,
   3442                                         uint8 &aPicType, OSCL_wHeapString<OsclMemAllocator> &aDescription, uint32 &aDataLen)
   3443 {
   3444     uint8 image_format[4] = {0};
   3445     uint32 currentfilepos = 0;
   3446     uint32 size = 0;
   3447     if (aFrameType == PV_ID3_FRAME_PIC)
   3448     {
   3449         if (readByteData(iInputFile, ID3V2_IMAGE_FORMAT_SIZE, image_format) == false)
   3450         {
   3451             return PVMFFailure;
   3452         }
   3453         else
   3454         {
   3455             aImageFormat = (char *)image_format;
   3456         }
   3457         if (read8(iInputFile, aPicType) == false)
   3458         {
   3459             return PVMFFailure;
   3460         }
   3461 
   3462         uint32 bomSz = 0;
   3463         currentfilepos = iInputFile->Tell();
   3464         //read description from file
   3465         if (readNullTerminatedUnicodeString(iInputFile, aDescription, bomSz) == false)
   3466         {
   3467             iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
   3468             return PVMFFailure;
   3469         }
   3470 
   3471         //get the graphic data len
   3472         size = (2 * oscl_strlen(aDescription.get_str())) + bomSz + sizeof(oscl_wchar) * 1; //2 byte null character
   3473         aDataLen = aFrameSize - (ID3V2_PIC_CONST_SIZE + size);
   3474         if (aDataLen > aFrameSize)
   3475         {
   3476             iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
   3477             aDataLen = 0;
   3478             return PVMFFailure;
   3479         }
   3480 
   3481 
   3482     }
   3483     else if (aFrameType == PV_ID3_FRAME_APIC)
   3484     {
   3485         uint32 mimeSize;
   3486         uint32 desSize;
   3487         currentfilepos = iInputFile->Tell();
   3488         //read the mime type information
   3489         if (readNullTerminatedAsciiString(iInputFile, aImageFormat) == false)
   3490         {
   3491             iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
   3492             return PVMFFailure;
   3493         }
   3494         //read the picture type information
   3495         if (read8(iInputFile, aPicType) == false)
   3496         {
   3497             return PVMFFailure;
   3498         }
   3499         uint32 bomSz = 0;
   3500         currentfilepos = iInputFile->Tell();
   3501         //read the null terminated description information
   3502         if (readNullTerminatedUnicodeString(iInputFile, aDescription, bomSz) == false)
   3503         {
   3504             iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
   3505             return PVMFFailure;
   3506         }
   3507         //get the graphic data len
   3508         mimeSize = aImageFormat.get_size() + 1;
   3509         desSize = (2 * oscl_strlen(aDescription.get_str())) + bomSz + sizeof(oscl_wchar) * 1; //2 bytes for null character
   3510         aDataLen = aFrameSize - (ID3V2_APIC_CONST_SIZE + mimeSize + desSize);
   3511         if (aDataLen > aFrameSize)
   3512         {
   3513             iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
   3514             aDataLen = 0;
   3515             return PVMFFailure;
   3516         }
   3517 
   3518 
   3519 
   3520     }
   3521     return PVMFSuccess;
   3522 }
   3523 
   3524 
   3525 ////////////////////////////////////////////////////////////////////////////
   3526 PVMFStatus PVID3ParCom::ReadTrackLengthFrame(uint32 aValueSize, PVID3CharacterSet aCharSet)
   3527 {
   3528     OSCL_StackString<128> keyStr;
   3529     if (ConstructKvpKey(keyStr, PV_ID3_FRAME_TRACK_LENGTH, PV_ID3_CHARSET_INVALID) != PVMFSuccess)
   3530     {
   3531         LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - ConstructKvpKey failed"));
   3532         return PVMFErrNotSupported;
   3533     }
   3534 
   3535     int32 err = OsclErrNone;
   3536     uint8* ptrFrameData = NULL;
   3537     ptrFrameData = (uint8*) AllocateValueArray(err, PVMI_KVPVALTYPE_UINT8PTR, aValueSize + 2, &iAlloc);
   3538     if (OsclErrNone != err || !ptrFrameData)
   3539     {
   3540         LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - ptrFrameData allocation failed"));
   3541         return PVMFErrNoMemory;
   3542     }
   3543 
   3544     if (readByteData(iInputFile, aValueSize, ptrFrameData) == false)
   3545     {
   3546         iAlloc.deallocate((OsclAny*)ptrFrameData);
   3547         LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - readByteData failed"));
   3548         return PVMFFailure;
   3549     }
   3550     ptrFrameData[aValueSize] = 0;
   3551     ptrFrameData[aValueSize+1] = 0;
   3552 
   3553     switch (aCharSet)
   3554     {
   3555         case PV_ID3_CHARSET_UTF16:
   3556         case PV_ID3_CHARSET_UTF16BE:
   3557         {
   3558             //it uses 16-bit unicode 2.0 (ISO/IEC 10646-1:1993, UCS-2)
   3559 
   3560             char* tmpData = NULL;
   3561             int len = aValueSize / UNICODE_CHAR_SIZE + 1;
   3562             tmpData = (char*) AllocateValueArray(err, PVMI_KVPVALTYPE_CHARPTR, len, &iAlloc);
   3563 
   3564             if (sizeof(oscl_wchar) == UNICODE_CHAR_SIZE)
   3565             {
   3566                 oscl_UnicodeToUTF8((oscl_wchar*)ptrFrameData, aValueSize / sizeof(oscl_wchar), tmpData, len);
   3567             }
   3568             else
   3569             {
   3570                 oscl_wchar* tmpData2 = NULL;
   3571 
   3572                 tmpData2 = (oscl_wchar*) AllocateValueArray(err, PVMI_KVPVALTYPE_WCHARPTR, len);
   3573                 // convert 2 byte unicode data  to 4 byte wchar data
   3574                 ExpandWChar2BytesTo4Bytes(tmpData2, (uint16*)ptrFrameData, len);
   3575 
   3576                 oscl_UnicodeToUTF8(tmpData2, aValueSize / UNICODE_CHAR_SIZE, tmpData, len);
   3577 
   3578                 OSCL_ARRAY_DELETE(tmpData2);
   3579             }
   3580 
   3581             // copy the UTF8 string back to ptrFrameData
   3582             oscl_strncpy((char*)ptrFrameData, tmpData, len);
   3583 
   3584             iAlloc.deallocate((OsclAny*)tmpData);
   3585         }
   3586         break;
   3587         case PV_ID3_CHARSET_ISO88591:
   3588         case PV_ID3_CHARSET_UTF8:
   3589             break;
   3590         default:
   3591             return PVMFFailure;
   3592     }
   3593 
   3594     // The ID3 Track Length is a numeric string in milliseconds.
   3595     uint32 duration = 0;
   3596     int32 numericStringLen = oscl_strlen((const char*)ptrFrameData);
   3597 
   3598     if (!PV_atoi((const char *)ptrFrameData, 'd', numericStringLen, duration))
   3599     {
   3600         uint8* ptr = ptrFrameData;
   3601         bool invalid_frame = false;
   3602         while (ptr - ptrFrameData < numericStringLen)
   3603         {
   3604             // if the charater read is a digit or decimal point
   3605             // then truncate it to integer value
   3606             if (!(((*ptr >= ZERO_CHARACTER_ASCII_VALUE) &&
   3607                     (*ptr <= NINE_CHARACTER_ASCII_VALUE)) ||
   3608                     (*ptr == PERIOD_CHARACTER_ASCII_VALUE) ||
   3609                     (*ptr == COMMA_CHARACTER_ASCII_VALUE)))
   3610             {
   3611                 invalid_frame = true;
   3612                 break;
   3613             }
   3614             else if (*ptr == PERIOD_CHARACTER_ASCII_VALUE ||
   3615                      *ptr == COMMA_CHARACTER_ASCII_VALUE)
   3616             {
   3617                 numericStringLen = ptr - ptrFrameData;
   3618                 break;
   3619             }
   3620             ptr++;
   3621         }
   3622 
   3623         if (!invalid_frame)
   3624         {
   3625             numericStringLen = ptr - ptrFrameData;
   3626         }
   3627         else
   3628         {
   3629             iAlloc.deallocate((OsclAny*)ptrFrameData);
   3630             numericStringLen = 0;
   3631             return PVMFSuccess;
   3632         }
   3633     }
   3634 
   3635     // Allocate key-value pair
   3636     bool truncate = false;
   3637     PvmiKvpSharedPtr kvpPtr;
   3638     PVMFStatus status = PVMFSuccess;
   3639     kvpPtr = HandleErrorForKVPAllocation(keyStr, PVMI_KVPVALTYPE_UINT32, 1, truncate, status);
   3640     if (PVMFSuccess != status || !kvpPtr)
   3641     {
   3642         iAlloc.deallocate((OsclAny*)ptrFrameData);
   3643         return PVMFErrNoMemory;
   3644     }
   3645 
   3646     kvpPtr->value.uint32_value = duration; // Track length in milliseconds
   3647     kvpPtr->length = numericStringLen;
   3648 
   3649     iAlloc.deallocate((OsclAny*)ptrFrameData);
   3650 
   3651     OSCL_TRY(err, iFrames.push_back(kvpPtr););
   3652     OSCL_FIRST_CATCH_ANY(err,
   3653                          LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - iFrame.push_back failed"));
   3654                          return PVMFErrNoMemory;
   3655                         );
   3656 
   3657     return PVMFSuccess;
   3658 }
   3659 
   3660 
   3661 ////////////////////////////////////////////////////////////////////////////
   3662 PVMFStatus PVID3ParCom::GetKvpValueType(PvmiKvpSharedPtr aKvp,
   3663                                         PvmiKvpValueType& aValueType,
   3664                                         PVID3CharacterSet& aCharSet)
   3665 {
   3666     aValueType = GetValTypeFromKeyString(aKvp->key);
   3667     aCharSet = PV_ID3_CHARSET_INVALID;
   3668     char* param = NULL;
   3669     switch (aValueType)
   3670     {
   3671         case PVMI_KVPVALTYPE_CHARPTR:
   3672             aCharSet = PV_ID3_CHARSET_ISO88591;
   3673             if (pv_mime_string_parse_param(aKvp->key, (char*) KVP_PARAM_CHAR_ENCODING_UTF8, param) > 0)
   3674                 aCharSet = PV_ID3_CHARSET_UTF8;
   3675             break;
   3676         case PVMI_KVPVALTYPE_WCHARPTR:
   3677             aCharSet = PV_ID3_CHARSET_UTF16;
   3678             if (pv_mime_string_parse_param(aKvp->key, (char*) KVP_PARAM_CHAR_ENCODING_UTF16BE, param) > 0)
   3679                 aCharSet = PV_ID3_CHARSET_UTF16BE;
   3680             break;
   3681         case PVMI_KVPVALTYPE_KSV:
   3682             // Comment field
   3683             break;
   3684         case PVMI_KVPVALTYPE_UNKNOWN:
   3685             return PVMFFailure;
   3686         default:
   3687             break;
   3688     }
   3689 
   3690     return PVMFSuccess;
   3691 }
   3692 
   3693 ////////////////////////////////////////////////////////////////////////////
   3694 PVMFStatus PVID3ParCom::GetFrameTypeFromKvp(PvmiKvpSharedPtr aKvp,
   3695         OSCL_String& aFrameID,
   3696         PVID3FrameType& aFrameType)
   3697 {
   3698     return GetFrameTypeFromKvp(*aKvp, aFrameID, aFrameType);
   3699 }
   3700 
   3701 ////////////////////////////////////////////////////////////////////////////
   3702 PVMFStatus PVID3ParCom::GetFrameTypeFromKvp(const PvmiKvp& aKvp,
   3703         OSCL_String& aFrameID,
   3704         PVID3FrameType& aFrameType)
   3705 {
   3706     if (iVersion == PV_ID3_V2_2)
   3707     {
   3708         if (pv_mime_strcmp(aKvp.key, KVP_KEY_TITLE) == 0)
   3709         {
   3710             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_TITLE);
   3711             aFrameType = PV_ID3_FRAME_TITLE;
   3712         }
   3713         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ARTIST) == 0)
   3714         {
   3715             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_ARTIST);
   3716             aFrameType = PV_ID3_FRAME_ARTIST;
   3717         }
   3718         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_PART_OF_SET) == 0)
   3719         {
   3720             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_PART_OF_SET);
   3721             aFrameType = PV_ID3_FRAME_PART_OF_SET;
   3722         }
   3723         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ALBUM) == 0)
   3724         {
   3725             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_ALBUM);
   3726             aFrameType = PV_ID3_FRAME_ALBUM;
   3727         }
   3728         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_TRACKINFO_TRACK_NUMBER) == 0)
   3729         {
   3730             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_TRACK_NUMBER);
   3731             aFrameType = PV_ID3_FRAME_TRACK_NUMBER;
   3732         }
   3733         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_GENRE) == 0)
   3734         {
   3735             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_GENRE);
   3736             aFrameType = PV_ID3_FRAME_GENRE;
   3737         }
   3738         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_YEAR) == 0)
   3739         {
   3740             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_YEAR);
   3741             aFrameType = PV_ID3_FRAME_YEAR;
   3742         }
   3743         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COPYRIGHT) == 0)
   3744         {
   3745             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_COPYRIGHT);
   3746             aFrameType = PV_ID3_FRAME_COPYRIGHT;
   3747         }
   3748         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COMMENT) == 0)
   3749         {
   3750             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_COMMENT);
   3751             aFrameType = PV_ID3_FRAME_COMMENT;
   3752         }
   3753         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ID3DURATION) == 0)
   3754         {
   3755             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_TRACK_LENGTH);
   3756             aFrameType = PV_ID3_FRAME_TRACK_LENGTH;
   3757         }
   3758         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_DATE) == 0)
   3759         {
   3760             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_DATE);
   3761             aFrameType = PV_ID3_FRAME_DATE;
   3762         }
   3763         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ALBUMART) == 0)
   3764         {
   3765             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_ALBUMART);
   3766             aFrameType = PV_ID3_FRAME_PIC;
   3767         }
   3768         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_LYRICS) == 0)
   3769         {
   3770             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_LYRICIST);
   3771             aFrameType = PV_ID3_FRAME_LYRICS;
   3772         }
   3773         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_AUTHOR) == 0)
   3774         {
   3775             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_AUTHOR);
   3776             aFrameType = PV_ID3_FRAME_AUTHOR;
   3777         }
   3778         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COMPOSER) == 0)
   3779         {
   3780             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_COMPOSER);
   3781             aFrameType = PV_ID3_FRAME_COMPOSER;
   3782         }
   3783         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_DESCRIPTION) >= 0)
   3784         {
   3785             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_DESCRIPTION);
   3786             aFrameType = PV_ID3_FRAME_DESCRIPTION;
   3787         }
   3788         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_VERSION) == 0)
   3789         {
   3790             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_VERSION);
   3791             aFrameType = PV_ID3_FRAME_VERSION;
   3792         }
   3793         else
   3794         {
   3795             LOG_ERR((0, "PVID3ParCom::GetFrameTypeFromKvp: Error : Frame type not supported for composing"));
   3796             return PVMFErrNotSupported;
   3797         }
   3798     }
   3799     else
   3800     {
   3801         if (pv_mime_strcmp(aKvp.key, KVP_KEY_TITLE) == 0)
   3802         {
   3803             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_TITLE);
   3804             aFrameType = PV_ID3_FRAME_TITLE;
   3805         }
   3806         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ARTIST) == 0)
   3807         {
   3808             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_ARTIST);
   3809             aFrameType = PV_ID3_FRAME_ARTIST;
   3810         }
   3811         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_PART_OF_SET) == 0)
   3812         {
   3813             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_PART_OF_SET);
   3814             aFrameType = PV_ID3_FRAME_PART_OF_SET;
   3815         }
   3816         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ALBUM) == 0)
   3817         {
   3818             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_ALBUM);
   3819             aFrameType = PV_ID3_FRAME_ALBUM;
   3820         }
   3821         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_TRACKINFO_TRACK_NUMBER) == 0)
   3822         {
   3823             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_TRACK_NUMBER);
   3824             aFrameType = PV_ID3_FRAME_TRACK_NUMBER;
   3825         }
   3826         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_GENRE) == 0)
   3827         {
   3828             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_GENRE);
   3829             aFrameType = PV_ID3_FRAME_GENRE;
   3830         }
   3831         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_YEAR) == 0)
   3832         {
   3833             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_YEAR);
   3834             aFrameType = PV_ID3_FRAME_YEAR;
   3835         }
   3836         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COPYRIGHT) == 0)
   3837         {
   3838             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_COPYRIGHT);
   3839             aFrameType = PV_ID3_FRAME_COPYRIGHT;
   3840         }
   3841         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COMMENT) == 0)
   3842         {
   3843             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_COMMENT);
   3844             aFrameType = PV_ID3_FRAME_COMMENT;
   3845         }
   3846         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ID3DURATION) == 0)
   3847         {
   3848             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_TRACK_LENGTH);
   3849             aFrameType = PV_ID3_FRAME_TRACK_LENGTH;
   3850         }
   3851         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_RECORDING_TIME) == 0)
   3852         {
   3853             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_RECORDING_TIME);
   3854             aFrameType = PV_ID3_FRAME_RECORDING_TIME;
   3855         }
   3856         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_AUTHOR) == 0)
   3857         {
   3858             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_AUTHOR);
   3859             aFrameType = PV_ID3_FRAME_AUTHOR;
   3860         }
   3861         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COMPOSER) == 0)
   3862         {
   3863             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_COMPOSER);
   3864             aFrameType = PV_ID3_FRAME_COMPOSER;
   3865         }
   3866         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_DESCRIPTION) == 0)
   3867         {
   3868             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_DESCRIPTION);
   3869             aFrameType = PV_ID3_FRAME_DESCRIPTION;
   3870         }
   3871         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_VERSION) == 0)
   3872         {
   3873             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_VERSION);
   3874             aFrameType = PV_ID3_FRAME_VERSION;
   3875         }
   3876         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_DATE) == 0)
   3877         {
   3878             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_DATE);
   3879             aFrameType = PV_ID3_FRAME_DATE;
   3880         }
   3881         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_LYRICS) == 0)
   3882         {
   3883             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_LYRICIST);
   3884             aFrameType = PV_ID3_FRAME_LYRICS;
   3885         }
   3886         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ALBUMART) == 0)
   3887         {
   3888             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_ALBUMART);
   3889             aFrameType = PV_ID3_FRAME_APIC;
   3890         }
   3891         else
   3892         {
   3893             LOG_ERR((0, "PVID3ParCom::GetFrameTypeFromKvp: Error : Frame type not supported for composing"));
   3894             return PVMFErrNotSupported;
   3895         }
   3896     }
   3897 
   3898     return PVMFSuccess;
   3899 }
   3900 
   3901 ////////////////////////////////////////////////////////////////////////////
   3902 PVMFStatus PVID3ParCom::GetID3v2FrameDataSize(PvmiKvpSharedPtr aKvp,
   3903         PvmiKvpValueType aValueType,
   3904         PVID3CharacterSet aCharSet,
   3905         uint32& aSize)
   3906 {
   3907     aSize = 0;
   3908     switch (aValueType)
   3909     {
   3910         case PVMI_KVPVALTYPE_CHARPTR:
   3911             aSize += (BYTE_FOR_CHARACTERSET_FORMAT + oscl_strlen(aKvp->value.pChar_value) + 1);
   3912             break;
   3913         case PVMI_KVPVALTYPE_WCHARPTR:
   3914             aSize += (BYTE_FOR_CHARACTERSET_FORMAT +
   3915                       (oscl_strlen(aKvp->value.pWChar_value) + 1) * sizeof(oscl_wchar));
   3916             break;
   3917         case PVMI_KVPVALTYPE_KSV:
   3918             // Comment field
   3919             break;
   3920         case PVMI_KVPVALTYPE_UINT32:
   3921             uint32 value;
   3922             value = aKvp->value.uint32_value;
   3923             if (value == 0)
   3924                 return PVMFSuccess;
   3925             while (value > 0)
   3926             {
   3927                 value = value / 10;
   3928                 ++aSize;
   3929             }
   3930             break;
   3931         default:
   3932             return PVMFErrNotSupported;
   3933     }
   3934 
   3935     // Add 1 byte for BOM value to indicate byte order
   3936     if (aCharSet == PV_ID3_CHARSET_UTF16)
   3937         ++aSize;
   3938 
   3939     return PVMFSuccess;
   3940 }
   3941 
   3942 ////////////////////////////////////////////////////////////////////////////
   3943 PVMFStatus PVID3ParCom::ComposeID3v2Tag(OsclRefCounterMemFrag& aTag)
   3944 {
   3945     uint8* memFragPtr;
   3946     uint32 index = 0;
   3947     uint32 composedTagSize = 0;
   3948     uint32 frameDataSize = 0;
   3949     uint32 i = 0;
   3950     char bufTrackLength[16];
   3951     oscl_wchar wbufTrackLength[16];
   3952     oscl_memset(bufTrackLength, 0, 16);
   3953     oscl_memset(wbufTrackLength, 0, 16);
   3954     PvmiKvpValueType kvpValueType;
   3955     PVID3CharacterSet charSet;
   3956     PVMFStatus status = PVMFSuccess;
   3957 
   3958     // At least one frame should be present for a valid ID3 tag to be composed
   3959     if (iFrames.empty())
   3960     {
   3961         LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - No Frames are available to add"));
   3962         return PVMFFailure;
   3963     }
   3964 
   3965     // Calculate the size of composed ID3tag
   3966     composedTagSize = GetID3TagSize();
   3967     if (composedTagSize == 0)
   3968     {
   3969         LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - GetID3TagSize failed"));
   3970         return PVMFFailure;
   3971     }
   3972 
   3973     //iUseMaxTagSize on but the max tag size set is smaller than the total tag size.
   3974     if (iUseMaxTagSize && (iMaxTagSize < composedTagSize))
   3975     {
   3976         LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - Max tag size is smaller than size of composed tag"));
   3977         return PVMFFailure;
   3978     }
   3979 
   3980     //if maxsize is greater than tagsize and padding is ON, allocate memory equal to iMaxTagSize
   3981     if (iUseMaxTagSize && iUsePadding)
   3982         composedTagSize = iMaxTagSize;
   3983 
   3984     //if the fragment buffer size is not sufficient, allocate memory
   3985     OsclMemoryFragment& my_memfrag = aTag.getMemFrag();
   3986     if (composedTagSize > aTag.getMemFragSize())
   3987     {
   3988         OsclRefCounter* my_refcnt;
   3989 
   3990         // Create mem frag for ID3 tag
   3991         OsclMemAllocDestructDealloc<uint8> my_alloc;
   3992         uint aligned_refcnt_size = oscl_mem_aligned_size(sizeof(OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >));
   3993         uint8* myPtr = (uint8*) my_alloc.allocate(aligned_refcnt_size + composedTagSize);
   3994         my_refcnt = OSCL_PLACEMENT_NEW(myPtr, OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >(myPtr));
   3995         myPtr += aligned_refcnt_size;
   3996 
   3997         my_memfrag.ptr = myPtr;
   3998         my_memfrag.len = 0;
   3999 
   4000         OsclRefCounterMemFrag mynewRefCntMemFrag(my_memfrag, my_refcnt, composedTagSize);
   4001 
   4002         //frees the old memeory and make the RefCounterMemFrag point to newly allocated memory
   4003         aTag = mynewRefCntMemFrag;
   4004     }
   4005 
   4006     memFragPtr = (uint8*)aTag.getMemFragPtr();
   4007     oscl_memset(memFragPtr, 0, composedTagSize);
   4008 
   4009     // Form the tag header and place it into the tag buffer
   4010     oscl_memcpy(memFragPtr, ID3_V2_IDENTIFIER, ID3V2_TAG_NUM_BYTES_ID);
   4011     index += ID3V2_TAG_NUM_BYTES_ID;
   4012 
   4013     // Store ID3 tag version
   4014     memFragPtr[index++] = (uint8)iVersion;
   4015     memFragPtr[index++] = 0;
   4016 
   4017     // ID3v2 flags
   4018     memFragPtr[index++] = ID3V2_FLAGS;
   4019 
   4020     // Tag size (4 bytes)
   4021     uint32 syncSafeInt = ConvertToSyncSafeInt(composedTagSize - 10); // Total Size of ID3 tag - 10 bytes for header
   4022 #if (OSCL_BYTE_ORDER_LITTLE_ENDIAN)
   4023     memFragPtr[index++] = (uint8)((syncSafeInt & 0xFF000000) >> 24);
   4024     memFragPtr[index++] = (uint8)((syncSafeInt & 0x00FF0000) >> 16);
   4025     memFragPtr[index++] = (uint8)((syncSafeInt & 0x0000FF00) >> 8);
   4026     memFragPtr[index++] = (uint8)(syncSafeInt & 0x000000FF);
   4027 #elif (OSCL_BYTE_ORDER_BIG_ENDIAN)
   4028     uint32* sizePtr = (uint32*)(memFragPtr + index);
   4029     *sizePtr = syncSafeInt;
   4030     index += 4;
   4031 #else
   4032 #error "Byte order is not specified in OSCL"
   4033 #endif
   4034 
   4035     //iterate the frames and write into the tag buffer
   4036     OSCL_StackString<4> frameID;
   4037     PVID3FrameType frameType;
   4038     for (i = 0; i < iFrames.size(); i++)
   4039     {
   4040         // 4 character Frame ID
   4041         status = GetFrameTypeFromKvp(iFrames[i], frameID, frameType);
   4042 
   4043         //ignore unsupported frames.
   4044         if ((status == PVMFErrNotSupported) || (frameType == PV_ID3_FRAME_LYRICS) ||
   4045                 (frameType == PV_ID3_FRAME_APIC) || (frameType == PV_ID3_FRAME_PIC) ||
   4046                 (frameType == PV_ID3_FRAME_COMMENT))
   4047         {
   4048             continue;
   4049         }
   4050 
   4051         if ((status != PVMFSuccess))
   4052         {
   4053             LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - GetFrameTypeFromKvp failed. status=%d", status));
   4054             return status;
   4055         }
   4056         if (iVersion == PV_ID3_V2_2)
   4057         {
   4058             oscl_memcpy(memFragPtr + index, frameID.get_cstr(), ID3V2_2_FRAME_NUM_BYTES_ID);
   4059             index += ID3V2_2_FRAME_NUM_BYTES_ID;
   4060         }
   4061         else
   4062         {
   4063             oscl_memcpy(memFragPtr + index, frameID.get_cstr(), ID3V2_FRAME_NUM_BYTES_ID);
   4064             index += ID3V2_FRAME_NUM_BYTES_ID;
   4065         }
   4066         status = GetKvpValueType(iFrames[i], kvpValueType, charSet);
   4067         if (status != PVMFSuccess)
   4068         {
   4069             LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - GetKvpValueType failed. status=%d", status));
   4070             return status;
   4071         }
   4072 
   4073         // Size of Frame (4 byte sync safe integer)
   4074         status = GetID3v2FrameDataSize(iFrames[i], kvpValueType, charSet, frameDataSize);
   4075         if (status != PVMFSuccess)
   4076         {
   4077             LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - GetID3v2FrameDataSize failed. status=%d", status));
   4078             return status;
   4079         }
   4080 //      syncSafeInt = ConvertToSyncSafeInt(frameDataSize);
   4081         syncSafeInt = frameDataSize;
   4082 
   4083         if (iVersion == PV_ID3_V2_2)
   4084         {
   4085 #if (OSCL_BYTE_ORDER_LITTLE_ENDIAN)
   4086             memFragPtr[index++] = (uint8)((syncSafeInt & 0x00FF0000) >> 16);
   4087             memFragPtr[index++] = (uint8)((syncSafeInt & 0x0000FF00) >> 8);
   4088             memFragPtr[index++] = (uint8)(syncSafeInt & 0x000000FF);
   4089 #elif (OSCL_BYTE_ORDER_BIG_ENDIAN)
   4090             sizePtr = (uint32*)(memFragPtr + index);
   4091             *sizePtr = syncSafeInt;
   4092             index += 3;
   4093 #else
   4094 #error "Byte order not specified in OSCL"
   4095 #endif
   4096 
   4097         }
   4098         else
   4099         {
   4100 #if (OSCL_BYTE_ORDER_LITTLE_ENDIAN)
   4101             memFragPtr[index++] = (uint8)((syncSafeInt & 0xFF000000) >> 24);
   4102             memFragPtr[index++] = (uint8)((syncSafeInt & 0x00FF0000) >> 16);
   4103             memFragPtr[index++] = (uint8)((syncSafeInt & 0x0000FF00) >> 8);
   4104             memFragPtr[index++] = (uint8)(syncSafeInt & 0x000000FF);
   4105 #elif (OSCL_BYTE_ORDER_BIG_ENDIAN)
   4106             sizePtr = (uint32*)(memFragPtr + index);
   4107             *sizePtr = syncSafeInt;
   4108             index += 4;
   4109 #else
   4110 #error "Byte order not specified in OSCL"
   4111 #endif
   4112 
   4113             //frame Flag for status messages
   4114             memFragPtr[index++] = ID3V2_FLAGS;
   4115 
   4116             //frame flag for format description
   4117             memFragPtr[index++] = ID3V2_FLAGS;
   4118         }
   4119 
   4120         switch (kvpValueType)
   4121         {
   4122             case PVMI_KVPVALTYPE_CHARPTR:
   4123                 memFragPtr[index++] = (uint8) charSet;
   4124                 frameDataSize -= 2; // Minus 1 byte for the character set and 1 byte for NULL character
   4125                 oscl_memcpy(memFragPtr + index, iFrames[i]->value.pChar_value, frameDataSize);
   4126                 index += frameDataSize;
   4127                 memFragPtr[index++] = 0; // NULL terminate the string
   4128                 break;
   4129             case PVMI_KVPVALTYPE_WCHARPTR:
   4130                 memFragPtr[index++] = (uint8)charSet;
   4131                 frameDataSize -= 3; // Minus 1 byte for the character set and 2 bytes for NULL character
   4132                 if (charSet == PV_ID3_CHARSET_UTF16)
   4133                 {
   4134 #if (OSCL_BYTE_ORDER_LITTLE_ENDIAN)
   4135                     memFragPtr[index++] = UNICODE_LITTLE_ENDIAN_INDICATOR;
   4136                     memFragPtr[index++] = UNICODE_BIG_ENDIAN_INDICATOR;
   4137 #elif (OSCL_BYTE_ORDER_BIG_ENDIAN)
   4138                     memFragPtr[index++] = UNICODE_BIG_ENDIAN_INDICATOR;
   4139                     memFragPtr[index++] = UNICODE_LITTLE_ENDIAN_INDICATOR;
   4140 
   4141 #else
   4142 #error "Byte order not specified"
   4143 #endif
   4144                     frameDataSize -= 2; // Minus 1 byte for byte order
   4145                 }
   4146                 oscl_memcpy(memFragPtr + index, iFrames[i]->value.pWChar_value, frameDataSize);
   4147                 index += frameDataSize;
   4148                 memFragPtr[index++] = 0; // NULL terminate the string
   4149                 memFragPtr[index++] = 0; // NULL terminate the string
   4150                 break;
   4151             case PVMI_KVPVALTYPE_UINT32:
   4152                 // Track length frame
   4153                 oscl_snprintf((char*)(memFragPtr + index), frameDataSize, "%d\0", iFrames[i]->value.uint32_value);
   4154                 break;
   4155             case PVMI_KVPVALTYPE_KSV:
   4156                 // Comment frame
   4157                 memFragPtr[index++] = (uint8)charSet;
   4158                 frameDataSize -= 1; // Minus 1 byte for the character set
   4159                 break;
   4160             default:
   4161                 LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - Unsupported key-value pair value type"));
   4162                 return PVMFErrNotSupported;
   4163         }
   4164 
   4165     }
   4166 
   4167     //if padding is on and the tag size is less than the maximum tag specified, do the padding
   4168     if (iUseMaxTagSize && iUsePadding && (index < iMaxTagSize))
   4169     {
   4170         oscl_memset((OsclAny*)(memFragPtr + index), 0, (iMaxTagSize - index));
   4171         my_memfrag.len = iMaxTagSize;
   4172     }
   4173     else
   4174     {
   4175         //save the filesize into the memory fragment
   4176         my_memfrag.len = index;
   4177     }
   4178 
   4179     return PVMFSuccess;
   4180 }
   4181 
   4182 ////////////////////////////////////////////////////////////////////////////
   4183 PVID3ParCom::PVID3FrameType PVID3ParCom::FrameValidatedID3V2_4(uint8* aFrameID)
   4184 {
   4185     PVID3FrameType ID3V2FrameTypeReturnValue;
   4186 
   4187     if ((oscl_memcmp(aFrameID, ID3_FRAME_ID_ENCRYPTION, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4188             (oscl_memcmp(aFrameID, ID3_FRAME_ID_AUDIO_SEEK_POINT_INDEX, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4189             (oscl_memcmp(aFrameID, ID3_FRAME_ID_COMMERCIAL_FRAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4190             (oscl_memcmp(aFrameID, ID3_FRAME_ID_ENCRYPTION_REGISTRATION, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4191             (oscl_memcmp(aFrameID, ID3_FRAME_ID_EQUALIZATION2, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4192             (oscl_memcmp(aFrameID, ID3_FRAME_ID_EVENT_TIMING_CODES, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4193             (oscl_memcmp(aFrameID, ID3_FRAME_ID_GENERAL_ENCAPSULATED_OBJECT, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4194             (oscl_memcmp(aFrameID, ID3_FRAME_ID_GROUP_IDENTITY_REGISTRATION, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4195             (oscl_memcmp(aFrameID, ID3_FRAME_ID_LINKED_INFORMATION, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4196             (oscl_memcmp(aFrameID, ID3_FRAME_ID_MUSIC_CD_IDENTIFIER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4197             (oscl_memcmp(aFrameID, ID3_FRAME_ID_MPEG_LOCATION_LOOKUP_TABLE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4198             (oscl_memcmp(aFrameID, ID3_FRAME_ID_OWNERSHIP_FRAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4199             (oscl_memcmp(aFrameID, ID3_FRAME_ID_PRIVATE_FRAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4200             (oscl_memcmp(aFrameID, ID3_FRAME_ID_PLAY_COUNTER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4201             (oscl_memcmp(aFrameID, ID3_FRAME_ID_POPULARIMETER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4202             (oscl_memcmp(aFrameID, ID3_FRAME_ID_POSITION_SYNCH_FRAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4203             (oscl_memcmp(aFrameID, ID3_FRAME_ID_RECOMMENDED_BUFFER_SIZE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4204             (oscl_memcmp(aFrameID, ID3_FRAME_ID_RELATIVE_VOLUME_ADJUSTMENT2, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4205             (oscl_memcmp(aFrameID, ID3_FRAME_ID_REVERB, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4206             (oscl_memcmp(aFrameID, ID3_FRAME_ID_SYNCHRONIZED_LYRICS_TEXT, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4207             (oscl_memcmp(aFrameID, ID3_FRAME_ID_SYNCHRONIZED_TEMPO_CODES, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4208             (oscl_memcmp(aFrameID, ID3_FRAME_ID_BPM, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4209             (oscl_memcmp(aFrameID, ID3_FRAME_ID_PLAYLIST_DELAY, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4210             (oscl_memcmp(aFrameID, ID3_FRAME_ID_FILE_TYPE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4211             (oscl_memcmp(aFrameID, ID3_FRAME_ID_CONTENT_GROUP_DESC, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4212             (oscl_memcmp(aFrameID, ID3_FRAME_ID_INITIAL_KEY, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4213             (oscl_memcmp(aFrameID, ID3_FRAME_ID_LANGUAGE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4214             (oscl_memcmp(aFrameID, ID3_FRAME_ID_MEDIA_TYPE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4215             (oscl_memcmp(aFrameID, ID3_FRAME_ID_ORIGINAL_ALBUM, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4216             (oscl_memcmp(aFrameID, ID3_FRAME_ID_ORIGINAL_FILENAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4217             (oscl_memcmp(aFrameID, ID3_FRAME_ID_ORIGINAL_LYRICIST, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4218             (oscl_memcmp(aFrameID, ID3_FRAME_ID_ORIGINAL_ARTIST, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4219             (oscl_memcmp(aFrameID, ID3_FRAME_ID_FILE_LICENSEE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4220             (oscl_memcmp(aFrameID, ID3_FRAME_ID_BAND, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4221             (oscl_memcmp(aFrameID, ID3_FRAME_ID_CONDUCTOR, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4222             (oscl_memcmp(aFrameID, ID3_FRAME_ID_MODIFIER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4223             (oscl_memcmp(aFrameID, ID3_FRAME_ID_PART_OF_SET, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4224             (oscl_memcmp(aFrameID, ID3_FRAME_ID_PUBLISHER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4225             (oscl_memcmp(aFrameID, ID3_FRAME_ID_INTERNET_RADIO_STATION_NAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4226             (oscl_memcmp(aFrameID, ID3_FRAME_ID_INTERNET_RADIO_STATION_OWNER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4227             (oscl_memcmp(aFrameID, ID3_FRAME_ID_RECORDING_CODE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4228             (oscl_memcmp(aFrameID, ID3_FRAME_ID_SOFTWARE_SETTING_ENCODE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4229             (oscl_memcmp(aFrameID, ID3_FRAME_ID_UNIQUE_FILE_IDENTIFIER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4230             (oscl_memcmp(aFrameID, ID3_FRAME_ID_TERMS_OF_USE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4231             (oscl_memcmp(aFrameID, ID3_FRAME_ID_COMMERCIAL_INFO, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4232             (oscl_memcmp(aFrameID, ID3_FRAME_ID_LEGAL_INFO, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4233             (oscl_memcmp(aFrameID, ID3_FRAME_ID_OFFICIAL_AUDIO_FILE_WEBPAGE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4234             (oscl_memcmp(aFrameID, ID3_FRAME_ID_OFFICIAL_ARTIST_WEBPAGE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4235             (oscl_memcmp(aFrameID, ID3_FRAME_ID_OFFICIAL_AUDIO__SOURCE_WEBPAGE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4236             (oscl_memcmp(aFrameID, ID3_FRAME_ID_OFFICIAL_RADIO_STATION_WEBPAGE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4237             (oscl_memcmp(aFrameID, ID3_FRAME_ID_PAYMENT, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4238             (oscl_memcmp(aFrameID, ID3_FRAME_ID_PUBLISHER_OFFICIAL_WEBPAGE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4239             (oscl_memcmp(aFrameID, ID3_FRAME_ID_USER_DEFINED_URL_LINK_FRAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4240             (oscl_memcmp(aFrameID, ID3_FRAME_ID_SIGNATURE_FRAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4241             (oscl_memcmp(aFrameID, ID3_FRAME_ID_ENCODING_TIME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4242             (oscl_memcmp(aFrameID, ID3_FRAME_ID_ORIGINAL_RELEASE_TIME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4243             (oscl_memcmp(aFrameID, ID3_FRAME_ID_RELEASE_TIME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4244             (oscl_memcmp(aFrameID, ID3_FRAME_ID_TAGGING_TIME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4245             (oscl_memcmp(aFrameID, ID3_FRAME_ID_INVOLVED_PEOPLE_LIST, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4246             (oscl_memcmp(aFrameID, ID3_FRAME_ID_MUSICIAN_CREDITS_LIST, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4247             (oscl_memcmp(aFrameID, ID3_FRAME_ID_MOOD, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4248             (oscl_memcmp(aFrameID, ID3_FRAME_ID_PRODUCED_NOTICE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4249             (oscl_memcmp(aFrameID, ID3_FRAME_ID_ALBUM_SORT_ORDER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4250             (oscl_memcmp(aFrameID, ID3_FRAME_ID_PERFORMER_SORT_ORDER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4251             (oscl_memcmp(aFrameID, ID3_FRAME_ID_TITLE_SORT_ORDER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4252             (oscl_memcmp(aFrameID, ID3_FRAME_ID_SET_SUBTITLE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
   4253             (oscl_memcmp(aFrameID, ID3_FRAME_ID_USER_DEFINED_TEXT_INFO, ID3V2_FRAME_NUM_BYTES_ID) == 0)
   4254        )
   4255     {
   4256         ID3V2FrameTypeReturnValue = PV_ID3_FRAME_UNRECOGNIZED;
   4257     }
   4258     // The frame ID made out of the characters capital A-Z and 0-9.
   4259     else if (IS_POTENTIAL_FRAME_ID(aFrameID))
   4260     {
   4261         ID3V2FrameTypeReturnValue = PV_ID3_FRAME_CANDIDATE;
   4262     }
   4263     else
   4264     {
   4265         // Frame ID doesn't match with defined/possible frame Ids
   4266         ID3V2FrameTypeReturnValue = PV_ID3_FRAME_INVALID;
   4267     }
   4268     return ID3V2FrameTypeReturnValue;
   4269 }
   4270 
   4271 PVMFStatus PVID3ParCom::PushFrameToFrameVector(PvmiKvpSharedPtr& aFrame, PvmiKvpSharedPtrVector& aFrameVector)
   4272 {
   4273     int32 err = OsclErrNone;
   4274     OSCL_TRY(err, aFrameVector.push_back(aFrame););
   4275     OSCL_FIRST_CATCH_ANY(err,
   4276                          LOG_ERR((0, "PVID3ParCom::GetID3Frame: Error - aFrame.push_back failed"));
   4277                          return PVMFErrNoMemory;);
   4278     return PVMFSuccess;
   4279 }
   4280 
   4281 OsclAny* PVID3ParCom::AllocateValueArray(int32& aLeaveCode, PvmiKvpValueType aValueType, int32 aNumElements, OsclMemAllocator* aMemAllocator)
   4282 {
   4283     int32 leaveCode = OsclErrNone;
   4284     OsclAny* buffer = NULL;
   4285     switch (aValueType)
   4286     {
   4287         case PVMI_KVPVALTYPE_WCHARPTR:
   4288             if (aMemAllocator)
   4289             {
   4290                 OSCL_TRY(leaveCode,
   4291                          buffer = (oscl_wchar*) aMemAllocator->ALLOCATE(aNumElements););
   4292             }
   4293             else
   4294             {
   4295                 OSCL_TRY(leaveCode,
   4296                          buffer = (oscl_wchar*) OSCL_ARRAY_NEW(oscl_wchar, aNumElements););
   4297             }
   4298             break;
   4299 
   4300         case PVMI_KVPVALTYPE_CHARPTR:
   4301             if (aMemAllocator)
   4302             {
   4303                 OSCL_TRY(leaveCode,
   4304                          buffer = (char*) aMemAllocator->ALLOCATE(aNumElements););
   4305             }
   4306             else
   4307             {
   4308                 OSCL_TRY(leaveCode,
   4309                          buffer = (char*) OSCL_ARRAY_NEW(char, aNumElements););
   4310             }
   4311             break;
   4312         case PVMI_KVPVALTYPE_UINT8PTR:
   4313             if (aMemAllocator)
   4314             {
   4315                 OSCL_TRY(leaveCode,
   4316                          buffer = (uint8*) aMemAllocator->ALLOCATE(aNumElements););
   4317             }
   4318             else
   4319             {
   4320                 OSCL_TRY(leaveCode,
   4321                          buffer = (uint8*) OSCL_ARRAY_NEW(char, aNumElements););
   4322             }
   4323             break;
   4324         default:
   4325             break;
   4326     }
   4327     aLeaveCode = leaveCode;
   4328     return buffer;
   4329 }
   4330 
   4331 PvmiKvpSharedPtr PVID3ParCom::HandleErrorForKVPAllocation(OSCL_String& aKey, PvmiKvpValueType aValueType, uint32 aValueSize, bool &truncate, PVMFStatus &aStatus)
   4332 {
   4333     PvmiKvpSharedPtr kvp;
   4334     int32 err = OsclErrNone;
   4335     aStatus = PVMFSuccess;
   4336     OSCL_TRY(err, kvp = AllocateKvp(aKey, aValueType, aValueSize, truncate););
   4337     if (OsclErrNone != err)
   4338     {
   4339         LOG_ERR((0, "PVID3ParCom::SetID3Frame: Error - AllocateKvp failed"));
   4340         aStatus = PVMFErrNoMemory;
   4341     }
   4342     return kvp;
   4343 }
   4344