• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012, 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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "MediaCodecListWriter"
19 #include <utils/Log.h>
20 
21 #include <media/stagefright/foundation/AMessage.h>
22 #include "media/stagefright/foundation/AString.h"
23 #include <media/stagefright/MediaCodecListWriter.h>
24 #include <media/MediaCodecInfo.h>
25 
26 #include <string>
27 
28 namespace android {
29 
addGlobalSetting(const char * key,const char * value)30 void MediaCodecListWriter::addGlobalSetting(
31         const char* key, const char* value) {
32     mGlobalSettings.emplace_back(key, value);
33 }
34 
35 std::unique_ptr<MediaCodecInfoWriter>
addMediaCodecInfo()36         MediaCodecListWriter::addMediaCodecInfo() {
37     sp<MediaCodecInfo> info = new MediaCodecInfo();
38     mCodecInfos.push_back(info);
39     return std::unique_ptr<MediaCodecInfoWriter>(
40             new MediaCodecInfoWriter(info.get()));
41 }
42 
43 std::unique_ptr<MediaCodecInfoWriter>
findMediaCodecInfo(const char * name)44         MediaCodecListWriter::findMediaCodecInfo(const char *name) {
45     for (const sp<MediaCodecInfo> &info : mCodecInfos) {
46         if (!strcmp(info->getCodecName(), name)) {
47             return std::unique_ptr<MediaCodecInfoWriter>(new MediaCodecInfoWriter(info.get()));
48         }
49     }
50     return nullptr;
51 }
52 
writeGlobalSettings(const sp<AMessage> & globalSettings) const53 void MediaCodecListWriter::writeGlobalSettings(
54         const sp<AMessage> &globalSettings) const {
55     for (const std::pair<std::string, std::string> &kv : mGlobalSettings) {
56         globalSettings->setString(kv.first.c_str(), kv.second.c_str());
57     }
58 }
59 
writeCodecInfos(std::vector<sp<MediaCodecInfo>> * codecInfos) const60 void MediaCodecListWriter::writeCodecInfos(
61         std::vector<sp<MediaCodecInfo>> *codecInfos) const {
62     // Since the introduction of the NDK MediaCodecList API, each
63     // MediaCodecInfo object can only support a single media type, so infos that
64     // support multiple media types are split into multiple infos.
65     // This process may result in name collisions that are handled here.
66 
67     // Prefer codec names that already support a single media type
68     // and also any existing aliases. If an alias matches an existing
69     // codec name, it is ignored, which is the right behavior.
70     std::set<std::string> reservedNames;
71     for (const sp<MediaCodecInfo> &info : mCodecInfos) {
72         Vector<AString> mediaTypes;
73         info->getSupportedMediaTypes(&mediaTypes);
74         if (mediaTypes.size() == 1) {
75             reservedNames.insert(info->getCodecName());
76         }
77         Vector<AString> aliases;
78         info->getAliases(&aliases);
79         for (const AString &alias : aliases) {
80             reservedNames.insert(alias.c_str());
81         }
82     }
83 
84     for (const sp<MediaCodecInfo> &info : mCodecInfos) {
85         Vector<AString> mediaTypes;
86         info->getSupportedMediaTypes(&mediaTypes);
87         if (mediaTypes.size() == 1) {
88             codecInfos->push_back(info);
89         } else {
90             // disambiguate each type
91             for (const AString &mediaType : mediaTypes) {
92                 // get the type name after the first slash (if exists)
93                 ssize_t slashPosition = mediaType.find("/");
94                 const char *typeName = mediaType.c_str() + (slashPosition + 1);
95 
96                 // find a unique name for the split codec info starting with "<name>.<type>"
97                 AString newName = AStringPrintf("%s.%s", info->getCodecName(), typeName);
98                 std::string newNameStr = newName.c_str();
99                 // append increasing suffix of the form ".<number>" until a unique name is found
100                 for (size_t ix = 1; reservedNames.count(newNameStr) > 0; ++ix) {
101                     newNameStr = AStringPrintf("%s.%zu", newName.c_str(), ix).c_str();
102                 }
103 
104                 codecInfos->push_back(info->splitOutType(mediaType.c_str(), newNameStr.c_str()));
105                 reservedNames.insert(newNameStr);
106             }
107         }
108     }
109 }
110 
111 }  // namespace android
112