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