• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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_engine_ctrl.h"
17 #include <vector>
18 #include "media_errors.h"
19 #include "media_log.h"
20 #include "scope_guard.h"
21 
22 namespace {
23     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AVCodecEngineCtrl"};
24 }
25 
26 namespace OHOS {
27 namespace Media {
AVCodecEngineCtrl()28 AVCodecEngineCtrl::AVCodecEngineCtrl()
29 {
30     MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
31 }
32 
~AVCodecEngineCtrl()33 AVCodecEngineCtrl::~AVCodecEngineCtrl()
34 {
35     MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
36     (void)Release();
37 }
38 
Init(AVCodecType type,bool useSoftware,const std::string & name)39 int32_t AVCodecEngineCtrl::Init(AVCodecType type, bool useSoftware, const std::string &name)
40 {
41     MEDIA_LOGD("Enter Init");
42     codecType_ = type;
43     gstPipeline_ = GST_PIPELINE_CAST(gst_pipeline_new("codec-pipeline"));
44     CHECK_AND_RETURN_RET(gstPipeline_ != nullptr, MSERR_NO_MEMORY);
45 
46     bus_ = gst_pipeline_get_bus(gstPipeline_);
47     CHECK_AND_RETURN_RET(bus_ != nullptr, MSERR_UNKNOWN);
48     gst_bus_set_sync_handler(bus_, BusSyncHandler, this, nullptr);
49 
50     codecBin_ = GST_ELEMENT_CAST(gst_object_ref(gst_element_factory_make("codecbin", "the_codec_bin")));
51     CHECK_AND_RETURN_RET(codecBin_ != nullptr, MSERR_NO_MEMORY);
52 
53     gboolean ret = gst_bin_add(GST_BIN_CAST(gstPipeline_), codecBin_);
54     CHECK_AND_RETURN_RET(ret == TRUE, MSERR_NO_MEMORY);
55 
56     g_object_set(codecBin_, "use-software", static_cast<gboolean>(useSoftware), nullptr);
57     g_object_set(codecBin_, "type", static_cast<int32_t>(type), nullptr);
58     g_object_set(codecBin_, "coder-name", name.c_str(), nullptr);
59 
60     isEncoder_ = (type == AVCODEC_TYPE_VIDEO_ENCODER) || (type == AVCODEC_TYPE_AUDIO_ENCODER);
61     if (isEncoder_) {
62         g_object_set(codecBin_, "src-convert", static_cast<gboolean>(true), nullptr);
63     } else {
64         g_object_set(codecBin_, "sink-convert", static_cast<gboolean>(true), nullptr);
65     }
66 
67     return MSERR_OK;
68 }
69 
Prepare(std::shared_ptr<ProcessorConfig> inputConfig,std::shared_ptr<ProcessorConfig> outputConfig)70 int32_t AVCodecEngineCtrl::Prepare(std::shared_ptr<ProcessorConfig> inputConfig,
71     std::shared_ptr<ProcessorConfig> outputConfig)
72 {
73     if (src_ == nullptr) {
74         MEDIA_LOGD("Use buffer src");
75         src_ = AVCodecEngineFactory::CreateSrc(SrcType::SRC_TYPE_BYTEBUFFER);
76         CHECK_AND_RETURN_RET_LOG(src_ != nullptr, MSERR_NO_MEMORY, "No memory");
77         CHECK_AND_RETURN_RET(src_->Init() == MSERR_OK, MSERR_UNKNOWN);
78         CHECK_AND_RETURN_RET(src_->SetCallback(obs_) == MSERR_OK, MSERR_UNKNOWN);
79     }
80 
81     if (sink_ == nullptr) {
82         MEDIA_LOGD("Use buffer sink");
83         sink_ = AVCodecEngineFactory::CreateSink(SinkType::SINK_TYPE_BYTEBUFFER);
84         CHECK_AND_RETURN_RET_LOG(sink_ != nullptr, MSERR_NO_MEMORY, "No memory");
85         CHECK_AND_RETURN_RET(sink_->Init() == MSERR_OK, MSERR_UNKNOWN);
86         CHECK_AND_RETURN_RET(sink_->SetCallback(obs_) == MSERR_OK, MSERR_UNKNOWN);
87     }
88 
89     CHECK_AND_RETURN_RET(codecBin_ != nullptr, MSERR_UNKNOWN);
90     if (inputConfig->needParser_) {
91         g_object_set(codecBin_, "parser", static_cast<gboolean>(true), nullptr);
92     }
93     g_object_set(codecBin_, "src", static_cast<gpointer>(const_cast<GstElement *>(src_->GetElement())), nullptr);
94     CHECK_AND_RETURN_RET(src_->Configure(inputConfig) == MSERR_OK, MSERR_UNKNOWN);
95 
96     g_object_set(codecBin_, "sink", static_cast<gpointer>(const_cast<GstElement *>(sink_->GetElement())), nullptr);
97     CHECK_AND_RETURN_RET(sink_->Configure(outputConfig) == MSERR_OK, MSERR_UNKNOWN);
98 
99     CHECK_AND_RETURN_RET(gstPipeline_ != nullptr, MSERR_UNKNOWN);
100     GstStateChangeReturn ret = gst_element_set_state(GST_ELEMENT_CAST(gstPipeline_), GST_STATE_PAUSED);
101     CHECK_AND_RETURN_RET(ret != GST_STATE_CHANGE_FAILURE, MSERR_UNKNOWN);
102     if (ret == GST_STATE_CHANGE_ASYNC) {
103         MEDIA_LOGD("Wait state change");
104         std::unique_lock<std::mutex> lock(gstPipeMutex_);
105         gstPipeCond_.wait(lock);
106     }
107 
108     MEDIA_LOGD("Prepare success");
109     return MSERR_OK;
110 }
111 
Start()112 int32_t AVCodecEngineCtrl::Start()
113 {
114     CHECK_AND_RETURN_RET(gstPipeline_ != nullptr, MSERR_UNKNOWN);
115 
116     CHECK_AND_RETURN_RET(sink_ != nullptr, MSERR_UNKNOWN);
117     if (flushAtStart_ || sink_->IsEos()) {
118         CHECK_AND_RETURN_RET(Flush() == MSERR_OK, MSERR_INVALID_OPERATION);
119         flushAtStart_ = false;
120     }
121 
122     CHECK_AND_RETURN_RET(src_->Start() == MSERR_OK, MSERR_INVALID_OPERATION);
123     GstStateChangeReturn ret = gst_element_set_state(GST_ELEMENT_CAST(gstPipeline_), GST_STATE_PLAYING);
124     CHECK_AND_RETURN_RET(ret != GST_STATE_CHANGE_FAILURE, MSERR_UNKNOWN);
125     if (ret == GST_STATE_CHANGE_ASYNC) {
126         MEDIA_LOGD("Wait state change");
127         std::unique_lock<std::mutex> lock(gstPipeMutex_);
128         gstPipeCond_.wait(lock);
129     }
130 
131     isStart_ = true;
132     MEDIA_LOGD("Start success");
133     return MSERR_OK;
134 }
135 
Stop()136 int32_t AVCodecEngineCtrl::Stop()
137 {
138     if (!isStart_) {
139         return MSERR_OK;
140     }
141 
142     CHECK_AND_RETURN_RET(src_->Stop() == MSERR_OK, MSERR_INVALID_OPERATION);
143     GstStateChangeReturn ret = gst_element_set_state(GST_ELEMENT_CAST(gstPipeline_), GST_STATE_PAUSED);
144     CHECK_AND_RETURN_RET(ret != GST_STATE_CHANGE_FAILURE, MSERR_UNKNOWN);
145     if (ret == GST_STATE_CHANGE_ASYNC) {
146         std::unique_lock<std::mutex> lock(gstPipeMutex_);
147         gstPipeCond_.wait(lock);
148     }
149 
150     CHECK_AND_RETURN_RET(Flush() == MSERR_OK, MSERR_UNKNOWN);
151 
152     MEDIA_LOGD("Stop success");
153     isStart_ = false;
154     return MSERR_OK;
155 }
156 
Flush()157 int32_t AVCodecEngineCtrl::Flush()
158 {
159     CHECK_AND_RETURN_RET(gstPipeline_ != nullptr, MSERR_UNKNOWN);
160 
161     CHECK_AND_RETURN_RET(src_ != nullptr, MSERR_UNKNOWN);
162     if (!src_->Needflush()) {
163         MEDIA_LOGD("Flush success, src is empty.");
164         return MSERR_OK;
165     }
166     CHECK_AND_RETURN_RET(src_->Flush() == MSERR_OK, MSERR_UNKNOWN);
167 
168     CHECK_AND_RETURN_RET(sink_ != nullptr, MSERR_UNKNOWN);
169     CHECK_AND_RETURN_RET(sink_->Flush() == MSERR_OK, MSERR_UNKNOWN);
170 
171     CHECK_AND_RETURN_RET(codecBin_ != nullptr, MSERR_UNKNOWN);
172     GstEvent *event = gst_event_new_flush_start();
173     CHECK_AND_RETURN_RET(event != nullptr, MSERR_NO_MEMORY);
174     (void)gst_element_send_event(codecBin_, event);
175 
176     event = gst_event_new_flush_stop(FALSE);
177     CHECK_AND_RETURN_RET(event != nullptr, MSERR_NO_MEMORY);
178     (void)gst_element_send_event(codecBin_, event);
179 
180     MEDIA_LOGD("Flush success");
181     return MSERR_OK;
182 }
183 
Release()184 int32_t AVCodecEngineCtrl::Release()
185 {
186     if (gstPipeline_ != nullptr) {
187         CHECK_AND_RETURN_RET(Stop() == MSERR_OK, MSERR_UNKNOWN);
188         (void)gst_element_set_state(GST_ELEMENT_CAST(gstPipeline_), GST_STATE_NULL);
189     }
190 
191     src_ = nullptr;
192     sink_ = nullptr;
193     if (codecBin_ != nullptr) {
194         gst_object_unref(codecBin_);
195         codecBin_ = nullptr;
196     }
197     if (gstPipeline_ != nullptr) {
198         gst_object_unref(gstPipeline_);
199         gstPipeline_ = nullptr;
200     }
201     if (bus_ != nullptr) {
202         g_clear_object(&bus_);
203         bus_ = nullptr;
204     }
205 
206     MEDIA_LOGD("Release success");
207     return MSERR_OK;
208 }
209 
SetObs(const std::weak_ptr<IAVCodecEngineObs> & obs)210 void AVCodecEngineCtrl::SetObs(const std::weak_ptr<IAVCodecEngineObs> &obs)
211 {
212     obs_ = obs;
213 }
214 
CreateInputSurface(std::shared_ptr<ProcessorConfig> inputConfig)215 sptr<Surface> AVCodecEngineCtrl::CreateInputSurface(std::shared_ptr<ProcessorConfig> inputConfig)
216 {
217     CHECK_AND_RETURN_RET(codecType_ == AVCODEC_TYPE_VIDEO_ENCODER, nullptr);
218     if (src_ == nullptr) {
219         MEDIA_LOGD("Use surface src");
220         src_ = AVCodecEngineFactory::CreateSrc(SrcType::SRC_TYPE_SURFACE);
221         CHECK_AND_RETURN_RET_LOG(src_ != nullptr, nullptr, "No memory");
222         CHECK_AND_RETURN_RET_LOG(src_->Init() == MSERR_OK, nullptr, "Failed to create input surface");
223     }
224 
225     auto surface =  src_->CreateInputSurface(inputConfig);
226     CHECK_AND_RETURN_RET(surface != nullptr, nullptr);
227     useSurfaceInput_ = true;
228     CHECK_AND_RETURN_RET(codecBin_ != nullptr, nullptr);
229     g_object_set(codecBin_, "use-surface-input", TRUE, nullptr);
230     MEDIA_LOGD("CreateInputSurface success");
231     return surface;
232 }
233 
SetOutputSurface(sptr<Surface> surface)234 int32_t AVCodecEngineCtrl::SetOutputSurface(sptr<Surface> surface)
235 {
236     CHECK_AND_RETURN_RET(codecType_ == AVCODEC_TYPE_VIDEO_DECODER, MSERR_INVALID_OPERATION);
237     if (sink_ == nullptr) {
238         MEDIA_LOGD("Use surface sink");
239         sink_ = AVCodecEngineFactory::CreateSink(SinkType::SINK_TYPE_SURFACE);
240         CHECK_AND_RETURN_RET_LOG(sink_ != nullptr, MSERR_NO_MEMORY, "No memory");
241         CHECK_AND_RETURN_RET(sink_->Init() == MSERR_OK, MSERR_UNKNOWN);
242         CHECK_AND_RETURN_RET(sink_->SetCallback(obs_) == MSERR_OK, MSERR_UNKNOWN);
243     }
244     if (sink_->SetOutputSurface(surface) == MSERR_OK) {
245         useSurfaceRender_ = true;
246     } else {
247         return MSERR_UNKNOWN;
248     }
249 
250     MEDIA_LOGD("SetOutputSurface success");
251     return MSERR_OK;
252 }
253 
GetInputBuffer(uint32_t index)254 std::shared_ptr<AVSharedMemory> AVCodecEngineCtrl::GetInputBuffer(uint32_t index)
255 {
256     CHECK_AND_RETURN_RET(src_ != nullptr, nullptr);
257     return src_->GetInputBuffer(index);
258 }
259 
QueueInputBuffer(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag)260 int32_t AVCodecEngineCtrl::QueueInputBuffer(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag)
261 {
262     CHECK_AND_RETURN_RET(src_ != nullptr, MSERR_UNKNOWN);
263     int32_t ret = src_->QueueInputBuffer(index, info, flag);
264     CHECK_AND_RETURN_RET(ret == MSERR_OK, ret);
265     if (flag & AVCODEC_BUFFER_FLAG_EOS) {
266         GstEvent *event = gst_event_new_eos();
267         CHECK_AND_RETURN_RET(event != nullptr, MSERR_NO_MEMORY);
268         (void)gst_element_send_event(codecBin_, event);
269         flushAtStart_ = true;
270     }
271     return MSERR_OK;
272 }
273 
GetOutputBuffer(uint32_t index)274 std::shared_ptr<AVSharedMemory> AVCodecEngineCtrl::GetOutputBuffer(uint32_t index)
275 {
276     CHECK_AND_RETURN_RET(sink_ != nullptr, nullptr);
277     return sink_->GetOutputBuffer(index);
278 }
279 
ReleaseOutputBuffer(uint32_t index,bool render)280 int32_t AVCodecEngineCtrl::ReleaseOutputBuffer(uint32_t index, bool render)
281 {
282     CHECK_AND_RETURN_RET(sink_ != nullptr, MSERR_UNKNOWN);
283     return sink_->ReleaseOutputBuffer(index, render);
284 }
285 
SetParameter(const Format & format)286 int32_t AVCodecEngineCtrl::SetParameter(const Format &format)
287 {
288     CHECK_AND_RETURN_RET(src_ != nullptr, MSERR_UNKNOWN);
289     CHECK_AND_RETURN_RET(src_->SetParameter(format) == MSERR_OK, MSERR_UNKNOWN);
290 
291     CHECK_AND_RETURN_RET(sink_ != nullptr, MSERR_UNKNOWN);
292     CHECK_AND_RETURN_RET(sink_->SetParameter(format) == MSERR_OK, MSERR_UNKNOWN);
293 
294     CHECK_AND_RETURN_RET(codecBin_ != nullptr, MSERR_UNKNOWN);
295 
296     int32_t value = 0;
297     if (format.GetValueType(std::string_view("req_i_frame")) == FORMAT_TYPE_INT32) {
298         if (format.GetIntValue("req_i_frame", value) && value >= 0) {
299             g_object_set(codecBin_, "req-i-frame", static_cast<uint32_t>(value), nullptr);
300         }
301     }
302 
303     if (format.GetValueType(std::string_view("bitrate")) == FORMAT_TYPE_INT32) {
304         if (format.GetIntValue("bitrate", value) && value > 0) {
305             g_object_set(codecBin_, "bitrate", static_cast<uint32_t>(value), nullptr);
306         }
307     }
308 
309     if (format.GetValueType(std::string_view("vendor.custom")) == FORMAT_TYPE_ADDR) {
310         uint8_t *addr = nullptr;
311         size_t size = 0;
312         if (format.GetBuffer("vendor.custom", &addr, size) && addr != nullptr) {
313             GstBuffer *buffer = gst_buffer_new_allocate(nullptr, size, nullptr);
314             CHECK_AND_RETURN_RET(buffer != nullptr, MSERR_NO_MEMORY);
315 
316             ON_SCOPE_EXIT(0) { gst_buffer_unref(buffer); };
317 
318             gsize ret = gst_buffer_fill(buffer, 0, (char *)addr, size);
319             CHECK_AND_RETURN_RET(ret == static_cast<gsize>(size), MSERR_UNKNOWN);
320             g_object_set(codecBin_, "vendor", static_cast<gpointer>(buffer), nullptr);
321         }
322     }
323 
324     MEDIA_LOGD("SetParameter success");
325     return MSERR_OK;
326 }
327 
BusSyncHandler(GstBus * bus,GstMessage * message,gpointer userData)328 GstBusSyncReply AVCodecEngineCtrl::BusSyncHandler(GstBus *bus, GstMessage *message, gpointer userData)
329 {
330     CHECK_AND_RETURN_RET(message != nullptr, GST_BUS_DROP);
331 
332     auto self = reinterpret_cast<AVCodecEngineCtrl *>(userData);
333     switch (GST_MESSAGE_TYPE(message)) {
334         case GST_MESSAGE_STATE_CHANGED: {
335             CHECK_AND_RETURN_RET(message->src != nullptr, GST_BUS_DROP);
336             if (GST_IS_BIN(message->src) && !GST_IS_PIPELINE(message->src)) {
337                 MEDIA_LOGD("Finish state change");
338                 std::unique_lock<std::mutex> lock(self->gstPipeMutex_);
339                 self->gstPipeCond_.notify_all();
340             }
341             break;
342         }
343         case GST_MESSAGE_ERROR: {
344             int32_t errCode = MSERR_UNKNOWN;
345             GError *err = nullptr;
346             gst_message_parse_error(message, &err, nullptr);
347             if (err->domain == GST_CORE_ERROR) {
348                 errCode = MSERR_UNKNOWN;
349             } else if (err->domain == GST_LIBRARY_ERROR) {
350                 errCode = MSERR_UNSUPPORT;
351             } else
352             if (err->domain == GST_RESOURCE_ERROR) {
353                 errCode = MSERR_INVALID_VAL;
354             } else if (err->domain == GST_STREAM_ERROR) {
355                 errCode = MSERR_DATA_SOURCE_ERROR_UNKNOWN;
356             }
357 
358             auto obs = self->obs_.lock();
359             CHECK_AND_RETURN_RET(obs != nullptr, GST_BUS_DROP);
360             obs->OnError(AVCODEC_ERROR_INTERNAL, errCode);
361             break;
362         }
363         default: {
364             break;
365         }
366     }
367     return GST_BUS_PASS;
368 }
369 } // namespace Media
370 } // namespace OHOS
371