• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "image_source_encoder.h"
17 
18 #include <securec.h>
19 #include <stddef.h>
20 
21 #include "dscreen_constants.h"
22 #include "dscreen_errcode.h"
23 #include "dscreen_log.h"
24 
25 namespace OHOS {
26 namespace DistributedHardware {
ConfigureEncoder(const VideoParam & configParam)27 int32_t ImageSourceEncoder::ConfigureEncoder(const VideoParam &configParam)
28 {
29     DHLOGI("%s: ConfigureEncoder.", LOG_TAG);
30     int32_t ret = InitVideoEncoder(configParam);
31     if (ret != DH_SUCCESS) {
32         DHLOGE("%s: Init encoder failed ret:%d.", LOG_TAG, ret);
33         return ret;
34     }
35 
36     ret = SetEncoderFormat(configParam);
37     if (ret != DH_SUCCESS) {
38         DHLOGE("%s: Set encoder format failed ret:%d.", LOG_TAG, ret);
39         return ret;
40     }
41 
42     videoSurface_ = videoEncoder_->CreateInputSurface();
43     if (videoSurface_ == nullptr) {
44         DHLOGE("%s: Create encoder surface failed.", LOG_TAG);
45         return ERR_DH_SCREEN_CODEC_SURFACE_ERROR;
46     }
47 
48     return DH_SUCCESS;
49 }
50 
ReleaseEncoder()51 int32_t ImageSourceEncoder::ReleaseEncoder()
52 {
53     DHLOGI("%s: ReleaseEncoder.", LOG_TAG);
54     if (!videoEncoder_) {
55         DHLOGE("%s: Encoder is null.", LOG_TAG);
56         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
57     }
58 
59     int32_t ret = videoEncoder_->Release();
60     if (ret != Media::MSERR_OK) {
61         DHLOGE("%s: Release encoder failed.", LOG_TAG);
62         return ERR_DH_SCREEN_CODEC_RELEASE_FAILED;
63     }
64     encodeVideoCallback_ = nullptr;
65     videoEncoder_ = nullptr;
66 
67     return DH_SUCCESS;
68 }
69 
StartEncoder()70 int32_t ImageSourceEncoder::StartEncoder()
71 {
72     DHLOGI("%s: StartEncoder.", LOG_TAG);
73     if (!videoEncoder_) {
74         DHLOGE("%s: Encoder is null.", LOG_TAG);
75         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
76     }
77 
78     int32_t ret = videoEncoder_->Prepare();
79     if (ret != Media::MSERR_OK) {
80         DHLOGE("%s: Prepare encoder failed.", LOG_TAG);
81         return ERR_DH_SCREEN_CODEC_PREPARE_FAILED;
82     }
83 
84     ret = videoEncoder_->Start();
85     if (ret != Media::MSERR_OK) {
86         DHLOGE("%s: Start encoder failed.", LOG_TAG);
87         return ERR_DH_SCREEN_CODEC_START_FAILED;
88     }
89 
90     return DH_SUCCESS;
91 }
92 
StopEncoder()93 int32_t ImageSourceEncoder::StopEncoder()
94 {
95     DHLOGI("%s: StopEncoder.", LOG_TAG);
96     if (!videoEncoder_) {
97         DHLOGE("%s: Encoder is null.", LOG_TAG);
98         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
99     }
100 
101     int32_t ret = videoEncoder_->Flush();
102     if (ret != Media::MSERR_OK) {
103         DHLOGE("%s: Flush encoder failed.", LOG_TAG);
104     }
105 
106     ret = videoEncoder_->Stop();
107     if (ret != Media::MSERR_OK) {
108         DHLOGE("%s: Stop encoder failed.", LOG_TAG);
109         return ERR_DH_SCREEN_CODEC_STOP_FAILED;
110     }
111 
112     return DH_SUCCESS;
113 }
114 
InitVideoEncoder(const VideoParam & configParam)115 int32_t ImageSourceEncoder::InitVideoEncoder(const VideoParam &configParam)
116 {
117     DHLOGI("%s: InitVideoEncoder.", LOG_TAG);
118     switch (configParam.GetCodecType()) {
119         case VIDEO_CODEC_TYPE_VIDEO_H264:
120             videoEncoder_ = Media::VideoEncoderFactory::CreateByMime("video/avc");
121             break;
122         case VIDEO_CODEC_TYPE_VIDEO_H265:
123             videoEncoder_ = Media::VideoEncoderFactory::CreateByMime("video/hevc");
124             break;
125         case VIDEO_CODEC_TYPE_VIDEO_MPEG4:
126             videoEncoder_ = Media::VideoEncoderFactory::CreateByMime("video/mp4v-es");
127             break;
128         default:
129             DHLOGE("%s: codecType is invalid!", LOG_TAG);
130             videoEncoder_ = nullptr;
131     }
132 
133     if (videoEncoder_ == nullptr) {
134         DHLOGE("%s: Create videoEncoder failed.", LOG_TAG);
135         return ERR_DH_SCREEN_TRANS_CREATE_CODEC_FAILED;
136     }
137 
138     encodeVideoCallback_ = std::make_shared<ImageEncoderCallback>(shared_from_this());
139     int32_t ret = videoEncoder_->SetCallback(encodeVideoCallback_);
140     if (ret != Media::MSERR_OK) {
141         DHLOGE("%s: Set codec callback failed.", LOG_TAG);
142         return ERR_DH_SCREEN_CODEC_SET_CALLBACK_FAILED;
143     }
144 
145     return DH_SUCCESS;
146 }
147 
SetEncoderFormat(const VideoParam & configParam)148 int32_t ImageSourceEncoder::SetEncoderFormat(const VideoParam &configParam)
149 {
150     DHLOGI("%s: SetEncoderFormat.", LOG_TAG);
151     if (!videoEncoder_) {
152         DHLOGE("%s: Encoder is null.", LOG_TAG);
153         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
154     }
155 
156     switch (configParam.GetCodecType()) {
157         case VIDEO_CODEC_TYPE_VIDEO_H264:
158             imageFormat_.PutStringValue("codec_mime", "video/avc");
159             break;
160         case VIDEO_CODEC_TYPE_VIDEO_H265:
161             imageFormat_.PutStringValue("codec_mime", "video/hevc");
162             break;
163         case VIDEO_CODEC_TYPE_VIDEO_MPEG4:
164             imageFormat_.PutStringValue("codec_mime", "video/mp4v-es");
165             break;
166         default:
167             DHLOGE("%s: Codec type is invalid.", LOG_TAG);
168             return ERR_DH_SCREEN_TRANS_ILLEGAL_PARAM;
169     }
170     switch (configParam.GetVideoFormat()) {
171         case VIDEO_DATA_FORMAT_YUVI420:
172             imageFormat_.PutIntValue("pixel_format", Media::VideoPixelFormat::YUVI420);
173             break;
174         case VIDEO_DATA_FORMAT_NV12:
175             imageFormat_.PutIntValue("pixel_format", Media::VideoPixelFormat::NV12);
176             break;
177         case VIDEO_DATA_FORMAT_NV21:
178             imageFormat_.PutIntValue("pixel_format", Media::VideoPixelFormat::NV21);
179             break;
180         case VIDEO_DATA_FORMAT_RGBA8888:
181             imageFormat_.PutIntValue("pixel_format", Media::VideoPixelFormat::RGBA);
182             break;
183         default:
184             DHLOGE("%s: Video format is invalid.", LOG_TAG);
185             return ERR_DH_SCREEN_TRANS_ILLEGAL_PARAM;
186     }
187     imageFormat_.PutLongValue("max_input_size", MAX_YUV420_BUFFER_SIZE);
188     imageFormat_.PutIntValue("width", configParam.GetVideoWidth());
189     imageFormat_.PutIntValue("height", configParam.GetVideoHeight());
190     imageFormat_.PutIntValue("frame_rate", configParam.GetFps());
191 
192     int32_t ret = videoEncoder_->Configure(imageFormat_);
193     if (ret != Media::MSERR_OK) {
194         DHLOGE("%s: Configure encoder failed.", LOG_TAG);
195         return ERR_DH_SCREEN_CODEC_CONFIGURE_FAILED;
196     }
197     return DH_SUCCESS;
198 }
199 
OnError(Media::AVCodecErrorType errorType,int32_t errorCode)200 void ImageSourceEncoder::OnError(Media::AVCodecErrorType errorType, int32_t errorCode)
201 {
202     DHLOGI("%s: Encoder error, errorType(%d), errorCode(%d)", LOG_TAG, errorType, errorCode);
203     std::shared_ptr<IImageSourceProcessorListener> listener = imageProcessorListener_.lock();
204     if (!listener) {
205         DHLOGE("%s: Processor listener is null", LOG_TAG);
206         return;
207     }
208     listener->OnProcessorStateNotify(errorCode);
209 }
210 
OnOutputBufferAvailable(uint32_t index,Media::AVCodecBufferInfo info,Media::AVCodecBufferFlag flag)211 void ImageSourceEncoder::OnOutputBufferAvailable(uint32_t index, Media::AVCodecBufferInfo info,
212     Media::AVCodecBufferFlag flag)
213 {
214     DHLOGD("%s: OnOutputBufferAvailable.", LOG_TAG);
215     std::shared_ptr<IImageSourceProcessorListener> listener = imageProcessorListener_.lock();
216     if (!listener) {
217         DHLOGE("%s: Processor listener is null", LOG_TAG);
218         return;
219     }
220     if (!videoEncoder_) {
221         DHLOGE("%s: Encoder is null.", LOG_TAG);
222         return;
223     }
224 
225     encoderBufferInfo_ = info;
226     videoSharedMemory_ = videoEncoder_->GetOutputBuffer(index);
227     if (!videoSharedMemory_) {
228         DHLOGE("%s: GetOutputBuffer failed.", LOG_TAG);
229         return;
230     }
231 
232     size_t dataSize = static_cast<size_t>(info.size);
233     auto dataBuf = std::make_shared<DataBuffer>(dataSize);
234     if (!dataBuf) {
235         DHLOGE("%s: Create buffer failed.", LOG_TAG);
236         return;
237     }
238     int32_t ret = memcpy_s(dataBuf->Data(), dataBuf->Capacity(), videoSharedMemory_->GetBase(), dataSize);
239     if (ret != EOK) {
240         DHLOGE("%s: Copy data failed.", LOG_TAG);
241         return;
242     }
243     listener->OnImageProcessDone(dataBuf);
244 
245     ret = videoEncoder_->ReleaseOutputBuffer(index);
246     if (ret != Media::MSERR_OK) {
247         DHLOGE("%s: videoEncoder ReleaseOutputBuffer failed.", LOG_TAG);
248     }
249 }
250 
OnInputBufferAvailable(uint32_t index)251 void ImageSourceEncoder::OnInputBufferAvailable(uint32_t index)
252 {
253     (void) index;
254 }
255 
OnOutputFormatChanged(const Media::Format & format)256 void ImageSourceEncoder::OnOutputFormatChanged(const Media::Format &format)
257 {
258     (void) format;
259 }
260 } // namespace DistributedHardware
261 } // namespace OHOS