summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/APE.cpp
blob: 74ca7dc4bfde83352d0f73e4707eed8db87c4b08 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/*
 * Copyright (C) Texas Instruments - http://www.ti.com/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "APE_TAG"
#include <utils/Log.h>

#include "include/APE.h"

namespace android {

APE::APE(){

}

APE::~APE(){

}

bool APE::isAPE(uint8_t *apeTag) const {
    if(apeTag[0] == 'A' && apeTag[1] == 'P' && apeTag[2] == 'E' &&
        apeTag[3] == 'T' && apeTag[4] == 'A' && apeTag[5] == 'G' &&
        apeTag[6] == 'E' && apeTag[7] == 'X'){
        return true;
    }
    return false;
}

size_t sizeItemKey(const sp<DataSource> &source, off64_t offset){
    off64_t ItemKeyOffset = offset;
    uint8_t keyTerminator = 0;
    size_t keySize = 0;
    while (keyTerminator != 0){
        source->readAt(ItemKeyOffset, &keyTerminator, 1);
        ItemKeyOffset++;
        keySize++;
    }
    return keySize - 1;
}

bool APE::parseAPE(const sp<DataSource> &source, off64_t offset,
        sp<MetaData> &meta){

    struct Map {
            int key;
            const char *tag;
    } const kMap[] = {
            { kKeyAlbum, "Album" },
            { kKeyArtist, "Artist" },
            { kKeyAlbumArtist, "Album" },
            { kKeyComposer, "Composer" },
            { kKeyGenre, "Genre" },
            { kKeyTitle, "Title" },
            { kKeyYear, "Year" },
            { kKeyCDTrackNumber, "Track" },
            { kKeyDate, "Record Date"},
    };

    static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);

    off64_t headerOffset = offset;
    headerOffset += 16;
    itemNumber = 0;
    if (source->readAt(headerOffset, &itemNumber, 1) == 0)
        return false;

    headerOffset += 16;

    for(uint32_t it = 0; it < itemNumber; it++){
        lenValue = 0;
        if (source->readAt(headerOffset, &lenValue, 1) == 0)
            return false;

        headerOffset += 4;

        itemFlags = 0;
        if (source->readAt(headerOffset, &itemFlags, 1) == 0)
            return false;

        headerOffset += 4;

        size_t sizeKey = sizeItemKey(source, headerOffset);

        char *key = new char[sizeKey];

        if (source->readAt(headerOffset, key, sizeKey) == 0)
            return false;

        key[sizeKey] = '\0';
        headerOffset += sizeKey + 1;

        char *val = new char[lenValue + 1];

        if (source->readAt(headerOffset, val, lenValue) == 0)
            return false;

        val[lenValue] = '\0';

        for (size_t i = 0; i < kNumMapEntries; i++){
            if (!strcmp(key, kMap[i].tag)){
                if (itemFlags == 0)
                    meta->setCString(kMap[i].key, (const char *)val);
                break;
            }
        }
        headerOffset += lenValue;
        delete[] key;
        delete[] val;
    }

    return true;
}
} //namespace android