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