• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "avmuxer_util.h"
17 #include <tuple>
18 #include "media_errors.h"
19 #include "media_log.h"
20 
21 namespace {
22     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AVMuxerUtil"};
23 }
24 
25 namespace OHOS {
26 namespace Media {
27 struct MultiValue {
MultiValueOHOS::Media::MultiValue28     explicit MultiValue(int32_t val)
29     {
30         val_.intVal = val;
31     }
MultiValueOHOS::Media::MultiValue32     explicit MultiValue(const char *val)
33     {
34         val_.stringVal = val;
35     }
36     union Val {
37         int32_t intVal;
38         const char *stringVal;
39     } val_ = {0};
40 };
41 
42 struct FormatInfo {
43     std::string mux_;
44     std::set<std::string> mimeTypes_;
45 };
46 
47 struct MimeInfo {
48     std::string innerType_;
49     std::string parse_;
50     MediaType mediaType_;
51 };
52 
53 struct CapsInfo {
54     std::string key_;
55     GType type_;
56     MultiValue value_;
57 };
58 
59 const std::map<std::string, FormatInfo> FORMAT_INFO = {
60     {"mp4", {"mp4mux", {"video/avc", "video/mp4v-es", "video/h263", "audio/mp4a-latm", "audio/mpeg"}}},
61     {"m4a", {"mp4mux", {"audio/mp4a-latm"}}},
62 };
63 
64 const std::map<const std::string, MimeInfo> MIME_INFO = {
65     {"video/avc", {"video/x-h264", "h264parse", MEDIA_TYPE_VID}},
66     {"video/h263", {"video/x-h263", "", MEDIA_TYPE_VID}},
67     {"video/mp4v-es", {"video/mpeg", "mpeg4videoparse", MEDIA_TYPE_VID}},
68     {"audio/mp4a-latm", {"audio/mpeg", "aacparse", MEDIA_TYPE_AUD}},
69     {"audio/mpeg", {"audio/mpeg", "", MEDIA_TYPE_AUD}}
70 };
71 
72 std::map<std::string, std::vector<CapsInfo>> optionCapsMap = {
73     {"video/avc", {
74         {"alignment", G_TYPE_STRING, MultiValue("nal")},
75         {"stream-format", G_TYPE_STRING, MultiValue("byte-stream")}
76     }},
77     {"video/h263", {
78     }},
79     {"video/mp4v-es", {
80         {"mpegversion", G_TYPE_INT, MultiValue(4)},
81         {"systemstream", G_TYPE_BOOLEAN, MultiValue(FALSE)}
82     }},
83     {"audio/mp4a-latm", {
84         {"mpegversion", G_TYPE_INT, MultiValue(4)},
85         {"stream-format", G_TYPE_STRING, MultiValue("adts")}
86     }},
87     {"audio/mpeg", {
88         {"mpegversion", G_TYPE_INT, MultiValue(1)},
89         {"layer", G_TYPE_INT, MultiValue(3)}
90     }}
91 };
92 
parseParam(FormatParam & param,const MediaDescription & trackDesc,const std::string & mimeType)93 static int32_t parseParam(FormatParam &param, const MediaDescription &trackDesc, const std::string &mimeType)
94 {
95     MediaType mediaType;
96     CHECK_AND_RETURN_RET_LOG(AVMuxerUtil::FindMediaType(mimeType, mediaType), MSERR_INVALID_VAL, "Illegal mimeType");
97     if (mediaType == MEDIA_TYPE_VID) {
98         CHECK_AND_RETURN_RET_LOG(trackDesc.GetIntValue(MediaDescriptionKey::MD_KEY_WIDTH, param.width),
99             MSERR_INVALID_VAL, "Failed to get MD_KEY_WIDTH");
100         CHECK_AND_RETURN_RET_LOG(trackDesc.GetIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, param.height),
101             MSERR_INVALID_VAL, "Failed to get MD_KEY_HEIGHT");
102         CHECK_AND_RETURN_RET_LOG(trackDesc.GetIntValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, param.frameRate),
103             MSERR_INVALID_VAL, "Failed to get MD_KEY_FRAME_RATE");
104         MEDIA_LOGD("width is: %{public}d, height is: %{public}d, frameRate is: %{public}d",
105             param.width, param.height, param.frameRate);
106     } else if (mediaType == MEDIA_TYPE_AUD) {
107         CHECK_AND_RETURN_RET_LOG(
108             trackDesc.GetIntValue(MediaDescriptionKey::MD_KEY_CHANNEL_COUNT, param.channels),
109             MSERR_INVALID_VAL, "Failed to get MD_KEY_CHANNEL_COUNT");
110         CHECK_AND_RETURN_RET_LOG(trackDesc.GetIntValue(MediaDescriptionKey::MD_KEY_SAMPLE_RATE, param.rate),
111             MSERR_INVALID_VAL, "Failed to get MD_KEY_SAMPLE_RATE");
112         MEDIA_LOGD("channels is: %{public}d, rate is: %{public}d", param.channels, param.rate);
113     } else {
114         MEDIA_LOGD("Faild to check track type");
115         return MSERR_INVALID_VAL;
116     }
117 
118     return MSERR_OK;
119 }
120 
AddOptionCaps(GstCaps * src_caps,const std::string & mimeType)121 static void AddOptionCaps(GstCaps *src_caps, const std::string &mimeType)
122 {
123     for (auto& elements : optionCapsMap[mimeType]) {
124         switch (elements.type_) {
125             case G_TYPE_BOOLEAN:
126             case G_TYPE_INT:
127                 gst_caps_set_simple(src_caps,
128                     elements.key_.c_str(),
129                     elements.type_,
130                     elements.value_.val_.intVal,
131                     nullptr);
132                 break;
133             case G_TYPE_STRING:
134                 gst_caps_set_simple(src_caps,
135                     elements.key_.c_str(),
136                     elements.type_,
137                     elements.value_.val_.stringVal,
138                     nullptr);
139                 break;
140             default:
141                 break;
142         }
143     }
144 }
145 
CreateCaps(FormatParam & param,const std::string & mimeType)146 static GstCaps *CreateCaps(FormatParam &param, const std::string &mimeType)
147 {
148     GstCaps *src_caps = nullptr;
149     std::string innerType;
150     MediaType mediaType;
151     CHECK_AND_RETURN_RET_LOG(AVMuxerUtil::FindInnerTypes(mimeType, innerType), nullptr, "Illegal mimeType");
152     CHECK_AND_RETURN_RET_LOG(AVMuxerUtil::FindMediaType(mimeType, mediaType), nullptr, "Illegal mimeType");
153     if (mediaType == MEDIA_TYPE_VID) {
154         src_caps = gst_caps_new_simple(innerType.c_str(),
155             "width", G_TYPE_INT, param.width,
156             "height", G_TYPE_INT, param.height,
157             "framerate", GST_TYPE_FRACTION, param.frameRate, 1,
158             nullptr);
159     } else if (mediaType == MEDIA_TYPE_AUD) {
160         src_caps = gst_caps_new_simple(innerType.c_str(),
161             "channels", G_TYPE_INT, param.channels,
162             "rate", G_TYPE_INT, param.rate,
163             nullptr);
164     } else {
165         MEDIA_LOGE("Failed to check track type");
166         return nullptr;
167     }
168     AddOptionCaps(src_caps, mimeType);
169 
170     return src_caps;
171 }
172 
SetCaps(const MediaDescription & trackDesc,const std::string & mimeType,GstCaps ** src_caps)173 bool AVMuxerUtil::SetCaps(const MediaDescription &trackDesc, const std::string &mimeType,
174     GstCaps **src_caps)
175 {
176     MEDIA_LOGD("Set %{public}s caps", mimeType.c_str());
177     CHECK_AND_RETURN_RET_LOG(src_caps != nullptr, false, "src_caps is nullptr");
178     FormatParam param;
179     bool ret = parseParam(param, trackDesc, mimeType);
180     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, false, "Failed to call parseParam");
181     *src_caps = CreateCaps(param, mimeType);
182 
183     return true;
184 }
185 
FindFormat()186 std::vector<std::string> AVMuxerUtil::FindFormat()
187 {
188     std::vector<std::string> formatList;
189     for (auto& formats : FORMAT_INFO) {
190         formatList.push_back(formats.first);
191     }
192     return formatList;
193 }
194 
FindMux(const std::string & format,std::string & mux)195 bool AVMuxerUtil::FindMux(const std::string &format, std::string &mux)
196 {
197     if (FORMAT_INFO.find(format) == FORMAT_INFO.end()) {
198         return false;
199     }
200     mux = FORMAT_INFO.at(format).mux_;
201     return true;
202 }
203 
FindMimeTypes(const std::string & format,std::set<std::string> & mimeTypes)204 bool AVMuxerUtil::FindMimeTypes(const std::string &format, std::set<std::string> &mimeTypes)
205 {
206     if (FORMAT_INFO.find(format) == FORMAT_INFO.end()) {
207         return false;
208     }
209     mimeTypes = FORMAT_INFO.at(format).mimeTypes_;
210     return true;
211 }
212 
FindInnerTypes(const std::string & mimeType,std::string & innerType)213 bool AVMuxerUtil::FindInnerTypes(const std::string &mimeType, std::string &innerType)
214 {
215     if (MIME_INFO.find(mimeType) == MIME_INFO.end()) {
216         return false;
217     }
218     innerType = MIME_INFO.at(mimeType).innerType_;
219     return true;
220 }
221 
FindParse(const std::string & mimeType,std::string & parse)222 bool AVMuxerUtil::FindParse(const std::string &mimeType, std::string &parse)
223 {
224     if (MIME_INFO.find(mimeType) == MIME_INFO.end()) {
225         return false;
226     }
227     parse = MIME_INFO.at(mimeType).parse_;
228     return true;
229 }
230 
FindMediaType(const std::string & mimeType,MediaType & mediaType)231 bool AVMuxerUtil::FindMediaType(const std::string &mimeType, MediaType &mediaType)
232 {
233     if (MIME_INFO.find(mimeType) == MIME_INFO.end()) {
234         return false;
235     }
236     mediaType = MIME_INFO.at(mimeType).mediaType_;
237     return true;
238 }
239 }
240 }