• 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 "sink_bytebuffer_impl.h"
17 #include "gst_shmem_memory.h"
18 #include "media_log.h"
19 #include "scope_guard.h"
20 
21 namespace {
22     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "SinkBytebufferImpl"};
23 }
24 
25 namespace OHOS {
26 namespace Media {
SinkBytebufferImpl()27 SinkBytebufferImpl::SinkBytebufferImpl()
28 {
29 }
30 
~SinkBytebufferImpl()31 SinkBytebufferImpl::~SinkBytebufferImpl()
32 {
33     std::unique_lock<std::mutex> lock(mutex_);
34     bufferList_.clear();
35     if (sink_ != nullptr) {
36         gst_object_unref(sink_);
37         sink_ = nullptr;
38     }
39 }
40 
Init()41 int32_t SinkBytebufferImpl::Init()
42 {
43     sink_ = GST_ELEMENT_CAST(gst_object_ref(gst_element_factory_make("sharedmemsink", "sink")));
44     CHECK_AND_RETURN_RET(sink_ != nullptr, MSERR_UNKNOWN);
45     gst_base_sink_set_async_enabled(GST_BASE_SINK(sink_), FALSE);
46     return MSERR_OK;
47 }
48 
Configure(std::shared_ptr<ProcessorConfig> config)49 int32_t SinkBytebufferImpl::Configure(std::shared_ptr<ProcessorConfig> config)
50 {
51     CHECK_AND_RETURN_RET(sink_ != nullptr && config->caps_ != nullptr, MSERR_UNKNOWN);
52 
53     g_object_set(G_OBJECT(sink_), "mem-size", static_cast<guint>(config->bufferSize_), nullptr);
54     g_object_set(G_OBJECT(sink_), "caps", config->caps_, nullptr);
55     (void)CapsToFormat(config->caps_, bufferFormat_);
56 
57     GstMemSinkCallbacks sinkCallbacks = { EosCb, nullptr, NewSampleCb };
58     gst_mem_sink_set_callback(GST_MEM_SINK(sink_), &sinkCallbacks, this, nullptr);
59 
60     return MSERR_OK;
61 }
62 
Flush()63 int32_t SinkBytebufferImpl::Flush()
64 {
65     std::unique_lock<std::mutex> lock(mutex_);
66     for (auto it = bufferList_.begin(); it != bufferList_.end(); it++) {
67         if ((*it)->owner_ != BufferWrapper::DOWNSTREAM) {
68             (*it)->owner_ = BufferWrapper::DOWNSTREAM;
69             if ((*it)->gstBuffer_ != nullptr) {
70                 gst_buffer_unref((*it)->gstBuffer_);
71                 (*it)->gstBuffer_ = nullptr;
72             }
73         }
74     }
75     isFirstFrame_ = true;
76     isEos_ = false;
77     return MSERR_OK;
78 }
79 
GetOutputBuffer(uint32_t index)80 std::shared_ptr<AVSharedMemory> SinkBytebufferImpl::GetOutputBuffer(uint32_t index)
81 {
82     std::unique_lock<std::mutex> lock(mutex_);
83     CHECK_AND_RETURN_RET(index <= bufferList_.size(), nullptr);
84     CHECK_AND_RETURN_RET(bufferList_[index]->owner_ == BufferWrapper::SERVER, nullptr);
85 
86     GstMemory *memory = gst_buffer_peek_memory(bufferList_[index]->gstBuffer_, 0);
87     CHECK_AND_RETURN_RET(memory != nullptr, nullptr);
88 
89     GstShMemMemory *shmem = reinterpret_cast<GstShMemMemory *>(memory);
90     bufferList_[index]->owner_ = BufferWrapper::APP;
91     return shmem->mem;
92 }
93 
ReleaseOutputBuffer(uint32_t index,bool render)94 int32_t SinkBytebufferImpl::ReleaseOutputBuffer(uint32_t index, bool render)
95 {
96     (void)render;
97     std::unique_lock<std::mutex> lock(mutex_);
98     CHECK_AND_RETURN_RET(index < bufferList_.size(), MSERR_INVALID_OPERATION);
99     CHECK_AND_RETURN_RET(bufferList_[index]->owner_ == BufferWrapper::APP, MSERR_INVALID_OPERATION);
100     CHECK_AND_RETURN_RET(bufferList_[index]->gstBuffer_ != nullptr, MSERR_UNKNOWN);
101 
102     bufferList_[index]->owner_ = BufferWrapper::DOWNSTREAM;
103     gst_buffer_unref(bufferList_[index]->gstBuffer_);
104     bufferList_[index]->gstBuffer_ = nullptr;
105 
106     return MSERR_OK;
107 }
108 
SetCallback(const std::weak_ptr<IAVCodecEngineObs> & obs)109 int32_t SinkBytebufferImpl::SetCallback(const std::weak_ptr<IAVCodecEngineObs> &obs)
110 {
111     std::unique_lock<std::mutex> lock(mutex_);
112     obs_ = obs;
113     return MSERR_OK;
114 }
115 
IsEos()116 bool SinkBytebufferImpl::IsEos()
117 {
118     return isEos_;
119 }
120 
NewSampleCb(GstMemSink * memSink,GstBuffer * sample,gpointer userData)121 GstFlowReturn SinkBytebufferImpl::NewSampleCb(GstMemSink *memSink, GstBuffer *sample, gpointer userData)
122 {
123     (void)memSink;
124     auto impl = static_cast<SinkBytebufferImpl *>(userData);
125     CHECK_AND_RETURN_RET(impl != nullptr, GST_FLOW_ERROR);
126     std::unique_lock<std::mutex> lock(impl->mutex_);
127     CHECK_AND_RETURN_RET(impl->HandleNewSampleCb(sample) == MSERR_OK, GST_FLOW_ERROR);
128     return GST_FLOW_OK;
129 }
130 
EosCb(GstMemSink * memSink,gpointer userData)131 void SinkBytebufferImpl::EosCb(GstMemSink *memSink, gpointer userData)
132 {
133     (void)memSink;
134     MEDIA_LOGI("EOS reached");
135     auto impl = static_cast<SinkBytebufferImpl *>(userData);
136     CHECK_AND_RETURN(impl != nullptr);
137     std::unique_lock<std::mutex> lock(impl->mutex_);
138     impl->isEos_ = true;
139 
140     auto obs = impl->obs_.lock();
141     CHECK_AND_RETURN(obs != nullptr);
142 
143     AVCodecBufferInfo info;
144     constexpr uint32_t invalidIndex = 1000;
145     obs->OnOutputBufferAvailable(invalidIndex, info, AVCODEC_BUFFER_FLAG_EOS);
146 }
147 
HandleNewSampleCb(GstBuffer * buffer)148 int32_t SinkBytebufferImpl::HandleNewSampleCb(GstBuffer *buffer)
149 {
150     CHECK_AND_RETURN_RET(buffer != nullptr, MSERR_UNKNOWN);
151     ON_SCOPE_EXIT(0) { gst_buffer_unref(buffer); };
152 
153     GstMemory *memory = gst_buffer_peek_memory(buffer, 0);
154     CHECK_AND_RETURN_RET(memory != nullptr, MSERR_UNKNOWN);
155     GstShMemMemory *shmem = reinterpret_cast<GstShMemMemory *>(memory);
156     CHECK_AND_RETURN_RET(shmem->mem != nullptr, MSERR_UNKNOWN);
157 
158     uint32_t index = 0;
159     CHECK_AND_RETURN_RET(FindBufferIndex(index, shmem->mem) == MSERR_OK, MSERR_UNKNOWN);
160 
161     auto obs = obs_.lock();
162     CHECK_AND_RETURN_RET_LOG(obs != nullptr, MSERR_UNKNOWN, "obs is nullptr");
163 
164     if (isFirstFrame_) {
165         isFirstFrame_ = false;
166         obs->OnOutputFormatChanged(bufferFormat_);
167     }
168 
169     isEos_ = false;
170 
171     GstMapInfo map = GST_MAP_INFO_INIT;
172     CHECK_AND_RETURN_RET(gst_buffer_map(buffer, &map, GST_MAP_READ) == TRUE, MSERR_UNKNOWN);
173 
174     AVCodecBufferInfo info;
175     info.offset = 0;
176     if (map.size >= INT32_MAX) {
177         MEDIA_LOGE("Invalid size");
178         gst_buffer_unmap(buffer, &map);
179         return MSERR_UNKNOWN;
180     }
181     info.size = static_cast<int32_t>(map.size);
182     constexpr uint64_t nsToUs = 1000;
183     info.presentationTimeUs = static_cast<int64_t>(GST_BUFFER_PTS(buffer) / nsToUs);
184     obs->OnOutputBufferAvailable(index, info, AVCODEC_BUFFER_FLAG_NONE);
185 
186     MEDIA_LOGD("OutputBufferAvailable, index:%{public}d", index);
187     gst_buffer_unmap(buffer, &map);
188     bufferList_[index]->owner_ = BufferWrapper::SERVER;
189     bufferList_[index]->gstBuffer_ = gst_buffer_ref(buffer);
190 
191     return MSERR_OK;
192 }
193 
FindBufferIndex(uint32_t & index,std::shared_ptr<AVSharedMemory> mem)194 int32_t SinkBytebufferImpl::FindBufferIndex(uint32_t &index, std::shared_ptr<AVSharedMemory> mem)
195 {
196     CHECK_AND_RETURN_RET(mem != nullptr, MSERR_UNKNOWN);
197 
198     index = 0;
199     for (auto it = bufferList_.begin(); it != bufferList_.end(); it++) {
200         if ((*it) != nullptr && (*it)->mem_ == mem.get()) {
201             break;
202         }
203         index++;
204     }
205 
206     if (index == bufferList_.size()) {
207         auto bufWrap = std::make_shared<BufferWrapper>(BufferWrapper::SERVER);
208         CHECK_AND_RETURN_RET(bufWrap != nullptr, MSERR_NO_MEMORY);
209         bufWrap->mem_ = mem.get();
210         bufferList_.push_back(bufWrap);
211     }
212 
213     return MSERR_OK;
214 }
215 } // namespace Media
216 } // namespace OHOS
217