1 /*
2 * Copyright (c) 2023-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 "mpeg_manager.h"
17
18 #include <fcntl.h>
19
20 #include "dp_log.h"
21
22 namespace OHOS {
23 namespace CameraStandard {
24 namespace DeferredProcessing {
25 constexpr int64_t DEFAULT_TIME_TAMP = 0;
26
27 class MpegManager::VideoCodecCallback : public MediaCodecCallback {
28 public:
VideoCodecCallback(const std::weak_ptr<MpegManager> & mpegManager)29 explicit VideoCodecCallback(const std::weak_ptr<MpegManager>& mpegManager) : mpegManager_(mpegManager)
30 {
31 DP_DEBUG_LOG("entered.");
32 }
33
~VideoCodecCallback()34 ~VideoCodecCallback()
35 {
36 DP_DEBUG_LOG("entered.");
37 }
38
39 void OnError(AVCodecErrorType errorType, int32_t errorCode) override;
40 void OnOutputFormatChanged(const Format &format) override;
41 void OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer) override;
42 void OnOutputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer) override;
43
44 private:
45 std::weak_ptr<MpegManager> mpegManager_;
46 };
47
OnError(AVCodecErrorType errorType,int32_t errorCode)48 void MpegManager::VideoCodecCallback::OnError(AVCodecErrorType errorType, int32_t errorCode)
49 {
50 DP_ERR_LOG("entered, errorType: %{public}d, errorCode: %{public}d", errorType, errorCode);
51 }
52
OnOutputFormatChanged(const Format & format)53 void MpegManager::VideoCodecCallback::OnOutputFormatChanged(const Format &format)
54 {
55 DP_DEBUG_LOG("entered.");
56 }
57
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)58 void MpegManager::VideoCodecCallback::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
59 {
60 DP_DEBUG_LOG("entered.");
61 (void)index;
62 }
63
OnOutputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)64 void MpegManager::VideoCodecCallback::OnOutputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
65 {
66 DP_CHECK_ERROR_RETURN_LOG(buffer == nullptr, "OutputBuffer is null");
67 auto manager = mpegManager_.lock();
68 if (manager != nullptr) {
69 manager->OnBufferAvailable(index, buffer);
70 }
71 }
72
MpegManager()73 MpegManager::MpegManager()
74 {
75 DP_DEBUG_LOG("entered.");
76 mediaManager_ = std::make_unique<MediaManager>();
77 }
78
~MpegManager()79 MpegManager::~MpegManager()
80 {
81 DP_DEBUG_LOG("entered.");
82 mediaManager_ = nullptr;
83 codecSurface_ = nullptr;
84 processThread_ = nullptr;
85 mediaInfo_ = nullptr;
86 outputFd_ = nullptr;
87 tempFd_ = nullptr;
88 remove(tempPath_.c_str());
89 if (result_ == MediaResult::PAUSE) {
90 int ret = rename(outPath_.c_str(), tempPath_.c_str());
91 if (ret != 0) {
92 DP_ERR_LOG("rename %{public}s to %{public}s failde, ret: %{public}d",
93 outPath_.c_str(), tempPath_.c_str(), ret);
94 } else {
95 DP_INFO_LOG("rename %{public}s to %{public}s success.", outPath_.c_str(), tempPath_.c_str());
96 }
97 }
98 }
99
Init(const std::string & requestId,const sptr<IPCFileDescriptor> & inputFd)100 MediaManagerError MpegManager::Init(const std::string& requestId, const sptr<IPCFileDescriptor>& inputFd)
101 {
102 DP_DEBUG_LOG("entered.");
103 outputFd_ = GetFileFd(requestId, O_CREAT | O_RDWR, OUT_TAG);
104 DP_CHECK_ERROR_RETURN_RET_LOG(outputFd_ == nullptr, ERROR_FAIL, "output video create failde.");
105
106 tempFd_ = GetFileFd(requestId, O_RDONLY, TEMP_TAG);
107 DP_CHECK_ERROR_RETURN_RET_LOG(tempFd_ == nullptr, ERROR_FAIL, "temp video create failde.");
108
109 auto ret = mediaManager_->Create(inputFd->GetFd(), outputFd_->GetFd(), tempFd_->GetFd());
110 DP_CHECK_ERROR_RETURN_RET_LOG(ret != OK, ERROR_FAIL, "media manager create failde.");
111
112 mediaManager_->GetMediaInfo(mediaInfo_);
113 DP_CHECK_ERROR_RETURN_RET_LOG(InitVideoCodec() != OK, ERROR_FAIL, "init video codec failde.");
114
115 isRunning_.store(true);
116 return OK;
117 }
118
UnInit(const MediaResult result)119 MediaManagerError MpegManager::UnInit(const MediaResult result)
120 {
121 DP_DEBUG_LOG("entered.");
122 DP_CHECK_RETURN_RET(!isRunning_.load(), OK);
123 result_ = result;
124 if (result == MediaResult::PAUSE) {
125 if (mediaManager_->Pause() == PAUSE_ABNORMAL) {
126 remove(outPath_.c_str());
127 }
128 } else {
129 mediaManager_->Stop();
130 }
131 UnInitVideoCodec();
132 isRunning_.store(false);
133 return OK;
134 }
135
GetSurface()136 sptr<Surface> MpegManager::GetSurface()
137 {
138 return codecSurface_;
139 }
140
GetProcessTimeStamp()141 uint64_t MpegManager::GetProcessTimeStamp()
142 {
143 DP_CHECK_RETURN_RET(mediaInfo_->recoverTime < DEFAULT_TIME_TAMP, DEFAULT_TIME_TAMP);
144 return static_cast<uint64_t>(mediaInfo_->recoverTime);
145 }
146
NotifyEnd()147 MediaManagerError MpegManager::NotifyEnd()
148 {
149 auto ret = encoder_->NotifyEos();
150 DP_CHECK_ERROR_RETURN_RET_LOG(ret != static_cast<int32_t>(OK), ERROR_FAIL, "video codec notify end failde.");
151 return OK;
152 }
153
ReleaseBuffer(uint32_t index)154 MediaManagerError MpegManager::ReleaseBuffer(uint32_t index)
155 {
156 auto ret = encoder_->ReleaseOutputBuffer(index);
157 DP_CHECK_ERROR_RETURN_RET_LOG(ret != static_cast<int32_t>(OK), ERROR_FAIL, "video codec release buffer failde.");
158 return OK;
159 }
160
GetResultFd()161 sptr<IPCFileDescriptor> MpegManager::GetResultFd()
162 {
163 return outputFd_;
164 }
165
InitVideoCodec()166 MediaManagerError MpegManager::InitVideoCodec()
167 {
168 DP_INFO_LOG("entered.");
169 auto codecInfo = mediaInfo_->codecInfo;
170 encoder_ = VideoEncoderFactory::CreateByMime(codecInfo.mimeType);
171 DP_CHECK_ERROR_RETURN_RET_LOG(encoder_ == nullptr, ERROR_FAIL, "video codec create failde.");
172
173 auto callback = std::make_shared<VideoCodecCallback>(weak_from_this());
174 auto ret = encoder_->SetCallback(callback);
175 DP_CHECK_ERROR_RETURN_RET_LOG(ret != static_cast<int32_t>(OK), ERROR_FAIL, "video codec set callback failde.");
176
177 Format videoFormat;
178 if (codecInfo.mimeType == MINE_VIDEO_HEVC) {
179 videoFormat.PutIntValue(Tag::VIDEO_COLOR_RANGE, static_cast<int32_t>(codecInfo.colorRange));
180 videoFormat.PutIntValue(Tag::VIDEO_COLOR_PRIMARIES, static_cast<int32_t>(codecInfo.colorPrimary));
181 videoFormat.PutIntValue(Tag::VIDEO_COLOR_TRC, static_cast<int32_t>(codecInfo.colorTransferCharacter));
182 videoFormat.PutIntValue(Tag::MEDIA_LEVEL, codecInfo.level);
183 videoFormat.PutIntValue(Tag::MEDIA_PROFILE, codecInfo.profile);
184 }
185 videoFormat.PutIntValue(Tag::VIDEO_ENCODE_BITRATE_MODE, codecInfo.bitMode);
186 videoFormat.PutIntValue(Tag::VIDEO_PIXEL_FORMAT, static_cast<int32_t>(PixelFormat::PIX_FMT_NV12));
187 videoFormat.PutStringValue(Tag::MIME_TYPE, codecInfo.mimeType);
188 videoFormat.PutLongValue(Tag::MEDIA_BITRATE, codecInfo.bitRate);
189 videoFormat.PutDoubleValue(Tag::VIDEO_FRAME_RATE, codecInfo.fps);
190 videoFormat.PutIntValue(Tag::VIDEO_WIDTH, codecInfo.width);
191 videoFormat.PutIntValue(Tag::VIDEO_HEIGHT, codecInfo.height);
192 videoFormat.PutIntValue(Tag::VIDEO_ROTATION, codecInfo.rotation);
193 videoFormat.PutLongValue(Tag::MEDIA_DURATION, codecInfo.duration);
194
195 ret = encoder_->Configure(videoFormat);
196 DP_CHECK_ERROR_RETURN_RET_LOG(ret != static_cast<int32_t>(OK), ERROR_FAIL,
197 "video codec configure failde, ret: %{public}d.", ret);
198
199 codecSurface_ = encoder_->CreateInputSurface();
200 ret = encoder_->Prepare();
201 DP_CHECK_ERROR_RETURN_RET_LOG(ret != static_cast<int32_t>(OK), ERROR_FAIL, "video codec prepare failde.");
202
203 ret = encoder_->Start();
204 DP_CHECK_ERROR_RETURN_RET_LOG(ret != static_cast<int32_t>(OK), ERROR_FAIL, "video codec start failde.");
205
206 return OK;
207 }
208
UnInitVideoCodec()209 void MpegManager::UnInitVideoCodec()
210 {
211 DP_DEBUG_LOG("entered.");
212 if (isRunning_) {
213 encoder_->Stop();
214 }
215 DP_CHECK_RETURN(encoder_ == nullptr);
216 encoder_->Release();
217 encoder_ = nullptr;
218 }
219
OnBufferAvailable(uint32_t index,const std::shared_ptr<AVBuffer> & buffer)220 void MpegManager::OnBufferAvailable(uint32_t index, const std::shared_ptr<AVBuffer>& buffer)
221 {
222 auto ret = mediaManager_->WriteSample(TrackType::AV_KEY_VIDEO_TYPE, buffer);
223 DP_CHECK_ERROR_RETURN_LOG(ret != OK, "video codec write failde.");
224 ret = ReleaseBuffer(index);
225 DP_CHECK_ERROR_RETURN_LOG(ret != OK, "video codec release buffer failde.");
226 }
227
GetFileFd(const std::string & requestId,int flags,const std::string & tag)228 sptr<IPCFileDescriptor> MpegManager::GetFileFd(const std::string& requestId, int flags, const std::string& tag)
229 {
230 std::string path = PATH + requestId + tag;
231 if (tag == TEMP_TAG) {
232 tempPath_ = path;
233 } else {
234 outPath_ = path;
235 }
236 DP_DEBUG_LOG("GetFileFd path: %{public}s", path.c_str());
237 int fd = open(path.c_str(), flags, S_IRUSR | S_IWUSR);
238 return sptr<IPCFileDescriptor>::MakeSptr(fd);
239 }
240 } // namespace DeferredProcessing
241 } // namespace CameraStandard
242 } // namespace OHOS