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 }
108 }
109
SeparateMeta(std::shared_ptr<Meta> meta,std::shared_ptr<Meta> & definedMeta,std::shared_ptr<Meta> & userMeta)110 static void SeparateMeta(std::shared_ptr<Meta> meta, std::shared_ptr<Meta> &definedMeta,
111 std::shared_ptr<Meta> &userMeta)
112 {
113 for (auto iter = meta->begin(); iter != meta->end(); ++iter) {
114 TagType tag = iter->first;
115 if (meta->IsDefinedKey(tag)) {
116 CopyMetaData(tag, meta, definedMeta);
117 } else {
118 CopyMetaData(tag, meta, userMeta);
119 }
120 }
121 }
122
SetDefinedMetaParam(std::shared_ptr<Meta> definedMeta,AVMuxerObject * object)123 static OH_AVErrCode SetDefinedMetaParam(std::shared_ptr<Meta> definedMeta, AVMuxerObject *object)
124 {
125 std::shared_ptr<Meta> param = std::make_shared<Meta>();
126 if (definedMeta->Find(Tag::MEDIA_CREATION_TIME) != definedMeta->end()) {
127 AVCODEC_LOGI("set format defined key %{public}s", Tag::MEDIA_CREATION_TIME);
128 std::string value;
129 definedMeta->Get<Tag::MEDIA_CREATION_TIME>(value);
130 std::regex pattern(R"((\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(.\d{1,6})?((\+|-\d{4})?)Z?)");
131 std::smatch match;
132 CHECK_AND_RETURN_RET_LOG(std::regex_match(value, match, pattern), AV_ERR_INVALID_VAL,
133 "format defined key %{public}s, value invalid", Tag::MEDIA_CREATION_TIME);
134 param->Set<Tag::MEDIA_CREATION_TIME>(value);
135 } else {
136 AVCODEC_LOGW("input format does not have a valid key!");
137 return AV_ERR_OK;
138 }
139 int32_t ret = object->muxer_->SetParameter(param);
140 return AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret));
141 }
142
SetUserMetaParam(std::shared_ptr<Meta> userMeta,AVMuxerObject * object)143 static OH_AVErrCode SetUserMetaParam(std::shared_ptr<Meta> userMeta, AVMuxerObject *object)
144 {
145 int32_t ret = object->muxer_->SetUserMeta(userMeta);
146 return AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret));
147 }
148
OH_AVMuxer_SetFormat(OH_AVMuxer * muxer,OH_AVFormat * format)149 OH_AVErrCode OH_AVMuxer_SetFormat(OH_AVMuxer *muxer, OH_AVFormat *format)
150 {
151 CHECK_AND_RETURN_RET_LOG(muxer != nullptr, AV_ERR_INVALID_VAL, "input muxer is nullptr!");
152 CHECK_AND_RETURN_RET_LOG(muxer->magic_ == AVMagic::AVCODEC_MAGIC_AVMUXER, AV_ERR_INVALID_VAL, "magic error!");
153 CHECK_AND_RETURN_RET_LOG(format != nullptr, AV_ERR_INVALID_VAL, "input format is nullptr!");
154 CHECK_AND_RETURN_RET_LOG(format->magic_ == MFMagic::MFMAGIC_FORMAT, AV_ERR_INVALID_VAL,
155 "format magic error!");
156
157 struct AVMuxerObject *object = reinterpret_cast<AVMuxerObject *>(muxer);
158 CHECK_AND_RETURN_RET_LOG(object->muxer_ != nullptr, AV_ERR_INVALID_VAL, "muxer_ is nullptr!");
159
160 std::shared_ptr<Meta> meta = format->format_.GetMeta();
161 std::shared_ptr<Meta> definedMeta = std::make_shared<Meta>();
162 std::shared_ptr<Meta> userMeta = std::make_shared<Meta>();
163
164 CHECK_AND_RETURN_RET_LOG(meta != nullptr, AV_ERR_INVALID_VAL, "input format is nullptr!");
165 SeparateMeta(meta, definedMeta, userMeta);
166
167 OH_AVErrCode ret = SetDefinedMetaParam(definedMeta, object);
168 CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, ret, "muxer_ SetFormat SetDefinedMetaParam failed!");
169
170 if (userMeta != nullptr && !userMeta->Empty()) {
171 ret = SetUserMetaParam(userMeta, object);
172 CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, ret, "muxer_ SetFormat SetUserMetaParam failed!");
173 }
174 return AV_ERR_OK;
175 }
176
OH_AVMuxer_AddTrack(OH_AVMuxer * muxer,int32_t * trackIndex,OH_AVFormat * trackFormat)177 OH_AVErrCode OH_AVMuxer_AddTrack(OH_AVMuxer *muxer, int32_t *trackIndex, OH_AVFormat *trackFormat)
178 {
179 CHECK_AND_RETURN_RET_LOG(muxer != nullptr, AV_ERR_INVALID_VAL, "input muxer is nullptr!");
180 CHECK_AND_RETURN_RET_LOG(muxer->magic_ == AVMagic::AVCODEC_MAGIC_AVMUXER, AV_ERR_INVALID_VAL, "magic error!");
181 CHECK_AND_RETURN_RET_LOG(trackIndex != nullptr, AV_ERR_INVALID_VAL, "input track index is nullptr!");
182 CHECK_AND_RETURN_RET_LOG(trackFormat != nullptr, AV_ERR_INVALID_VAL, "input track format is nullptr!");
183 CHECK_AND_RETURN_RET_LOG(trackFormat->magic_ == MFMagic::MFMAGIC_FORMAT, AV_ERR_INVALID_VAL,
184 "track format magic error!");
185
186 struct AVMuxerObject *object = reinterpret_cast<AVMuxerObject *>(muxer);
187 CHECK_AND_RETURN_RET_LOG(object->muxer_ != nullptr, AV_ERR_INVALID_VAL, "muxer_ is nullptr!");
188
189 int32_t ret = object->muxer_->AddTrack(*trackIndex, trackFormat->format_.GetMeta());
190 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
191 "muxer_ AddTrack failed!");
192
193 return AV_ERR_OK;
194 }
195
OH_AVMuxer_Start(OH_AVMuxer * muxer)196 OH_AVErrCode OH_AVMuxer_Start(OH_AVMuxer *muxer)
197 {
198 CHECK_AND_RETURN_RET_LOG(muxer != nullptr, AV_ERR_INVALID_VAL, "input muxer is nullptr!");
199 CHECK_AND_RETURN_RET_LOG(muxer->magic_ == AVMagic::AVCODEC_MAGIC_AVMUXER, AV_ERR_INVALID_VAL, "magic error!");
200
201 struct AVMuxerObject *object = reinterpret_cast<AVMuxerObject *>(muxer);
202 CHECK_AND_RETURN_RET_LOG(object->muxer_ != nullptr, AV_ERR_INVALID_VAL, "muxer_ is nullptr!");
203
204 int32_t ret = object->muxer_->Start();
205 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
206 "muxer_ Start failed!");
207
208 return AV_ERR_OK;
209 }
210
OH_AVMuxer_WriteSample(OH_AVMuxer * muxer,uint32_t trackIndex,OH_AVMemory * sample,OH_AVCodecBufferAttr info)211 OH_AVErrCode OH_AVMuxer_WriteSample(OH_AVMuxer *muxer, uint32_t trackIndex,
212 OH_AVMemory *sample, OH_AVCodecBufferAttr info)
213 {
214 CHECK_AND_RETURN_RET_LOG(muxer != nullptr, AV_ERR_INVALID_VAL, "input muxer is nullptr!");
215 CHECK_AND_RETURN_RET_LOG(muxer->magic_ == AVMagic::AVCODEC_MAGIC_AVMUXER, AV_ERR_INVALID_VAL, "magic error!");
216 CHECK_AND_RETURN_RET_LOG(sample != nullptr, AV_ERR_INVALID_VAL, "input sample is nullptr!");
217 CHECK_AND_RETURN_RET_LOG(sample->magic_ == MFMagic::MFMAGIC_SHARED_MEMORY, AV_ERR_INVALID_VAL,
218 "sample magic error!");
219 CHECK_AND_RETURN_RET_LOG(sample->memory_ != nullptr && info.offset >= 0 && info.size >= 0 &&
220 sample->memory_->GetSize() >= (info.offset + info.size), AV_ERR_INVALID_VAL, "invalid memory");
221
222 struct AVMuxerObject *object = reinterpret_cast<AVMuxerObject *>(muxer);
223 CHECK_AND_RETURN_RET_LOG(object->muxer_ != nullptr, AV_ERR_INVALID_VAL, "muxer_ is nullptr!");
224
225 std::shared_ptr<AVBuffer> buffer = AVBuffer::CreateAVBuffer(sample->memory_->GetBase() + info.offset,
226 sample->memory_->GetSize(), info.size);
227 CHECK_AND_RETURN_RET_LOG(buffer != nullptr, AV_ERR_NO_MEMORY, "create buffer failed");
228 buffer->pts_ = info.pts;
229 buffer->flag_ = info.flags;
230
231 int32_t ret = object->muxer_->WriteSample(trackIndex, buffer);
232 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
233 "muxer_ WriteSample failed!");
234
235 return AV_ERR_OK;
236 }
237
OH_AVMuxer_WriteSampleBuffer(OH_AVMuxer * muxer,uint32_t trackIndex,const OH_AVBuffer * sample)238 OH_AVErrCode OH_AVMuxer_WriteSampleBuffer(OH_AVMuxer *muxer, uint32_t trackIndex,
239 const OH_AVBuffer *sample)
240 {
241 CHECK_AND_RETURN_RET_LOG(muxer != nullptr, AV_ERR_INVALID_VAL, "input muxer is nullptr!");
242 CHECK_AND_RETURN_RET_LOG(muxer->magic_ == AVMagic::AVCODEC_MAGIC_AVMUXER, AV_ERR_INVALID_VAL, "magic error!");
243 CHECK_AND_RETURN_RET_LOG(sample != nullptr, AV_ERR_INVALID_VAL, "input sample is nullptr!");
244 CHECK_AND_RETURN_RET_LOG(sample->magic_ == MFMagic::MFMAGIC_AVBUFFER, AV_ERR_INVALID_VAL,
245 "sample magic error!");
246
247 struct AVMuxerObject *object = reinterpret_cast<AVMuxerObject *>(muxer);
248 CHECK_AND_RETURN_RET_LOG(object->muxer_ != nullptr, AV_ERR_INVALID_VAL, "muxer_ is nullptr!");
249
250 int32_t ret = object->muxer_->WriteSample(trackIndex, sample->buffer_);
251 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
252 "muxer_ WriteSampleBuffer failed!");
253
254 return AV_ERR_OK;
255 }
256
OH_AVMuxer_Stop(OH_AVMuxer * muxer)257 OH_AVErrCode OH_AVMuxer_Stop(OH_AVMuxer *muxer)
258 {
259 CHECK_AND_RETURN_RET_LOG(muxer != nullptr, AV_ERR_INVALID_VAL, "input muxer is nullptr!");
260 CHECK_AND_RETURN_RET_LOG(muxer->magic_ == AVMagic::AVCODEC_MAGIC_AVMUXER, AV_ERR_INVALID_VAL, "magic error!");
261
262 struct AVMuxerObject *object = reinterpret_cast<AVMuxerObject *>(muxer);
263 CHECK_AND_RETURN_RET_LOG(object->muxer_ != nullptr, AV_ERR_INVALID_VAL, "muxer_ is nullptr!");
264
265 int32_t ret = object->muxer_->Stop();
266 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
267 "muxer_ Stop failed!");
268
269 return AV_ERR_OK;
270 }
271
OH_AVMuxer_Destroy(OH_AVMuxer * muxer)272 OH_AVErrCode OH_AVMuxer_Destroy(OH_AVMuxer *muxer)
273 {
274 CHECK_AND_RETURN_RET_LOG(muxer != nullptr, AV_ERR_INVALID_VAL, "input muxer is nullptr!");
275 CHECK_AND_RETURN_RET_LOG(muxer->magic_ == AVMagic::AVCODEC_MAGIC_AVMUXER, AV_ERR_INVALID_VAL, "magic error!");
276
277 delete muxer;
278
279 return AV_ERR_OK;
280 }