• 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 "src_bytebuffer_impl.h"
17 #include <mutex>
18 #include "gst_shmem_memory.h"
19 #include "buffer_type_meta.h"
20 #include "media_log.h"
21 #include "scope_guard.h"
22 #include "media_dfx.h"
23 
24 namespace {
25     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "SrcBytebufferImpl"};
26     constexpr uint32_t DEFAULT_BUFFER_NUM = 10;
27 }
28 
29 namespace OHOS {
30 namespace Media {
SrcBytebufferImpl()31 SrcBytebufferImpl::SrcBytebufferImpl()
32 {
33 }
34 
~SrcBytebufferImpl()35 SrcBytebufferImpl::~SrcBytebufferImpl()
36 {
37     bufferList_.clear();
38     if (src_ != nullptr) {
39         gst_object_unref(src_);
40         src_ = nullptr;
41     }
42     if (caps_ != nullptr) {
43         gst_caps_unref(caps_);
44         caps_ = nullptr;
45     }
46 }
47 
Init()48 int32_t SrcBytebufferImpl::Init()
49 {
50     src_ = GST_ELEMENT_CAST(gst_object_ref_sink(gst_element_factory_make("shmemsrc", "src")));
51     CHECK_AND_RETURN_RET_LOG(src_ != nullptr, MSERR_UNKNOWN, "Failed to gst_element_factory_make");
52     return MSERR_OK;
53 }
54 
Configure(const std::shared_ptr<ProcessorConfig> & config)55 int32_t SrcBytebufferImpl::Configure(const std::shared_ptr<ProcessorConfig> &config)
56 {
57     CHECK_AND_RETURN_RET(config != nullptr, MSERR_UNKNOWN);
58     CHECK_AND_RETURN_RET(src_ != nullptr, MSERR_UNKNOWN);
59 
60     g_object_set(G_OBJECT(src_), "buffer-num", DEFAULT_BUFFER_NUM, nullptr);
61     g_object_set(G_OBJECT(src_), "buffer-size", config->bufferSize_, nullptr);
62     g_object_set(G_OBJECT(src_), "caps", config->caps_, nullptr);
63     gst_mem_src_set_callback(GST_MEM_SRC(src_), BufferAvailable, this, nullptr);
64 
65     needCodecData_ = config->needCodecData_;
66     if (needCodecData_) {
67         caps_ = config->caps_;
68         gst_caps_ref(caps_);
69     }
70     return MSERR_OK;
71 }
72 
Start()73 int32_t SrcBytebufferImpl::Start()
74 {
75     std::unique_lock<std::mutex> lock(mutex_);
76     start_ = true;
77     return MSERR_OK;
78 }
79 
Stop()80 int32_t SrcBytebufferImpl::Stop()
81 {
82     std::unique_lock<std::mutex> lock(mutex_);
83     start_ = false;
84     return MSERR_OK;
85 }
86 
Flush()87 int32_t SrcBytebufferImpl::Flush()
88 {
89     std::unique_lock<std::mutex> lock(mutex_);
90     bufferList_.clear();
91     return MSERR_OK;
92 }
93 
Needflush()94 bool SrcBytebufferImpl::Needflush()
95 {
96     std::unique_lock<std::mutex> lock(mutex_);
97     return !bufferList_.empty();
98 }
99 
GetInputBuffer(uint32_t index)100 std::shared_ptr<AVSharedMemory> SrcBytebufferImpl::GetInputBuffer(uint32_t index)
101 {
102     std::unique_lock<std::mutex> lock(mutex_);
103     CHECK_AND_RETURN_RET(index <= bufferList_.size(), nullptr);
104     CHECK_AND_RETURN_RET(bufferList_[index] != nullptr, nullptr);
105     CHECK_AND_RETURN_RET(bufferList_[index]->owner_ == BufferWrapper::SERVER, nullptr);
106 
107     GstMemory *memory = gst_buffer_peek_memory(bufferList_[index]->gstBuffer_, 0);
108     CHECK_AND_RETURN_RET(memory != nullptr, nullptr);
109     CHECK_AND_RETURN_RET(gst_is_shmem_memory(memory), nullptr);
110 
111     GstShMemMemory *shmem = reinterpret_cast<GstShMemMemory *>(memory);
112     bufferList_[index]->owner_ = BufferWrapper::APP;
113 
114     return shmem->mem;
115 }
116 
QueueInputBuffer(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag)117 int32_t SrcBytebufferImpl::QueueInputBuffer(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag)
118 {
119     std::unique_lock<std::mutex> lock(mutex_);
120     CHECK_AND_RETURN_RET(index <= bufferList_.size(), MSERR_INVALID_VAL);
121     CHECK_AND_RETURN_RET(bufferList_[index] != nullptr, MSERR_INVALID_VAL);
122 
123     auto &bufWrapper = bufferList_[index];
124     CHECK_AND_RETURN_RET(bufWrapper->owner_ == BufferWrapper::APP, MSERR_INVALID_OPERATION);
125     CHECK_AND_RETURN_RET(bufWrapper->gstBuffer_ != nullptr, MSERR_INVALID_OPERATION);
126     CHECK_AND_RETURN_RET(info.offset >= 0 && info.size >= 0, MSERR_INVALID_VAL);
127     gst_buffer_resize(bufWrapper->gstBuffer_, info.offset, info.size);
128     GstBufferTypeMeta *meta = gst_buffer_get_buffer_type_meta(bufWrapper->gstBuffer_);
129     CHECK_AND_RETURN_RET(meta != nullptr, MSERR_INVALID_OPERATION);
130     meta->offset = static_cast<uint32_t>(info.offset);
131     meta->length = static_cast<uint32_t>(info.size);
132     MEDIA_LOGD("meta->offset change to: %{public}u, meta->length change to: %{public}u",
133         meta->offset, meta->length);
134 
135     if (needCodecData_) {
136         if (HandleCodecBuffer(index, info, flag) == MSERR_OK) {
137             needCodecData_ = false;
138             bufWrapper->owner_ = BufferWrapper::DOWNSTREAM;
139             gst_buffer_unref(bufWrapper->gstBuffer_);
140             bufWrapper->gstBuffer_ = nullptr;
141             return MSERR_OK;
142         }
143         return MSERR_UNKNOWN;
144     }
145 
146     uint8_t *address = bufWrapper->mem_->GetBase();
147     CHECK_AND_RETURN_RET(address != nullptr, MSERR_UNKNOWN);
148     CHECK_AND_RETURN_RET((info.offset + info.size) <= bufWrapper->mem_->GetSize(), MSERR_INVALID_VAL);
149 
150     constexpr int32_t usToNs = 1000;
151     if (info.presentationTimeUs < 0) {
152         MEDIA_LOGE("Invalid pts: < 0, use 0 as default");
153         GST_BUFFER_PTS(bufWrapper->gstBuffer_) = 0;
154     } else if (info.presentationTimeUs >= (INT64_MAX / usToNs)) {
155         MEDIA_LOGE("Invalid pts: too big, use 0 as default");
156         GST_BUFFER_PTS(bufWrapper->gstBuffer_) = 0;
157     } else {
158         GST_BUFFER_PTS(bufWrapper->gstBuffer_) = static_cast<uint64_t>(info.presentationTimeUs * usToNs);
159     }
160 
161     CHECK_AND_RETURN_RET(src_ != nullptr, MSERR_UNKNOWN);
162     (void)gst_mem_src_push_buffer(GST_MEM_SRC(src_), bufWrapper->gstBuffer_);
163     bufWrapper->owner_ = BufferWrapper::DOWNSTREAM;
164     bufWrapper->gstBuffer_ = nullptr; // src elem take ownership of this buffer.
165 
166     MEDIA_LOGD("QueueInputBuffer, index = %{public}u", index);
167     return MSERR_OK;
168 }
169 
SetCallback(const std::weak_ptr<IAVCodecEngineObs> & obs)170 int32_t SrcBytebufferImpl::SetCallback(const std::weak_ptr<IAVCodecEngineObs> &obs)
171 {
172     std::unique_lock<std::mutex> lock(mutex_);
173     obs_ = obs;
174     return MSERR_OK;
175 }
176 
HandleCodecBuffer(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag)177 int32_t SrcBytebufferImpl::HandleCodecBuffer(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag)
178 {
179     CHECK_AND_RETURN_RET(caps_ != nullptr, MSERR_UNKNOWN);
180     CHECK_AND_RETURN_RET(src_ != nullptr, MSERR_UNKNOWN);
181     bool hasCodecFlag = static_cast<uint32_t>(flag) & static_cast<uint32_t>(AVCODEC_BUFFER_FLAG_CODEC_DATA);
182     CHECK_AND_RETURN_RET(bufferList_[index] != nullptr, MSERR_INVALID_VAL);
183     CHECK_AND_RETURN_RET_LOG(hasCodecFlag == true, MSERR_INVALID_VAL, "First buffer must be codec buffer");
184 
185     uint8_t *address = bufferList_[index]->mem_->GetBase();
186     CHECK_AND_RETURN_RET(address != nullptr, MSERR_UNKNOWN);
187     CHECK_AND_RETURN_RET((info.offset + info.size) <= bufferList_[index]->mem_->GetSize(), MSERR_INVALID_VAL);
188 
189     GstBuffer *codecBuffer = gst_buffer_new_allocate(nullptr, info.size, nullptr);
190     CHECK_AND_RETURN_RET_LOG(codecBuffer != nullptr, MSERR_NO_MEMORY, "no memory");
191 
192     ON_SCOPE_EXIT(0) { gst_buffer_unref(codecBuffer); };
193 
194     gsize size = gst_buffer_fill(codecBuffer, 0, (char*)address + info.offset, info.size);
195     CHECK_AND_RETURN_RET(size == static_cast<gsize>(info.size), MSERR_UNKNOWN);
196 
197     gst_caps_set_simple(caps_, "codec_data", GST_TYPE_BUFFER, codecBuffer, nullptr);
198     g_object_set(G_OBJECT(src_), "caps", caps_, nullptr);
199 
200     CHECK_AND_RETURN_RET(gst_base_src_set_caps(GST_BASE_SRC(src_), caps_) == TRUE, MSERR_UNKNOWN);
201     return MSERR_OK;
202 }
203 
BufferAvailable(GstMemSrc * memsrc,gpointer userData)204 GstFlowReturn SrcBytebufferImpl::BufferAvailable(GstMemSrc *memsrc, gpointer userData)
205 {
206     CHECK_AND_RETURN_RET(memsrc != nullptr, GST_FLOW_ERROR);
207     CHECK_AND_RETURN_RET(userData != nullptr, GST_FLOW_ERROR);
208 
209     GstBuffer *buffer = gst_mem_src_pull_buffer(memsrc);
210     CHECK_AND_RETURN_RET(buffer != nullptr, GST_FLOW_ERROR);
211 
212     SrcBytebufferImpl *thiz = reinterpret_cast<SrcBytebufferImpl *>(userData);
213     int32_t ret = thiz->HandleBufferAvailable(buffer);
214     CHECK_AND_RETURN_RET(ret == MSERR_OK, GST_FLOW_ERROR);
215 
216     return GST_FLOW_OK;
217 }
218 
HandleBufferAvailable(GstBuffer * buffer)219 int32_t SrcBytebufferImpl::HandleBufferAvailable(GstBuffer *buffer)
220 {
221     std::unique_lock<std::mutex> lock(mutex_);
222     ON_SCOPE_EXIT(0) { gst_buffer_unref(buffer); };
223     if (!start_) {
224         MEDIA_LOGD("Codec source is stop, unref available buffer");
225         return MSERR_OK;
226     }
227 
228     GstMemory *memory = gst_buffer_peek_memory(buffer, 0);
229     CHECK_AND_RETURN_RET(memory != nullptr, MSERR_UNKNOWN);
230     CHECK_AND_RETURN_RET(gst_is_shmem_memory(memory), MSERR_UNKNOWN);
231     GstShMemMemory *shmem = reinterpret_cast<GstShMemMemory *>(memory);
232     CHECK_AND_RETURN_RET(shmem->mem != nullptr, MSERR_UNKNOWN);
233 
234     uint32_t index = 0;
235     int32_t ret = FindBufferIndex(index, shmem->mem);
236     CHECK_AND_RETURN_RET(ret == MSERR_OK, MSERR_UNKNOWN);
237 
238     auto obs = obs_.lock();
239     CHECK_AND_RETURN_RET_LOG(obs != nullptr, MSERR_UNKNOWN, "obs is nullptr");
240     MediaTrace::TraceBegin("Codec::OnInputBufferAvailable", FAKE_POINTER(this));
241     obs->OnInputBufferAvailable(index);
242     MediaTrace::TraceEnd("Codec::OnInputBufferAvailable", FAKE_POINTER(this));
243 
244     MEDIA_LOGD("OnInputBufferAvailable, index:%{public}u", index);
245     bufferList_[index]->owner_ = BufferWrapper::SERVER;
246     bufferList_[index]->gstBuffer_ = gst_buffer_ref(buffer);
247 
248     return MSERR_OK;
249 }
250 
FindBufferIndex(uint32_t & index,const std::shared_ptr<AVSharedMemory> & mem)251 int32_t SrcBytebufferImpl::FindBufferIndex(uint32_t &index, const std::shared_ptr<AVSharedMemory> &mem)
252 {
253     CHECK_AND_RETURN_RET(mem != nullptr, MSERR_UNKNOWN);
254 
255     index = 0;
256     for (auto it = bufferList_.begin(); it != bufferList_.end(); it++) {
257         if ((*it) != nullptr && (*it)->mem_ == mem.get()) {
258             break;
259         }
260         index++;
261     }
262 
263     if (index == bufferList_.size()) {
264         auto bufWrap = std::make_shared<BufferWrapper>(BufferWrapper::SERVER);
265         CHECK_AND_RETURN_RET(bufWrap != nullptr, MSERR_NO_MEMORY);
266         bufWrap->mem_ = mem.get();
267         bufferList_.push_back(bufWrap);
268     }
269 
270     return MSERR_OK;
271 }
272 } // namespace Media
273 } // namespace OHOS
274