1 /*
2 * Copyright (c) 2024-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 "avcodec_task_manager.h"
17
18 #include <algorithm>
19 #include <chrono>
20 #include <cinttypes>
21 #include <cstdint>
22 #include <fcntl.h>
23 #include <memory>
24 #include <mutex>
25 #include <unistd.h>
26 #include <utility>
27 #include "datetime_ex.h"
28 #include "camera_util.h"
29 #include "datetime_ex.h"
30 #include "audio_capturer_session.h"
31 #include "audio_record.h"
32 #include "audio_video_muxer.h"
33 #include "camera_log.h"
34 #include "datetime_ex.h"
35 #include "external_window.h"
36 #include "frame_record.h"
37 #include "native_avbuffer.h"
38 #include "native_avbuffer_info.h"
39 #include "native_buffer_inner.h"
40 #include "sample_info.h"
41 #include "native_mfmagic.h"
42
43 namespace {
44 using namespace std::string_literals;
45 using namespace std::chrono_literals;
46 } // namespace
47 namespace OHOS {
48 namespace CameraStandard {
49
~AvcodecTaskManager()50 AvcodecTaskManager::~AvcodecTaskManager()
51 {
52 CAMERA_SYNC_TRACE;
53 Release();
54 }
55
AvcodecTaskManager(sptr<AudioCapturerSession> audioCaptureSession,VideoCodecType type)56 AvcodecTaskManager::AvcodecTaskManager(sptr<AudioCapturerSession> audioCaptureSession,
57 VideoCodecType type) : videoCodecType_(type)
58 {
59 CAMERA_SYNC_TRACE;
60 #ifdef MOVING_PHOTO_ADD_AUDIO
61 audioCapturerSession_ = audioCaptureSession;
62 audioEncoder_ = make_unique<AudioEncoder>();
63 #endif
64 // Create Task Manager
65 videoEncoder_ = make_unique<VideoEncoder>();
66 }
67
GetTaskManager()68 shared_ptr<TaskManager>& AvcodecTaskManager::GetTaskManager()
69 {
70 lock_guard<mutex> lock(taskManagerMutex_);
71 if (taskManager_ == nullptr && isActive_.load()) {
72 taskManager_ = make_unique<TaskManager>("AvcodecTaskManager", DEFAULT_THREAD_NUMBER, false);
73 }
74 return taskManager_;
75 }
76
GetEncoderManager()77 shared_ptr<TaskManager>& AvcodecTaskManager::GetEncoderManager()
78 {
79 lock_guard<mutex> lock(encoderManagerMutex_);
80 if (videoEncoderManager_ == nullptr && isActive_.load()) {
81 videoEncoderManager_ = make_unique<TaskManager>("VideoTaskManager", DEFAULT_ENCODER_THREAD_NUMBER, true);
82 }
83 return videoEncoderManager_;
84 }
85
EncodeVideoBuffer(sptr<FrameRecord> frameRecord,CacheCbFunc cacheCallback)86 void AvcodecTaskManager::EncodeVideoBuffer(sptr<FrameRecord> frameRecord, CacheCbFunc cacheCallback)
87 {
88 auto thisPtr = sptr<AvcodecTaskManager>(this);
89 auto encodeManager = GetEncoderManager();
90 if (!encodeManager) {
91 return;
92 }
93 encodeManager->SubmitTask([thisPtr, frameRecord, cacheCallback]() {
94 CAMERA_SYNC_TRACE;
95 bool isEncodeSuccess = false;
96 if (!thisPtr->videoEncoder_ && !frameRecord) {
97 return;
98 }
99 isEncodeSuccess = thisPtr->videoEncoder_->EncodeSurfaceBuffer(frameRecord);
100 if (isEncodeSuccess) {
101 thisPtr->videoEncoder_->ReleaseSurfaceBuffer(frameRecord);
102 }
103 frameRecord->SetEncodedResult(isEncodeSuccess);
104 if (isEncodeSuccess) {
105 MEDIA_INFO_LOG("encode image success %{public}s, refCount: %{public}d", frameRecord->GetFrameId().c_str(),
106 frameRecord->GetSptrRefCount());
107 } else {
108 MEDIA_ERR_LOG("encode image fail %{public}s", frameRecord->GetFrameId().c_str());
109 }
110 if (cacheCallback) {
111 cacheCallback(frameRecord, isEncodeSuccess);
112 }
113 });
114 }
115
SubmitTask(function<void ()> task)116 void AvcodecTaskManager::SubmitTask(function<void()> task)
117 {
118 auto taskManager = GetTaskManager();
119 if (taskManager) {
120 taskManager->SubmitTask(task);
121 }
122 }
123
SetVideoFd(int64_t timestamp,PhotoAssetIntf * photoAssetProxy)124 void AvcodecTaskManager::SetVideoFd(int64_t timestamp, PhotoAssetIntf* photoAssetProxy)
125 {
126 lock_guard<mutex> lock(videoFdMutex_);
127 MEDIA_INFO_LOG("Set timestamp: %{public}" PRId64, timestamp);
128 videoFdQueue_.push(std::make_pair(timestamp, photoAssetProxy));
129 MEDIA_DEBUG_LOG("video queue size:%{public}zu", videoFdQueue_.size());
130 cvEmpty_.notify_all();
131 }
132
CreateAVMuxer(vector<sptr<FrameRecord>> frameRecords,int32_t captureRotation,vector<sptr<FrameRecord>> & choosedBuffer,int32_t captureId)133 sptr<AudioVideoMuxer> AvcodecTaskManager::CreateAVMuxer(vector<sptr<FrameRecord>> frameRecords, int32_t captureRotation,
134 vector<sptr<FrameRecord>> &choosedBuffer, int32_t captureId)
135 {
136 CAMERA_SYNC_TRACE;
137 unique_lock<mutex> lock(videoFdMutex_);
138 if (videoFdQueue_.empty()) {
139 bool waitResult = false;
140 auto thisPtr = sptr<AvcodecTaskManager>(this);
141 waitResult = cvEmpty_.wait_for(lock, std::chrono::milliseconds(GET_FD_EXPIREATION_TIME),
142 [thisPtr] { return !thisPtr->videoFdQueue_.empty(); });
143 CHECK_ERROR_RETURN_RET(!waitResult || videoFdQueue_.empty(), nullptr);
144 }
145 sptr<AudioVideoMuxer> muxer = new AudioVideoMuxer();
146 OH_AVOutputFormat format = AV_OUTPUT_FORMAT_MPEG_4;
147 int64_t timestamp = videoFdQueue_.front().first;
148 auto photoAssetProxy = videoFdQueue_.front().second;
149 videoFdQueue_.pop();
150 ChooseVideoBuffer(frameRecords, choosedBuffer, timestamp, captureId);
151 muxer->Create(format, photoAssetProxy);
152 muxer->SetRotation(captureRotation);
153 if (!choosedBuffer.empty()) {
154 muxer->SetCoverTime(NanosecToMillisec(timestamp - choosedBuffer.front()->GetTimeStamp()));
155 }
156 auto formatVideo = make_shared<Format>();
157 MEDIA_INFO_LOG("CreateAVMuxer videoCodecType_ = %{public}d", videoCodecType_);
158 formatVideo->PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, videoCodecType_
159 == VIDEO_ENCODE_TYPE_HEVC ? OH_AVCODEC_MIMETYPE_VIDEO_HEVC : OH_AVCODEC_MIMETYPE_VIDEO_AVC);
160 formatVideo->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, frameRecords[0]->GetFrameSize()->width);
161 formatVideo->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, frameRecords[0]->GetFrameSize()->height);
162 formatVideo->PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, VIDEO_FRAME_RATE);
163 int videoTrackId = -1;
164 muxer->AddTrack(videoTrackId, formatVideo, VIDEO_TRACK);
165 int audioTrackId = -1;
166 #ifdef MOVING_PHOTO_ADD_AUDIO
167 auto formatAudio = make_shared<Format>();
168 formatAudio->PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, OH_AVCODEC_MIMETYPE_AUDIO_AAC);
169 formatAudio->PutIntValue(MediaDescriptionKey::MD_KEY_SAMPLE_RATE, DEFAULT_SAMPLERATE);
170 formatAudio->PutIntValue(MediaDescriptionKey::MD_KEY_CHANNEL_COUNT, DEFAULT_CHANNEL_COUNT);
171 muxer->AddTrack(audioTrackId, formatAudio, AUDIO_TRACK);
172 #endif
173 int metaTrackId = -1;
174 auto formatMeta = make_shared<Format>();
175 formatMeta->PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, TIMED_METADATA_TRACK_MIMETYPE);
176 formatMeta->PutStringValue(MediaDescriptionKey::MD_KEY_TIMED_METADATA_KEY, TIMED_METADATA_KEY);
177 formatMeta->PutIntValue(MediaDescriptionKey::MD_KEY_TIMED_METADATA_SRC_TRACK_ID, videoTrackId);
178 muxer->AddTrack(metaTrackId, formatMeta, META_TRACK);
179
180 MEDIA_INFO_LOG("CreateMuxer vId:%{public}d,aid:%{public}d,mid:%{public}d", videoTrackId, audioTrackId, metaTrackId);
181 muxer->SetTimedMetadata();
182 muxer->Start();
183 return muxer;
184 }
185
FinishMuxer(sptr<AudioVideoMuxer> muxer)186 void AvcodecTaskManager::FinishMuxer(sptr<AudioVideoMuxer> muxer)
187 {
188 CAMERA_SYNC_TRACE;
189 MEDIA_INFO_LOG("doMxuer video is finished");
190 if (muxer) {
191 muxer->Stop();
192 muxer->Release();
193 PhotoAssetIntf* proxy = muxer->GetPhotoAssetProxy();
194 MEDIA_INFO_LOG("PhotoAssetProxy notify enter");
195 if (proxy) {
196 proxy->NotifyVideoSaveFinished();
197 delete proxy;
198 }
199 }
200 }
201
DoMuxerVideo(vector<sptr<FrameRecord>> frameRecords,uint64_t taskName,int32_t captureRotation,int32_t captureId)202 void AvcodecTaskManager::DoMuxerVideo(vector<sptr<FrameRecord>> frameRecords, uint64_t taskName,
203 int32_t captureRotation, int32_t captureId) __attribute__((no_sanitize("cfi")))
204 {
205 CHECK_ERROR_RETURN_LOG(frameRecords.empty(), "DoMuxerVideo error of empty encoded frame");
206 auto thisPtr = sptr<AvcodecTaskManager>(this);
207 auto taskManager = GetTaskManager();
208 if (!taskManager) {
209 MEDIA_ERR_LOG("GetTaskManager is null");
210 return;
211 }
212 GetTaskManager()->SubmitTask([thisPtr, frameRecords, captureRotation, captureId]() {
213 MEDIA_INFO_LOG("CreateAVMuxer with %{public}s", frameRecords.front()->GetFrameId().c_str());
214 vector<sptr<FrameRecord>> choosedBuffer;
215 sptr<AudioVideoMuxer> muxer = thisPtr->CreateAVMuxer(frameRecords, captureRotation, choosedBuffer, captureId);
216 CHECK_ERROR_RETURN_LOG(muxer == nullptr, "CreateAVMuxer failed");
217 CHECK_ERROR_RETURN_LOG(choosedBuffer.empty(), "choosed empty buffer!");
218 int64_t videoStartTime = choosedBuffer.front()->GetTimeStamp();
219 for (size_t index = 0; index < choosedBuffer.size(); index++) {
220 OH_AVCodecBufferAttr attr = { 0, 0, 0, AVCODEC_BUFFER_FLAGS_NONE };
221 OH_AVBuffer* buffer = choosedBuffer[index]->encodedBuffer;
222 CHECK_AND_CONTINUE_LOG(buffer != nullptr, "video encodedBuffer is null");
223 OH_AVBuffer_GetBufferAttr(buffer, &attr);
224 attr.pts = NanosecToMicrosec(choosedBuffer[index]->GetTimeStamp() - videoStartTime);
225 OH_AVBuffer_SetBufferAttr(buffer, &attr);
226 muxer->WriteSampleBuffer(buffer->buffer_, VIDEO_TRACK);
227 sptr<SurfaceBuffer> metaSurfaceBuffer = frameRecords[index]->GetMetaBuffer();
228 if (metaSurfaceBuffer) {
229 shared_ptr<AVBuffer> metaAvBuffer = AVBuffer::CreateAVBuffer(metaSurfaceBuffer);
230 metaAvBuffer->pts_ = attr.pts;
231 MEDIA_DEBUG_LOG("metaAvBuffer pts_ %{public}llu, avBufferSize: %{public}d",
232 (long long unsigned)(metaAvBuffer->pts_), metaAvBuffer->memory_->GetSize());
233 muxer->WriteSampleBuffer(metaAvBuffer, META_TRACK);
234 } else {
235 MEDIA_ERR_LOG("metaSurfaceBuffer is nullptr");
236 }
237 frameRecords[index]->UnLockMetaBuffer();
238 }
239 #ifdef MOVING_PHOTO_ADD_AUDIO
240 // CollectAudioBuffer
241 vector<sptr<AudioRecord>> audioRecords;
242 if (thisPtr->audioCapturerSession_) {
243 int64_t startTime = NanosecToMillisec(videoStartTime);
244 int64_t endTime = NanosecToMillisec(choosedBuffer.back()->GetTimeStamp());
245 thisPtr->audioCapturerSession_->GetAudioRecords(startTime, endTime, audioRecords);
246 }
247 thisPtr->CollectAudioBuffer(audioRecords, muxer);
248 #endif
249 thisPtr->FinishMuxer(muxer);
250 });
251 }
252
ChooseVideoBuffer(vector<sptr<FrameRecord>> frameRecords,vector<sptr<FrameRecord>> & choosedBuffer,int64_t shutterTime,int32_t captureId)253 void AvcodecTaskManager::ChooseVideoBuffer(vector<sptr<FrameRecord>> frameRecords,
254 vector<sptr<FrameRecord>> &choosedBuffer, int64_t shutterTime, int32_t captureId)
255 {
256 choosedBuffer.clear();
257 std::unique_lock<mutex> startTimeLock(startTimeMutex_);
258 int64_t clearVideoStartTime = shutterTime - preBufferDuration_;
259 if (mPStartTimeMap_.count(captureId) && mPStartTimeMap_[captureId] <= shutterTime) {
260 clearVideoStartTime = mPStartTimeMap_[captureId];
261 }
262 mPStartTimeMap_.erase(captureId);
263 startTimeLock.unlock();
264 std::unique_lock<mutex> endTimeLock(endTimeMutex_);
265 int64_t clearVideoEndTime = shutterTime + postBufferDuration_;
266 if (mPEndTimeMap_.count(captureId) && mPEndTimeMap_[captureId] >= shutterTime) {
267 clearVideoEndTime = mPEndTimeMap_[captureId];
268 }
269 mPEndTimeMap_.erase(captureId);
270 endTimeLock.unlock();
271 MEDIA_INFO_LOG("ChooseVideoBuffer captureId : %{public}d, shutterTime : %{public}" PRId64 ", "
272 "clearVideoStartTime : %{public}" PRId64 ", clearVideoEndTime : %{public}" PRId64,
273 captureId, shutterTime, clearVideoStartTime, clearVideoEndTime);
274 size_t idrIndex = frameRecords.size();
275 for (size_t index = 0; index < frameRecords.size(); ++index) {
276 auto frame = frameRecords[index];
277 if (frame->IsIDRFrame() && frame->GetTimeStamp() <= clearVideoStartTime) {
278 idrIndex = index;
279 }
280 }
281 if (idrIndex == frameRecords.size()) {
282 for (size_t index = 0; index < frameRecords.size(); ++index) {
283 auto frame = frameRecords[index];
284 if (frame->IsIDRFrame()) {
285 idrIndex = index;
286 break;
287 }
288 idrIndex = 0;
289 }
290 }
291 for (size_t index = idrIndex; index < frameRecords.size(); ++index) {
292 auto frame = frameRecords[index];
293 int64_t timestamp = frame->GetTimeStamp();
294 if (timestamp <= clearVideoEndTime) {
295 choosedBuffer.push_back(frame);
296 }
297 }
298 if (choosedBuffer.empty()) {
299 choosedBuffer = frameRecords;
300 }
301 MEDIA_INFO_LOG("ChooseVideoBuffer with size %{public}zu", choosedBuffer.size());
302 }
303
CollectAudioBuffer(vector<sptr<AudioRecord>> audioRecordVec,sptr<AudioVideoMuxer> muxer)304 void AvcodecTaskManager::CollectAudioBuffer(vector<sptr<AudioRecord>> audioRecordVec, sptr<AudioVideoMuxer> muxer)
305 {
306 CAMERA_SYNC_TRACE;
307 MEDIA_INFO_LOG("CollectAudioBuffer start with size %{public}zu", audioRecordVec.size());
308 bool isEncodeSuccess = false;
309 CHECK_ERROR_RETURN_LOG(!audioEncoder_ || audioRecordVec.empty() || !muxer,
310 "CollectAudioBuffer cannot find useful data");
311 isEncodeSuccess = audioEncoder_->EncodeAudioBuffer(audioRecordVec);
312 MEDIA_DEBUG_LOG("encode audio buffer result %{public}d", isEncodeSuccess);
313 size_t maxFrameCount = std::min(audioRecordVec.size(), MAX_AUDIO_FRAME_COUNT);
314 for (size_t index = 0; index < maxFrameCount; index++) {
315 OH_AVCodecBufferAttr attr = { 0, 0, 0, AVCODEC_BUFFER_FLAGS_NONE };
316 OH_AVBuffer* buffer = audioRecordVec[index]->encodedBuffer;
317 CHECK_AND_CONTINUE_LOG(buffer != nullptr, "audio encodedBuffer is null");
318 OH_AVBuffer_GetBufferAttr(buffer, &attr);
319 attr.pts = static_cast<int64_t>(index * AUDIO_FRAME_INTERVAL);
320 if (audioRecordVec.size() > 0) {
321 if (index == audioRecordVec.size() - 1) {
322 attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
323 }
324 }
325 OH_AVBuffer_SetBufferAttr(buffer, &attr);
326 muxer->WriteSampleBuffer(buffer->buffer_, AUDIO_TRACK);
327 }
328 MEDIA_INFO_LOG("CollectAudioBuffer finished");
329 }
330
Release()331 void AvcodecTaskManager::Release()
332 {
333 CAMERA_SYNC_TRACE;
334 MEDIA_INFO_LOG("AvcodecTaskManager release start");
335 if (videoEncoder_ != nullptr) {
336 videoEncoder_->Release();
337 }
338 if (audioEncoder_ != nullptr) {
339 audioEncoder_->Release();
340 }
341 unique_lock<mutex> lock(videoFdMutex_);
342 MEDIA_INFO_LOG("videoFdQueue_ size is %{public}zu", videoFdQueue_.size());
343 while (!videoFdQueue_.empty()) {
344 int32_t fd = videoFdQueue_.front().first;
345 PhotoAssetIntf* photoAssetProxy = videoFdQueue_.front().second;
346 MEDIA_INFO_LOG("close with videoFd: %{public}d", fd);
347 close(fd);
348 if (photoAssetProxy) {
349 delete photoAssetProxy;
350 }
351 videoFdQueue_.pop();
352 }
353 MEDIA_INFO_LOG("AvcodecTaskManager release end");
354 }
355
Stop()356 void AvcodecTaskManager::Stop()
357 {
358 CAMERA_SYNC_TRACE;
359 MEDIA_INFO_LOG("AvcodecTaskManager Stop start");
360 if (videoEncoder_ != nullptr) {
361 videoEncoder_->Stop();
362 }
363 if (audioEncoder_ != nullptr) {
364 audioEncoder_->Stop();
365 }
366 MEDIA_INFO_LOG("AvcodecTaskManager Stop end");
367 }
368
ClearTaskResource()369 void AvcodecTaskManager::ClearTaskResource()
370 {
371 CAMERA_SYNC_TRACE;
372 MEDIA_INFO_LOG("AvcodecTaskManager ClearTaskResource start");
373 {
374 lock_guard<mutex> lock(taskManagerMutex_);
375 isActive_ = false;
376 if (taskManager_ != nullptr) {
377 taskManager_->CancelAllTasks();
378 taskManager_.reset();
379 }
380 }
381 {
382 lock_guard<mutex> lock(encoderManagerMutex_);
383 isActive_ = false;
384 if (videoEncoderManager_ != nullptr) {
385 videoEncoderManager_->CancelAllTasks();
386 videoEncoderManager_.reset();
387 }
388 }
389 {
390 lock_guard<mutex> lock(startTimeMutex_);
391 mPStartTimeMap_.clear();
392 }
393 {
394 lock_guard<mutex> lock(endTimeMutex_);
395 mPEndTimeMap_.clear();
396 }
397 MEDIA_INFO_LOG("AvcodecTaskManager ClearTaskResource end");
398 }
399
SetVideoBufferDuration(uint32_t preBufferCount,uint32_t postBufferCount)400 void AvcodecTaskManager::SetVideoBufferDuration(uint32_t preBufferCount, uint32_t postBufferCount)
401 {
402 MEDIA_INFO_LOG("AvcodecTaskManager SetVideoBufferCount enter");
403 preBufferDuration_ = static_cast<int64_t>(preBufferCount) * ONE_BILLION / VIDEO_FRAME_RATE;
404 postBufferDuration_ = static_cast<int64_t>(postBufferCount) * ONE_BILLION / VIDEO_FRAME_RATE;
405 }
406 } // namespace CameraStandard
407 } // namespace OHOS