1 /*
2 * Copyright (C) 2024 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 "media_log.h"
17 #include <native_avcapability.h>
18 #include <native_avcodec_videoencoder.h>
19 #include <native_averrors.h>
20 #include <native_avformat.h>
21 #include "codec/video/encoder/video_muxer.h"
22
23 namespace OHOS {
24 namespace Media {
25 namespace {
26 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_VIDEOEDITOR, "VideoEditorMuxer"};
27 }
28
VideoMuxer(uint64_t id)29 VideoMuxer::VideoMuxer(uint64_t id)
30 {
31 logTag_ = "video-muxer-" + std::to_string(id);
32 }
33
~VideoMuxer()34 VideoMuxer::~VideoMuxer()
35 {
36 MEDIA_LOGD("[%{public}s] video muxer destruct begin.", logTag_.c_str());
37 if (muxer_) {
38 OH_AVMuxer_Destroy(muxer_);
39 muxer_ = nullptr;
40 }
41 MEDIA_LOGD("[%{public}s] video muxer destruct finish.", logTag_.c_str());
42 }
43
Start()44 VEFError VideoMuxer::Start()
45 {
46 MEDIA_LOGI("[%{public}s] start muxer.", logTag_.c_str());
47 OH_AVErrCode error = OH_AVMuxer_Start(muxer_);
48 if (error != AV_ERR_OK) {
49 MEDIA_LOGE("[%{public}s] start muxer failed, OH_AVMuxer_Start return: %{public}d.", logTag_.c_str(), error);
50 return VEFError::ERR_INTERNAL_ERROR;
51 }
52 MEDIA_LOGI("[%{public}s] start muxer success.", logTag_.c_str());
53 return VEFError::ERR_OK;
54 }
55
Stop()56 VEFError VideoMuxer::Stop()
57 {
58 MEDIA_LOGI("[%{public}s] stop muxer.", logTag_.c_str());
59 OH_AVErrCode error = OH_AVMuxer_Stop(muxer_);
60 if (error != AV_ERR_OK) {
61 MEDIA_LOGE("[%{public}s] stop muxer failed, OH_AVMuxer_Stop return: %{public}d.", logTag_.c_str(), error);
62 return VEFError::ERR_INTERNAL_ERROR;
63 }
64 MEDIA_LOGI("[%{public}s] stop muxer success.", logTag_.c_str());
65 return VEFError::ERR_OK;
66 }
67
Init(const VideoMuxerParam & muxerParam)68 VEFError VideoMuxer::Init(const VideoMuxerParam& muxerParam)
69 {
70 MEDIA_LOGD("[%{public}s] init video muxer, format = %{public}d, rotation = %{public}d.", logTag_.c_str(),
71 muxerParam.avOutputFormat, muxerParam.rotation);
72 muxer_ = OH_AVMuxer_Create(muxerParam.targetFileFd, muxerParam.avOutputFormat);
73 if (muxer_ == nullptr) {
74 MEDIA_LOGE("[%{public}s] create muxer by OH_AVMuxer_Create failed, fd = %{public}d, format = %{public}d.",
75 logTag_.c_str(), muxerParam.targetFileFd, muxerParam.avOutputFormat);
76 return VEFError::ERR_INTERNAL_ERROR;
77 }
78
79 OH_AVErrCode error = OH_AVMuxer_SetRotation(muxer_, muxerParam.rotation);
80 if (error != AV_ERR_OK) {
81 MEDIA_LOGE("[%{public}s] set rotation to %{public}d failed, err = %{public}d.",
82 logTag_.c_str(), muxerParam.rotation, error);
83 return VEFError::ERR_INTERNAL_ERROR;
84 }
85
86 MEDIA_LOGI("[%{public}s] init video muxer success.", logTag_.c_str());
87 return VEFError::ERR_OK;
88 }
89
AddVideoTrack(OH_AVFormat * format)90 VEFError VideoMuxer::AddVideoTrack(OH_AVFormat* format)
91 {
92 MEDIA_LOGI("[%{public}s] add video track.", logTag_.c_str());
93 if (format == nullptr) {
94 MEDIA_LOGE("[%{public}s] add video track failed, parameter format is nullptr.", logTag_.c_str());
95 return VEFError::ERR_INTERNAL_ERROR;
96 }
97 OH_AVErrCode error = OH_AVMuxer_AddTrack(muxer_, &videoTrackId_, format);
98 if (error != AV_ERR_OK) {
99 MEDIA_LOGE("[%{public}s] add video track failed, OH_AVMuxer_AddTrack return: %{public}d.", logTag_.c_str(),
100 error);
101 return VEFError::ERR_INTERNAL_ERROR;
102 }
103 return VEFError::ERR_OK;
104 }
105
AddAudioTrack(OH_AVFormat * format)106 VEFError VideoMuxer::AddAudioTrack(OH_AVFormat* format)
107 {
108 MEDIA_LOGI("[%{public}s] add audio track.", logTag_.c_str());
109 if (format == nullptr) {
110 MEDIA_LOGE("[%{public}s] add audio track failed, parameter format is nullptr.", logTag_.c_str());
111 return VEFError::ERR_INTERNAL_ERROR;
112 }
113 OH_AVErrCode error = OH_AVMuxer_AddTrack(muxer_, &audioTrackId_, format);
114 if (error != AV_ERR_OK) {
115 MEDIA_LOGE("[%{public}s] add audio track failed, OH_AVMuxer_AddTrack return: %{public}d.", logTag_.c_str(),
116 error);
117 return VEFError::ERR_INTERNAL_ERROR;
118 }
119 return VEFError::ERR_OK;
120 }
121
WriteVideoData(OH_AVMemory * data,OH_AVCodecBufferAttr * attr)122 VEFError VideoMuxer::WriteVideoData(OH_AVMemory* data, OH_AVCodecBufferAttr* attr)
123 {
124 MEDIA_LOGD("[%{public}s] OH_AVMuxer_WriteSample video flags=%{public}u, pts=%{public}" PRIu64 ","
125 "size:%{public}d.", logTag_.c_str(), attr->flags, attr->pts, attr->size);
126 std::lock_guard<ffrt::mutex> lk(writeFrameMutex_);
127 auto ret = OH_AVMuxer_WriteSample(muxer_, videoTrackId_, data, *attr);
128 if (attr->flags == AVCODEC_BUFFER_FLAGS_EOS) {
129 MEDIA_LOGI("[%{public}s] write video finish(EOS).", logTag_.c_str());
130 return VEFError::ERR_OK;
131 }
132 if (ret != AV_ERR_OK) {
133 MEDIA_LOGE("[%{public}s] OH_AVMuxer_WriteSample video failed, pts=%{public}" PRIu64 ".",
134 logTag_.c_str(), attr->pts);
135 return VEFError::ERR_INTERNAL_ERROR;
136 }
137 return VEFError::ERR_OK;
138 }
139
WriteAudioData(OH_AVMemory * data,OH_AVCodecBufferAttr * attr)140 VEFError VideoMuxer::WriteAudioData(OH_AVMemory* data, OH_AVCodecBufferAttr* attr)
141 {
142 if (data == nullptr || attr == nullptr) {
143 MEDIA_LOGE("[%{public}s] invalid parameter, data or attr is nullptr.", logTag_.c_str());
144 return VEFError::ERR_INTERNAL_ERROR;
145 }
146 MEDIA_LOGD("[%{public}s] OH_AVMuxer_WriteSample audio flags=%{public}u, pts=%{public}" PRIu64
147 ", size:%{public}d.", logTag_.c_str(), attr->flags, attr->pts, attr->size);
148 std::lock_guard<ffrt::mutex> lk(writeFrameMutex_);
149 auto ret = OH_AVMuxer_WriteSample(muxer_, audioTrackId_, data, *attr);
150 if (ret != AV_ERR_OK) {
151 MEDIA_LOGE("[%{public}s] OH_AVMuxer_WriteSample audio failed, pts=%{public}" PRIu64 ".",
152 logTag_.c_str(), attr->pts);
153 return VEFError::ERR_INTERNAL_ERROR;
154 }
155 return VEFError::ERR_OK;
156 }
157 } // namespace Media
158 } // namespace OHOS
159