1 /*
2  * Copyright (C) 2010 The Android Open Source Project
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 express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <MimeTypeUtil.h>
18 #include <utils/Log.h>
19 
20 namespace android {
21 
22 #undef LOG_TAG
23 #define LOG_TAG "MimeTypeUtil"
24 
25 #ifdef DRM_OMA_FL_ENGINE_DEBUG
26 #define LOG_NDEBUG 0
27 #define LOG_DEBUG(...) ALOGD(__VA_ARGS__)
28 #else
29 #define LOG_DEBUG(...)
30 #endif
31 
32 enum {
33     MIMETYPE_AUDIO       = 0,
34     MIMETYPE_APPLICATION = 1,
35     MIMETYPE_IMAGE       = 2,
36     MIMETYPE_VIDEO       = 3,
37     MIMETYPE_LAST        = -1,
38 };
39 
40 struct MimeGroup{
41     int         type;     // Audio, video,.. use the enum values
42     const char* pGroup;   // "audio/", "video/",.. should contain the last "/"
43     int         size;     // Number of bytes. e.g. "audio/" = 6 bytes
44 };
45 
46 struct MimeTypeList{
47     int         type;
48     const char* pMimeExt;  // Everything after the '/' e.g. audio/x-mpeg -> "x-mpeg"
49     int         size;      // Number of bytes. e.g. "x-mpeg" = 6 bytes
50     const char* pMimeType; // Mimetype that should be returned
51 };
52 
53 
54 // Known mimetypes by android
55 static const char mime_type_audio_mpeg[]  = "audio/mpeg";
56 static const char mime_type_audio_3gpp[]  = "audio/3gpp";
57 static const char mime_type_audio_amr[]   = "audio/amr-wb";
58 static const char mime_type_audio_aac[]   = "audio/mp4a-latm";
59 static const char mime_type_audio_wav[]   = "audio/wav";
60 
61 static const char mime_type_video_mpeg4[] = "video/mpeg4";
62 static const char mime_type_video_3gpp[]  = "video/3gpp";
63 
64 // Known mimetype groups
65 static const char mime_group_audio[]       = "audio/";
66 static const char mime_group_application[] = "application/";
67 static const char mime_group_image[]       = "image/";
68 static const char mime_group_video[]       = "video/";
69 static const char mime_type_unsupported[]  = "unsupported/drm.mimetype";
70 
71 static struct MimeGroup mimeGroup[] = {
72     {MIMETYPE_AUDIO,       mime_group_audio,        sizeof(mime_group_audio)-1},
73     {MIMETYPE_APPLICATION, mime_group_application,  sizeof(mime_group_application)-1},
74     {MIMETYPE_IMAGE,       mime_group_image,        sizeof(mime_group_image)-1},
75     {MIMETYPE_VIDEO,       mime_group_video,        sizeof(mime_group_video)-1},
76     {MIMETYPE_LAST,        NULL,                    0} // Must be last entry
77 };
78 
79 // List of all mimetypes that should be converted.
80 static struct MimeTypeList mimeTypeList[] = {
81     // Mp3 mime types
82     {MIMETYPE_AUDIO, "mp3",          sizeof("mp3")-1,         mime_type_audio_mpeg},
83     {MIMETYPE_AUDIO, "x-mpeg",       sizeof("x-mpeg")-1,      mime_type_audio_mpeg},
84     {MIMETYPE_AUDIO, "x-mp3",        sizeof("x-mp3")-1,       mime_type_audio_mpeg},
85     {MIMETYPE_AUDIO, "mpg",          sizeof("mpg")-1,         mime_type_audio_mpeg},
86     {MIMETYPE_AUDIO, "mpg3",         sizeof("mpg")-1,         mime_type_audio_mpeg},
87     {MIMETYPE_AUDIO, "x-mpg",        sizeof("x-mpg")-1,       mime_type_audio_mpeg},
88     {MIMETYPE_AUDIO, "x-mpegaudio",  sizeof("x-mpegaudio")-1, mime_type_audio_mpeg},
89 
90     // 3gpp audio mime types
91     {MIMETYPE_AUDIO, "3gp",          sizeof("3gp")-1,         mime_type_audio_3gpp},
92 
93     // Amr audio mime types
94     {MIMETYPE_AUDIO, "amr",          sizeof("amr")-1,         mime_type_audio_amr},
95 
96     // Aac audio mime types
97     {MIMETYPE_AUDIO, "aac",          sizeof("aac")-1,         mime_type_audio_aac},
98 
99     // Wav audio mime types
100     {MIMETYPE_AUDIO, "x-wav",        sizeof("x-wav")-1,       mime_type_audio_wav},
101 
102     // Mpeg4 video mime types
103     {MIMETYPE_VIDEO, "mpg4",         sizeof("mpg4")-1,        mime_type_video_mpeg4},
104     {MIMETYPE_VIDEO, "mp4v-es",      sizeof("mp4v-es")-1,     mime_type_video_mpeg4},
105 
106     // 3gpp video mime types
107     {MIMETYPE_VIDEO, "3gp",          sizeof("3gp")-1,         mime_type_video_3gpp},
108 
109     // Must be last entry
110     {MIMETYPE_LAST,  NULL,           0,                       NULL}
111 };
112 
113 /**
114  * May convert the mimetype if there is a well known
115  * replacement mimetype otherwise the original mimetype
116  * is returned.
117  *
118  * If the mimetype is of unsupported group i.e. application / *
119  * then "unsupported/drm.mimetype" will be returned.
120  *
121  * @param mimeType - mimetype in lower case to convert.
122  *
123  * @return mimetype or "unsupported/drm.mimetype".
124  */
convertMimeType(String8 & mimeType)125 String8 MimeTypeUtil::convertMimeType(String8& mimeType) {
126     String8 result = mimeType;
127     const char* pMimeType;
128     struct MimeGroup* pGroup;
129     struct MimeTypeList* pMimeItem;
130     int len;
131     pMimeType = mimeType.string();
132     if (NULL != pMimeType) {
133         if ((0 == strncmp(pMimeType, mime_group_audio, (sizeof mime_group_audio) - 1)) ||
134             (0 == strncmp(pMimeType, mime_group_video, (sizeof mime_group_video) - 1))) {
135             /* Check which group the mimetype is */
136             pGroup = mimeGroup;
137             while (MIMETYPE_LAST != pGroup->type) {
138                 if (0 == strncmp(pMimeType, pGroup->pGroup, pGroup->size)) {
139                     break;
140                 }
141                 pGroup++;
142             }
143 
144             /* Go through the mimetype list. Only check items of the correct group */
145             if (MIMETYPE_LAST != pGroup->type) {
146                 pMimeItem = mimeTypeList;
147                 len = strlen (pMimeType+pGroup->size);
148                 while (MIMETYPE_LAST != pMimeItem->type) {
149                     if ((pGroup->type == pMimeItem->type) &&
150                         (len == pMimeItem->size) &&
151                         (0 == strcmp(pMimeType+pGroup->size, pMimeItem->pMimeExt))) {
152                         result = String8(pMimeItem->pMimeType);
153                         break;
154                     }
155                     pMimeItem++;
156                 }
157             }
158         } else {
159             result = String8(mime_type_unsupported);
160         }
161         LOG_DEBUG("convertMimeType got mimetype %s, converted into mimetype %s",
162                 pMimeType, result.string());
163     }
164     return result;
165 }
166 };
167