2 // @ Copyright [2019] <S/W Platform, Visual Display, Samsung Electronics>
5 #ifndef __PLUSPLAYER_SRC_ESPLAYER_DECODED_PACKET_LIST_H__
6 #define __PLUSPLAYER_SRC_ESPLAYER_DECODED_PACKET_LIST_H__
8 #include <tbm_surface.h>
16 #include "core/utils/plusplayer_log.h"
17 #include "plusplayer/types/buffer.h"
20 void DecodedPacketDeleter(esplusplayer_decoded_video_packet* packet) {
21 if (packet == nullptr) return;
22 // LOG_DEBUG("packet[%p] deleted", packet);
23 if(packet->private_data) { // hw dec
24 gst_buffer_unref((GstBuffer *)packet->private_data);
25 packet->private_data = nullptr;
27 if(packet->surface_data) {
28 tbm_surface_destroy(static_cast<tbm_surface_h>(packet->surface_data));
29 packet->surface_data = nullptr;
34 namespace plusplayer {
35 struct DecodedPacketManagerInterface {
36 virtual ~DecodedPacketManagerInterface() = default;
37 virtual bool TryToAdd(esplusplayer_decoded_video_packet* packet) = 0;
38 virtual void Remove(esplusplayer_decoded_video_packet* packet) = 0;
39 virtual void Clear() = 0;
40 virtual void GetFreeTbmSurface(void** ptr, bool is_scale_change) = 0;
42 struct CmaBufferInfo {
43 void* tbm_surf = nullptr;
44 bool tbm_is_free = true;
45 bool destroy_flag = false;
48 class AbstractDecodedPacketList : public DecodedPacketManagerInterface {
50 explicit AbstractDecodedPacketList() = default;
51 virtual ~AbstractDecodedPacketList() = default;
52 using DecodedPacketPtr =
53 std::unique_ptr<esplusplayer_decoded_video_packet,
54 std::function<void(esplusplayer_decoded_video_packet*)>>;
57 virtual bool TryToAdd(esplusplayer_decoded_video_packet* packet) override {
58 if (packet == nullptr) {
59 LOG_ERROR("packet is nullptr");
62 std::unique_lock<std::mutex> lk(mtx_);
63 auto pkt_ptr = DecodedPacketPtr(
64 packet, [this](esplusplayer_decoded_video_packet* pkt) {
65 DecodedPacketDeleter(pkt);
68 if (IsAvailableInternal() == false) {
69 LOG_ERROR("not available to add a packet");
72 // LOG_DEBUG("packet[%p] added", packet);
73 list_.emplace_back(std::move(pkt_ptr));
76 virtual void Remove(esplusplayer_decoded_video_packet* packet) override {
77 if (packet == nullptr) return;
78 std::unique_lock<std::mutex> lk(mtx_);
79 list_.remove_if([&packet](const DecodedPacketPtr& cur) {
80 if (cur.get() == packet) return true;
84 virtual void Clear() override {
85 std::unique_lock<std::mutex> lk(mtx_);
86 LOG_DEBUG("all packets are cleared");
90 virtual void GetFreeTbmSurface(void** ptr, bool is_scale_change) override {
95 const std::list<DecodedPacketPtr>& GetList() { return list_; }
98 virtual bool IsAvailableInternal() = 0;
99 virtual void DecodedPacketDeleter(
100 esplusplayer_decoded_video_packet* packet) = 0;
104 std::list<DecodedPacketPtr> list_;
107 class DecodedReferencePacketList : public AbstractDecodedPacketList {
109 explicit DecodedReferencePacketList() { LOG_DEBUG("created"); }
110 virtual ~DecodedReferencePacketList() { LOG_DEBUG("destroyed"); }
113 virtual bool IsAvailableInternal() override {
114 if (GetList().size() > kMaxAvailableSize_) return false;
117 virtual void DecodedPacketDeleter(
118 esplusplayer_decoded_video_packet* packet) override {
119 ::DecodedPacketDeleter(packet);
123 const std::uint32_t kMaxAvailableSize_ = 5;
126 class DecodedCopiedPacketList : public AbstractDecodedPacketList {
128 explicit DecodedCopiedPacketList() { LOG_DEBUG("created"); }
129 virtual ~DecodedCopiedPacketList() { LOG_DEBUG("destroyed"); }
132 virtual bool IsAvailableInternal() override { return true; }
133 virtual void DecodedPacketDeleter(
134 esplusplayer_decoded_video_packet* packet) override {
135 ::DecodedPacketDeleter(packet);
139 class ManualDecodedCopiedPacketList : public DecodedPacketManagerInterface {
141 using Handler = std::function<bool(esplusplayer_decoded_video_packet*)>;
142 explicit ManualDecodedCopiedPacketList(Handler handler) : handler_(handler) {
143 LOG_DEBUG("created");
145 virtual ~ManualDecodedCopiedPacketList() { LOG_DEBUG("destroyed"); }
148 virtual bool TryToAdd(esplusplayer_decoded_video_packet* packet) {
151 virtual void Clear() {}
152 virtual void GetFreeTbmSurface(void** ptr, bool is_scale_change) {}
154 virtual void Remove(esplusplayer_decoded_video_packet* packet) {
155 if (handler_(packet) == false) {
156 LOG_ERROR("packet return failed");
163 class DecodedScaledPacketList : public AbstractDecodedPacketList {
165 explicit DecodedScaledPacketList() { LOG_DEBUG("created"); }
166 virtual ~DecodedScaledPacketList() { LOG_DEBUG("destroyed"); }
167 virtual void GetFreeTbmSurface(void** ptr, bool is_scale_change) {
168 std::unique_lock<std::mutex> lk(mtx_);
169 if (is_scale_change) {
170 for (std::vector<CmaBufferInfo>::iterator it = tbm_mgr_.begin();
171 it != tbm_mgr_.end();) {
172 if (it->tbm_is_free == true) {
173 LOG_ERROR("scale size changed, destroy the free tbm %p",
175 tbm_surface_destroy(static_cast<tbm_surface_h>(it->tbm_surf));
176 it = tbm_mgr_.erase(it);
178 LOG_ERROR("scale size changed, using tbm will be destroy later%p",
180 it->destroy_flag = true;
186 auto tbm_is_free = [](const CmaBufferInfo& item) -> bool {
187 return item.tbm_is_free == true;
189 auto target = std::find_if(tbm_mgr_.begin(), tbm_mgr_.end(), tbm_is_free);
190 if (target != tbm_mgr_.end()) {
191 *ptr = target->tbm_surf;
197 virtual bool TryToAdd(esplusplayer_decoded_video_packet* packet) override {
198 if (packet == nullptr) {
199 LOG_ERROR("packet is nullptr");
202 std::unique_lock<std::mutex> lk(mtx_);
203 auto pkt_ptr = DecodedPacketPtr(
204 packet, [this](esplusplayer_decoded_video_packet* pkt) {
205 DecodedPacketDeleter(pkt);
208 if (IsAvailableInternal() == false) {
209 LOG_ERROR("not available to add a packet");
212 // traverse tbm_mgr to find the same tbm surf,if find, change that,if not,
213 // new one and add to vector.
214 void* tbm_ptr = packet->surface_data;
215 auto has_tbm = [tbm_ptr](const CmaBufferInfo& item) -> bool {
216 return item.tbm_surf == tbm_ptr;
218 auto target = std::find_if(tbm_mgr_.begin(), tbm_mgr_.end(), has_tbm);
219 if (target == tbm_mgr_.end()) {
220 CmaBufferInfo tmp_tbm_buffer;
221 tmp_tbm_buffer.tbm_surf = packet->surface_data;
222 tmp_tbm_buffer.tbm_is_free = false;
223 tmp_tbm_buffer.destroy_flag = false;
224 tbm_mgr_.push_back(tmp_tbm_buffer);
225 LOG_ERROR("add tbm surface %p to list", tmp_tbm_buffer.tbm_surf);
227 target->tbm_is_free = false;
229 list_.emplace_back(std::move(pkt_ptr));
233 virtual void Remove(esplusplayer_decoded_video_packet* packet) override {
234 if (packet == nullptr) return;
235 std::unique_lock<std::mutex> lk(mtx_);
236 // LOG_ERROR("Remove pkt %p ", packet->surface_data);
237 // before remove packet, set the tbm surf free.
238 void* tbm_ptr = packet->surface_data;
239 auto has_tbm = [tbm_ptr](const CmaBufferInfo& item) -> bool {
240 return item.tbm_surf == tbm_ptr;
242 auto target = std::find_if(tbm_mgr_.begin(), tbm_mgr_.end(), has_tbm);
243 if (target != tbm_mgr_.end()) {
244 if (target->destroy_flag == true) {
245 LOG_ERROR("destroy tbm surface %p", target->tbm_surf);
246 tbm_surface_destroy(static_cast<tbm_surface_h>(target->tbm_surf));
247 tbm_mgr_.erase(target);
249 target->tbm_is_free = true;
252 list_.remove_if([&packet](const DecodedPacketPtr& cur) {
253 if (cur.get() == packet) return true;
258 virtual void Clear() override {
259 std::unique_lock<std::mutex> lk(mtx_);
260 LOG_DEBUG("all packets are cleared");
262 for (auto& iter : tbm_mgr_) {
263 LOG_ERROR("destroy tbm buffer in list %p", iter.tbm_surf);
264 tbm_surface_destroy(static_cast<tbm_surface_h>(iter.tbm_surf));
266 std::vector<CmaBufferInfo> tmp;
271 virtual bool IsAvailableInternal() override {
272 if (GetList().size() > kMaxAvailableSize_) return false;
276 virtual void DecodedPacketDeleter(
277 esplusplayer_decoded_video_packet* packet) override {
278 // redesign, when pkt list is full, which means new tbm ptr can't add, so
279 // destroy it after create in trackrender.
280 if (GetList().size() > kMaxAvailableSize_) {
281 if (packet == nullptr || packet->surface_data == nullptr) return;
282 // only destroy the tbm surface new created but not added in tbm list
283 void* tbm_ptr = packet->surface_data;
284 auto has_tbm = [tbm_ptr](const CmaBufferInfo& item) -> bool {
285 return item.tbm_surf == tbm_ptr;
287 auto target = std::find_if(tbm_mgr_.begin(), tbm_mgr_.end(), has_tbm);
288 if (target == tbm_mgr_.end()) {
289 LOG_ERROR("tbm_surface_destroy[%p] deleted", packet->surface_data);
290 tbm_surface_destroy(static_cast<tbm_surface_h>(packet->surface_data));
291 packet->surface_data = NULL;
297 const std::uint32_t kMaxAvailableSize_ = 5;
298 std::vector<CmaBufferInfo> tbm_mgr_;
300 } // namespace plusplayer
302 #endif // __PLUSPLAYER_SRC_ESPLAYER_DECODED_PACKET_LIST_H__