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