1 /*
2 * Copyright (C) 2023 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 "native_avmuxer.h"
17 #include <regex>
18 #include "avcodec_errors.h"
19 #include "avcodec_log.h"
20 #include "avmuxer.h"
21 #include "common/native_mfmagic.h"
22 #include "native_avmagic.h"
23
24 namespace {
25 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_MUXER, "NativeAVMuxer"};
26 }
27
28 using namespace OHOS::Media;
29 using namespace OHOS::MediaAVCodec;
30
31 struct AVMuxerObject : public OH_AVMuxer {
AVMuxerObjectAVMuxerObject32 explicit AVMuxerObject(const std::shared_ptr<AVMuxer> &muxer)
33 : OH_AVMuxer(AVMagic::AVCODEC_MAGIC_AVMUXER), muxer_(muxer) {}
34 ~AVMuxerObject() = default;
35
36 const std::shared_ptr<AVMuxer> muxer_;
37 };
38
OH_AVMuxer_Create(int32_t fd,OH_AVOutputFormat format)39 struct OH_AVMuxer *OH_AVMuxer_Create(int32_t fd, OH_AVOutputFormat format)
40 {
41 std::shared_ptr<AVMuxer> avmuxer = AVMuxerFactory::CreateAVMuxer(fd, static_cast<Plugins::OutputFormat>(format));
42 CHECK_AND_RETURN_RET_LOG(avmuxer != nullptr, nullptr, "create muxer failed!");
43 struct AVMuxerObject *object = new(std::nothrow) AVMuxerObject(avmuxer);
44 return object;
45 }
46
OH_AVMuxer_SetRotation(OH_AVMuxer * muxer,int32_t rotation)47 OH_AVErrCode OH_AVMuxer_SetRotation(OH_AVMuxer *muxer, int32_t rotation)
48 {
49 CHECK_AND_RETURN_RET_LOG(muxer != nullptr, AV_ERR_INVALID_VAL, "input muxer is nullptr!");
50 CHECK_AND_RETURN_RET_LOG(muxer->magic_ == AVMagic::AVCODEC_MAGIC_AVMUXER, AV_ERR_INVALID_VAL, "magic error!");
51
52 struct AVMuxerObject *object = reinterpret_cast<AVMuxerObject *>(muxer);
53 CHECK_AND_RETURN_RET_LOG(object->muxer_ != nullptr, AV_ERR_INVALID_VAL, "muxer_ is nullptr!");
54
55 std::shared_ptr<Meta> param = std::make_shared<Meta>();
56 param->Set<Tag::VIDEO_ROTATION>(static_cast<Plugins::VideoRotation>(rotation));
57 int32_t ret = object->muxer_->SetParameter(param);
58 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
59 "muxer_ SetRotation failed!");
60
61 return AV_ERR_OK;
62 }
63
CopyMetaData(const TagType & tag,std::shared_ptr<Meta> & fromMeta,std::shared_ptr<Meta> & toMeta)64 static void CopyMetaData(const TagType &tag, std::shared_ptr<Meta> &fromMeta, std::shared_ptr<Meta> &toMeta)
65 {
66 AnyValueType type = fromMeta->GetValueType(tag);
67 if (type == AnyValueType::INVALID_TYPE || type == AnyValueType::STRING) {
68 std::string value;
69 fromMeta->GetData(tag, value);
70 toMeta->SetData(tag, value);
71 } else if (type == AnyValueType::BOOL) {
72 bool value = false;
73 fromMeta->GetData(tag, value);
74 toMeta->SetData(tag, value);
75 } else if (type == AnyValueType::INT8_T) {
76 int8_t value = 0;
77 fromMeta->GetData(tag, value);
78 toMeta->SetData(tag, value);
79 } else if (type == AnyValueType::UINT8_T) {
80 uint8_t value = 0;
81 fromMeta->GetData(tag, value);
82 toMeta->SetData(tag, value);
83 } else if (type == AnyValueType::INT32_T) {
84 int32_t value = 0;
85 fromMeta->GetData(tag, value);
86 toMeta->SetData(tag, value);
87 } else if (type == AnyValueType::UINT32_T) {
88 uint32_t value = 0;
89 fromMeta->GetData(tag, value);
90 toMeta->SetData(tag, value);
91 } else if (type == AnyValueType::INT64_T) {
92 int64_t value = 0;
93 fromMeta->GetData(tag, value);
94 toMeta->SetData(tag, value);
95 } else if (type == AnyValueType::UINT64_T) {
96 uint64_t value = 0;
97 fromMeta->GetData(tag, value);
98 toMeta->SetData(tag, value);
99 } else if (type == AnyValueType::FLOAT) {
100 float value = 0.0f;
101 fromMeta->GetData(tag, value);
102 toMeta->SetData(tag, value);
103 } else if (type == AnyValueType::DOUBLE) {
104 double value = 0.0;
105 fromMeta->GetData(tag, value);
106 toMeta->SetData(tag, value);
107 } else if (type == AnyValueType::VECTOR_UINT8) {
108 std::vector<uint8_t> value;
109 fromMeta->GetData(tag, value);
110 toMeta->SetData(tag, value);
111 }
112 }
113
SeparateMeta(std::shared_ptr<Meta> meta,std::shared_ptr<Meta> & definedMeta,std::shared_ptr<Meta> & userMeta)114 static void SeparateMeta(std::shared_ptr<Meta> meta, std::shared_ptr<Meta> &definedMeta,
115 std::shared_ptr<Meta> &userMeta)
116 {
117 for (auto iter = meta->begin(); iter != meta->end(); ++iter) {
118 TagType tag = iter->first;
119 if (meta->IsDefinedKey(tag)) {
120 CopyMetaData(tag, meta, definedMeta);
121 } else {
122 CopyMetaData(tag, meta, userMeta);
123 }
124 }
125 }
126
SetCreationTimeMeta(std::shared_ptr<Meta> definedMeta,std::shared_ptr<Meta> & param)127 static OH_AVErrCode SetCreationTimeMeta(std::shared_ptr<Meta> definedMeta, std::shared_ptr<Meta> ¶m)
128 {
129 if (definedMeta->Find(Tag::MEDIA_CREATION_TIME) == definedMeta->end()) {
130 return AV_ERR_OK;
131 }
132
133 AVCODEC_LOGI("set format defined key %{public}s", Tag::MEDIA_CREATION_TIME);
134 std::string value;
135 definedMeta->Get<Tag::MEDIA_CREATION_TIME>(value);
136 std::regex pattern(R"((\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(.\d{1,6})?((\+|-\d{4})?)Z?)");
137 std::smatch match;
138 CHECK_AND_RETURN_RET_LOG(std::regex_match(value, match, pattern), AV_ERR_INVALID_VAL, "creation time is invalid");
139
140 param->Set<Tag::MEDIA_CREATION_TIME>(value);
141 return AV_ERR_OK;
142 }
143
SetCommentMeta(std::shared_ptr<Meta> definedMeta,std::shared_ptr<Meta> & param)144 static OH_AVErrCode SetCommentMeta(std::shared_ptr<Meta> definedMeta, std::shared_ptr<Meta> ¶m)
145 {
146 if (definedMeta->Find(Tag::MEDIA_COMMENT) == definedMeta->end()) {
147 return AV_ERR_OK;
148 }
149
150 AVCODEC_LOGI("set format defined key %{public}s", Tag::MEDIA_COMMENT);
151 std::string comment;
152 definedMeta->Get<Tag::MEDIA_COMMENT>(comment);
153 std::regex pattern(R"(^.{1,256}$)");
154 std::smatch match;
155 CHECK_AND_RETURN_RET_LOG(std::regex_match(comment, match, pattern), AV_ERR_INVALID_VAL, "comment is invalid");
156
157 param->Set<Tag::MEDIA_COMMENT>(comment);
158 return AV_ERR_OK;
159 }
160
SetMoovFrontMeta(std::shared_ptr<Meta> definedMeta,std::shared_ptr<Meta> & param)161 static OH_AVErrCode SetMoovFrontMeta(std::shared_ptr<Meta> definedMeta, std::shared_ptr<Meta> ¶m)
162 {
163 if (definedMeta->Find(Tag::MEDIA_ENABLE_MOOV_FRONT) == definedMeta->end()) {
164 return AV_ERR_OK;
165 }
166
167 AVCODEC_LOGI("set format defined key %{public}s", Tag::MEDIA_ENABLE_MOOV_FRONT);
168 int32_t isFront;
169 definedMeta->Get<Tag::MEDIA_ENABLE_MOOV_FRONT>(isFront);
170 param->Set<Tag::MEDIA_ENABLE_MOOV_FRONT>(isFront);
171 return AV_ERR_OK;
172 }
173
SetDefinedMetaParam(std::shared_ptr<Meta> definedMeta,AVMuxerObject * object)174 static OH_AVErrCode SetDefinedMetaParam(std::shared_ptr<Meta> definedMeta, AVMuxerObject* object)
175 {
176 std::shared_ptr<Meta> param = std::make_shared<Meta>();
177
178 OH_AVErrCode metaRet = SetCreationTimeMeta(definedMeta, param);
179 CHECK_AND_RETURN_RET_LOG(metaRet == AV_ERR_OK, AV_ERR_INVALID_VAL, "input format is invalid");
180 metaRet = SetCommentMeta(definedMeta, param);
181 CHECK_AND_RETURN_RET_LOG(metaRet == AV_ERR_OK, AV_ERR_INVALID_VAL, "input format is invalid");
182 metaRet = SetMoovFrontMeta(definedMeta, param);
183 CHECK_AND_RETURN_RET_LOG(metaRet == AV_ERR_OK, AV_ERR_INVALID_VAL, "input format is invalid");
184
185 if (param->Empty()) {
186 AVCODEC_LOGW("input format does not have a valid key");
187 return AV_ERR_OK;
188 }
189
190 int32_t ret = object->muxer_->SetParameter(param);
191 return AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret));
192 }
193
SetUserMetaParam(std::shared_ptr<Meta> userMeta,AVMuxerObject * object)194 static OH_AVErrCode SetUserMetaParam(std::shared_ptr<Meta> userMeta, AVMuxerObject *object)
195 {
196 int32_t ret = object->muxer_->SetUserMeta(userMeta);
197 return AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret));
198 }
199
OH_AVMuxer_SetFormat(OH_AVMuxer * muxer,OH_AVFormat * format)200 OH_AVErrCode OH_AVMuxer_SetFormat(OH_AVMuxer *muxer, OH_AVFormat *format)
201 {
202 CHECK_AND_RETURN_RET_LOG(muxer != nullptr, AV_ERR_INVALID_VAL, "input muxer is nullptr!");
203 CHECK_AND_RETURN_RET_LOG(muxer->magic_ == AVMagic::AVCODEC_MAGIC_AVMUXER, AV_ERR_INVALID_VAL, "magic error!");
204 CHECK_AND_RETURN_RET_LOG(format != nullptr, AV_ERR_INVALID_VAL, "input format is nullptr!");
205 CHECK_AND_RETURN_RET_LOG(format->magic_ == MFMagic::MFMAGIC_FORMAT, AV_ERR_INVALID_VAL,
206 "format magic error!");
207
208 struct AVMuxerObject *object = reinterpret_cast<AVMuxerObject *>(muxer);
209 CHECK_AND_RETURN_RET_LOG(object->muxer_ != nullptr, AV_ERR_INVALID_VAL, "muxer_ is nullptr!");
210
211 std::shared_ptr<Meta> meta = format->format_.GetMeta();
212 std::shared_ptr<Meta> definedMeta = std::make_shared<Meta>();
213 std::shared_ptr<Meta> userMeta = std::make_shared<Meta>();
214
215 CHECK_AND_RETURN_RET_LOG(meta != nullptr, AV_ERR_INVALID_VAL, "input format is nullptr!");
216 SeparateMeta(meta, definedMeta, userMeta);
217
218 OH_AVErrCode ret = AV_ERR_OK;
219 if (definedMeta != nullptr && !definedMeta->Empty()) {
220 ret = SetDefinedMetaParam(definedMeta, object);
221 CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, ret, "muxer_ SetFormat SetDefinedMetaParam failed!");
222 }
223
224 if (userMeta != nullptr && !userMeta->Empty()) {
225 ret = SetUserMetaParam(userMeta, object);
226 CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, ret, "muxer_ SetFormat SetUserMetaParam failed!");
227 }
228 return AV_ERR_OK;
229 }
230
OH_AVMuxer_AddTrack(OH_AVMuxer * muxer,int32_t * trackIndex,OH_AVFormat * trackFormat)231 OH_AVErrCode OH_AVMuxer_AddTrack(OH_AVMuxer *muxer, int32_t *trackIndex, OH_AVFormat *trackFormat)
232 {
233 CHECK_AND_RETURN_RET_LOG(muxer != nullptr, AV_ERR_INVALID_VAL, "input muxer is nullptr!");
234 CHECK_AND_RETURN_RET_LOG(muxer->magic_ == AVMagic::AVCODEC_MAGIC_AVMUXER, AV_ERR_INVALID_VAL, "magic error!");
235 CHECK_AND_RETURN_RET_LOG(trackIndex != nullptr, AV_ERR_INVALID_VAL, "input track index is nullptr!");
236 CHECK_AND_RETURN_RET_LOG(trackFormat != nullptr, AV_ERR_INVALID_VAL, "input track format is nullptr!");
237 CHECK_AND_RETURN_RET_LOG(trackFormat->magic_ == MFMagic::MFMAGIC_FORMAT, AV_ERR_INVALID_VAL,
238 "track format magic error!");
239
240 struct AVMuxerObject *object = reinterpret_cast<AVMuxerObject *>(muxer);
241 CHECK_AND_RETURN_RET_LOG(object->muxer_ != nullptr, AV_ERR_INVALID_VAL, "muxer_ is nullptr!");
242
243 int32_t ret = object->muxer_->AddTrack(*trackIndex, trackFormat->format_.GetMeta());
244 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
245 "muxer_ AddTrack failed!");
246
247 return AV_ERR_OK;
248 }
249
OH_AVMuxer_Start(OH_AVMuxer * muxer)250 OH_AVErrCode OH_AVMuxer_Start(OH_AVMuxer *muxer)
251 {
252 CHECK_AND_RETURN_RET_LOG(muxer != nullptr, AV_ERR_INVALID_VAL, "input muxer is nullptr!");
253 CHECK_AND_RETURN_RET_LOG(muxer->magic_ == AVMagic::AVCODEC_MAGIC_AVMUXER, AV_ERR_INVALID_VAL, "magic error!");
254
255 struct AVMuxerObject *object = reinterpret_cast<AVMuxerObject *>(muxer);
256 CHECK_AND_RETURN_RET_LOG(object->muxer_ != nullptr, AV_ERR_INVALID_VAL, "muxer_ is nullptr!");
257
258 int32_t ret = object->muxer_->Start();
259 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
260 "muxer_ Start failed!");
261
262 return AV_ERR_OK;
263 }
264
OH_AVMuxer_WriteSample(OH_AVMuxer * muxer,uint32_t trackIndex,OH_AVMemory * sample,OH_AVCodecBufferAttr info)265 OH_AVErrCode OH_AVMuxer_WriteSample(OH_AVMuxer *muxer, uint32_t trackIndex,
266 OH_AVMemory *sample, OH_AVCodecBufferAttr info)
267 {
268 CHECK_AND_RETURN_RET_LOG(muxer != nullptr, AV_ERR_INVALID_VAL, "input muxer is nullptr!");
269 CHECK_AND_RETURN_RET_LOG(muxer->magic_ == AVMagic::AVCODEC_MAGIC_AVMUXER, AV_ERR_INVALID_VAL, "magic error!");
270 CHECK_AND_RETURN_RET_LOG(sample != nullptr, AV_ERR_INVALID_VAL, "input sample is nullptr!");
271 CHECK_AND_RETURN_RET_LOG(sample->magic_ == MFMagic::MFMAGIC_SHARED_MEMORY, AV_ERR_INVALID_VAL,
272 "sample magic error!");
273 CHECK_AND_RETURN_RET_LOG(sample->memory_ != nullptr && info.offset >= 0 && info.size >= 0 &&
274 sample->memory_->GetSize() >= (info.offset + info.size), AV_ERR_INVALID_VAL, "invalid memory");
275
276 struct AVMuxerObject *object = reinterpret_cast<AVMuxerObject *>(muxer);
277 CHECK_AND_RETURN_RET_LOG(object->muxer_ != nullptr, AV_ERR_INVALID_VAL, "muxer_ is nullptr!");
278
279 std::shared_ptr<AVBuffer> buffer = AVBuffer::CreateAVBuffer(sample->memory_->GetBase() + info.offset,
280 sample->memory_->GetSize(), info.size);
281 CHECK_AND_RETURN_RET_LOG(buffer != nullptr, AV_ERR_NO_MEMORY, "create buffer failed");
282 buffer->pts_ = info.pts;
283 buffer->flag_ = info.flags;
284
285 int32_t ret = object->muxer_->WriteSample(trackIndex, buffer);
286 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
287 "muxer_ WriteSample failed!");
288
289 return AV_ERR_OK;
290 }
291
OH_AVMuxer_WriteSampleBuffer(OH_AVMuxer * muxer,uint32_t trackIndex,const OH_AVBuffer * sample)292 OH_AVErrCode OH_AVMuxer_WriteSampleBuffer(OH_AVMuxer *muxer, uint32_t trackIndex,
293 const OH_AVBuffer *sample)
294 {
295 CHECK_AND_RETURN_RET_LOG(muxer != nullptr, AV_ERR_INVALID_VAL, "input muxer is nullptr!");
296 CHECK_AND_RETURN_RET_LOG(muxer->magic_ == AVMagic::AVCODEC_MAGIC_AVMUXER, AV_ERR_INVALID_VAL, "magic error!");
297 CHECK_AND_RETURN_RET_LOG(sample != nullptr, AV_ERR_INVALID_VAL, "input sample is nullptr!");
298 CHECK_AND_RETURN_RET_LOG(sample->magic_ == MFMagic::MFMAGIC_AVBUFFER, AV_ERR_INVALID_VAL,
299 "sample magic error!");
300
301 struct AVMuxerObject *object = reinterpret_cast<AVMuxerObject *>(muxer);
302 CHECK_AND_RETURN_RET_LOG(object->muxer_ != nullptr, AV_ERR_INVALID_VAL, "muxer_ is nullptr!");
303
304 int32_t ret = object->muxer_->WriteSample(trackIndex, sample->buffer_);
305 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
306 "muxer_ WriteSampleBuffer failed!");
307
308 return AV_ERR_OK;
309 }
310
OH_AVMuxer_Stop(OH_AVMuxer * muxer)311 OH_AVErrCode OH_AVMuxer_Stop(OH_AVMuxer *muxer)
312 {
313 CHECK_AND_RETURN_RET_LOG(muxer != nullptr, AV_ERR_INVALID_VAL, "input muxer is nullptr!");
314 CHECK_AND_RETURN_RET_LOG(muxer->magic_ == AVMagic::AVCODEC_MAGIC_AVMUXER, AV_ERR_INVALID_VAL, "magic error!");
315
316 struct AVMuxerObject *object = reinterpret_cast<AVMuxerObject *>(muxer);
317 CHECK_AND_RETURN_RET_LOG(object->muxer_ != nullptr, AV_ERR_INVALID_VAL, "muxer_ is nullptr!");
318
319 int32_t ret = object->muxer_->Stop();
320 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
321 "muxer_ Stop failed!");
322
323 return AV_ERR_OK;
324 }
325
OH_AVMuxer_Destroy(OH_AVMuxer * muxer)326 OH_AVErrCode OH_AVMuxer_Destroy(OH_AVMuxer *muxer)
327 {
328 CHECK_AND_RETURN_RET_LOG(muxer != nullptr, AV_ERR_INVALID_VAL, "input muxer is nullptr!");
329 CHECK_AND_RETURN_RET_LOG(muxer->magic_ == AVMagic::AVCODEC_MAGIC_AVMUXER, AV_ERR_INVALID_VAL, "magic error!");
330
331 delete muxer;
332
333 return AV_ERR_OK;
334 }