1 /*
2 * Copyright (c) 2021-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 "dcamera_sink_data_process.h"
17
18 #include "anonymous_string.h"
19 #include "dcamera_channel_sink_impl.h"
20 #include "dcamera_pipeline_sink.h"
21 #include "dcamera_sink_data_process_listener.h"
22 #include "dcamera_hidumper.h"
23 #include "distributed_camera_constants.h"
24 #include "distributed_camera_errno.h"
25 #include "distributed_hardware_log.h"
26 #include <sys/prctl.h>
27
28 namespace OHOS {
29 namespace DistributedHardware {
DCameraSinkDataProcess(const std::string & dhId,std::shared_ptr<ICameraChannel> & channel)30 DCameraSinkDataProcess::DCameraSinkDataProcess(const std::string& dhId, std::shared_ptr<ICameraChannel>& channel)
31 : dhId_(dhId), channel_(channel), eventHandler_(nullptr)
32 {
33 DHLOGI("DCameraSinkDataProcess Constructor dhId: %{public}s", GetAnonyString(dhId_).c_str());
34 }
35
~DCameraSinkDataProcess()36 DCameraSinkDataProcess::~DCameraSinkDataProcess()
37 {
38 DHLOGI("DCameraSinkDataProcess delete dhId: %{public}s", GetAnonyString(dhId_).c_str());
39 DumpFileUtil::CloseDumpFile(&dumpFile_);
40 if ((eventHandler_ != nullptr) && (eventHandler_->GetEventRunner() != nullptr)) {
41 eventHandler_->GetEventRunner()->Stop();
42 }
43 if (eventThread_.joinable()) {
44 eventThread_.join();
45 }
46 eventHandler_ = nullptr;
47 }
48
Init()49 void DCameraSinkDataProcess::Init()
50 {
51 DHLOGI("DCameraSinkDataProcess Init dhId: %{public}s", GetAnonyString(dhId_).c_str());
52 eventThread_ = std::thread([this]() { this->StartEventHandler(); });
53 std::unique_lock<std::mutex> lock(eventMutex_);
54 eventCon_.wait(lock, [this] {
55 return eventHandler_ != nullptr;
56 });
57 }
58
StartEventHandler()59 void DCameraSinkDataProcess::StartEventHandler()
60 {
61 prctl(PR_SET_NAME, SINK_START_EVENT.c_str());
62 auto runner = AppExecFwk::EventRunner::Create(false);
63 {
64 std::lock_guard<std::mutex> lock(eventMutex_);
65 eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
66 }
67 eventCon_.notify_one();
68 runner->Run();
69 }
70
StartCapture(std::shared_ptr<DCameraCaptureInfo> & captureInfo)71 int32_t DCameraSinkDataProcess::StartCapture(std::shared_ptr<DCameraCaptureInfo>& captureInfo)
72 {
73 DHLOGI("StartCapture dhId: %{public}s, width: %{public}d, height: %{public}d, format: %{public}d, stream: "
74 "%{public}d, encode: %{public}d", GetAnonyString(dhId_).c_str(), captureInfo->width_, captureInfo->height_,
75 captureInfo->format_, captureInfo->streamType_, captureInfo->encodeType_);
76 DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, DUMP_DCAMERA_AFTER_ENC_FILENAME, &dumpFile_);
77 captureInfo_ = captureInfo;
78 if (pipeline_ != nullptr) {
79 DHLOGI("StartCapture %{public}s pipeline already exits", GetAnonyString(dhId_).c_str());
80 return DCAMERA_OK;
81 }
82
83 if (captureInfo->streamType_ == CONTINUOUS_FRAME) {
84 DHLOGI("StartCapture %{public}s create data process pipeline", GetAnonyString(dhId_).c_str());
85 pipeline_ = std::make_shared<DCameraPipelineSink>();
86 auto dataProcess = std::shared_ptr<DCameraSinkDataProcess>(shared_from_this());
87 std::shared_ptr<DataProcessListener> listener = std::make_shared<DCameraSinkDataProcessListener>(dataProcess);
88 VideoConfigParams srcParams(VideoCodecType::NO_CODEC,
89 GetPipelineFormat(captureInfo->format_),
90 DCAMERA_PRODUCER_FPS_DEFAULT,
91 captureInfo->width_,
92 captureInfo->height_);
93 VideoConfigParams destParams(GetPipelineCodecType(captureInfo->encodeType_),
94 GetPipelineFormat(captureInfo->format_),
95 DCAMERA_PRODUCER_FPS_DEFAULT,
96 captureInfo->width_,
97 captureInfo->height_);
98 int32_t ret = pipeline_->CreateDataProcessPipeline(PipelineType::VIDEO, srcParams, destParams, listener);
99 if (ret != DCAMERA_OK) {
100 DHLOGE("create data process pipeline failed, dhId: %{public}s, ret: %{public}d",
101 GetAnonyString(dhId_).c_str(), ret);
102 return ret;
103 }
104 }
105 DHLOGI("StartCapture %{public}s success", GetAnonyString(dhId_).c_str());
106 return DCAMERA_OK;
107 }
108
StopCapture()109 int32_t DCameraSinkDataProcess::StopCapture()
110 {
111 DHLOGI("StopCapture dhId: %{public}s", GetAnonyString(dhId_).c_str());
112 if (pipeline_ != nullptr) {
113 pipeline_->DestroyDataProcessPipeline();
114 pipeline_ = nullptr;
115 }
116 if (eventHandler_ != nullptr) {
117 DHLOGI("StopCapture dhId: %{public}s, remove all events", GetAnonyString(dhId_).c_str());
118 eventHandler_->RemoveAllEvents();
119 }
120 return DCAMERA_OK;
121 }
122
FeedStream(std::shared_ptr<DataBuffer> & dataBuffer)123 int32_t DCameraSinkDataProcess::FeedStream(std::shared_ptr<DataBuffer>& dataBuffer)
124 {
125 DCStreamType type = captureInfo_->streamType_;
126 DHLOGD("FeedStream dhId: %{public}s, stream type: %{public}d", GetAnonyString(dhId_).c_str(), type);
127 switch (type) {
128 case CONTINUOUS_FRAME: {
129 int32_t ret = FeedStreamInner(dataBuffer);
130 if (ret != DCAMERA_OK) {
131 DHLOGE("FeedStream continuous frame failed, dhId: %{public}s, ret: %{public}d",
132 GetAnonyString(dhId_).c_str(), ret);
133 return ret;
134 }
135 break;
136 }
137 case SNAPSHOT_FRAME: {
138 SendDataAsync(dataBuffer);
139 break;
140 }
141 default: {
142 DHLOGE("FeedStream %{public}s unknown stream type: %{public}d", GetAnonyString(dhId_).c_str(), type);
143 break;
144 }
145 }
146 return DCAMERA_OK;
147 }
148
SendDataAsync(const std::shared_ptr<DataBuffer> & buffer)149 void DCameraSinkDataProcess::SendDataAsync(const std::shared_ptr<DataBuffer>& buffer)
150 {
151 auto sendFunc = [this, buffer]() mutable {
152 std::shared_ptr<DataBuffer> sendBuffer = buffer;
153 int32_t ret = channel_->SendData(sendBuffer);
154 uint64_t buffersSize = static_cast<uint64_t>(buffer->Size());
155 DHLOGD("SendData type: %{public}d output data ret: %{public}d, dhId: %{public}s, bufferSize: %{public}" PRIu64,
156 captureInfo_->streamType_, ret, GetAnonyString(dhId_).c_str(), buffersSize);
157 };
158 if (eventHandler_ != nullptr) {
159 eventHandler_->PostTask(sendFunc);
160 }
161 }
162
OnProcessedVideoBuffer(const std::shared_ptr<DataBuffer> & videoResult)163 void DCameraSinkDataProcess::OnProcessedVideoBuffer(const std::shared_ptr<DataBuffer>& videoResult)
164 {
165 #ifdef DUMP_DCAMERA_FILE
166 if (DcameraHidumper::GetInstance().GetDumpFlag() && (IsUnderDumpMaxSize(DUMP_PATH + AFTER_ENCODE) == DCAMERA_OK)) {
167 DumpBufferToFile(DUMP_PATH + AFTER_ENCODE, videoResult->Data(), videoResult->Size());
168 }
169 #endif
170 DumpFileUtil::WriteDumpFile(dumpFile_, static_cast<void *>(videoResult->Data()), videoResult->Size());
171 SendDataAsync(videoResult);
172 }
173
OnError(DataProcessErrorType errorType)174 void DCameraSinkDataProcess::OnError(DataProcessErrorType errorType)
175 {
176 DHLOGE("OnError %{public}s data process pipeline error, errorType: %{public}d",
177 GetAnonyString(dhId_).c_str(), errorType);
178 }
179
FeedStreamInner(std::shared_ptr<DataBuffer> & dataBuffer)180 int32_t DCameraSinkDataProcess::FeedStreamInner(std::shared_ptr<DataBuffer>& dataBuffer)
181 {
182 std::vector<std::shared_ptr<DataBuffer>> buffers;
183 buffers.push_back(dataBuffer);
184 CHECK_AND_RETURN_RET_LOG(pipeline_ == nullptr, DCAMERA_BAD_VALUE, "pipeline_ is null.");
185 int32_t ret = pipeline_->ProcessData(buffers);
186 if (ret != DCAMERA_OK) {
187 DHLOGE("process data failed, dhId: %{public}s, ret: %{public}d", GetAnonyString(dhId_).c_str(), ret);
188 return ret;
189 }
190 return DCAMERA_OK;
191 }
192
GetPipelineCodecType(DCEncodeType encodeType)193 VideoCodecType DCameraSinkDataProcess::GetPipelineCodecType(DCEncodeType encodeType)
194 {
195 VideoCodecType codecType;
196 switch (encodeType) {
197 case ENCODE_TYPE_H264:
198 codecType = VideoCodecType::CODEC_H264;
199 break;
200 case ENCODE_TYPE_H265:
201 codecType = VideoCodecType::CODEC_H265;
202 break;
203 case ENCODE_TYPE_MPEG4_ES:
204 codecType = VideoCodecType::CODEC_MPEG4_ES;
205 break;
206 default:
207 codecType = VideoCodecType::NO_CODEC;
208 break;
209 }
210 return codecType;
211 }
212
GetPipelineFormat(int32_t format)213 Videoformat DCameraSinkDataProcess::GetPipelineFormat(int32_t format)
214 {
215 Videoformat videoFormat;
216 switch (format) {
217 case OHOS_CAMERA_FORMAT_RGBA_8888:
218 videoFormat = Videoformat::RGBA_8888;
219 break;
220 default:
221 videoFormat = Videoformat::NV21;
222 break;
223 }
224 return videoFormat;
225 }
226
GetProperty(const std::string & propertyName,PropertyCarrier & propertyCarrier)227 int32_t DCameraSinkDataProcess::GetProperty(const std::string& propertyName, PropertyCarrier& propertyCarrier)
228 {
229 if (pipeline_ == nullptr) {
230 DHLOGD("GetProperty: pipeline is nullptr.");
231 return DCAMERA_BAD_VALUE;
232 }
233 return pipeline_->GetProperty(propertyName, propertyCarrier);
234 }
235 } // namespace DistributedHardware
236 } // namespace OHOS