59ae83689f2c24a12cd3463e850c5cd439f212cc
[platform/core/multimedia/esplusplayer.git] / src / esplusplayer / include_internal / esplayer / decoded_pkt_list.h
1 //
2 // @ Copyright [2019] <S/W Platform, Visual Display, Samsung Electronics>
3 //
4
5 #ifndef __PLUSPLAYER_SRC_ESPLAYER_DECODED_PACKET_LIST_H__
6 #define __PLUSPLAYER_SRC_ESPLAYER_DECODED_PACKET_LIST_H__
7
8 #include <tbm_surface.h>
9
10 #include <algorithm>
11 #include <functional>
12 #include <list>
13 #include <memory>
14 #include <gst/gst.h>
15
16 #include "core/utils/plusplayer_log.h"
17 #include "plusplayer/types/buffer.h"
18
19 namespace {
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;
26   }
27   if(packet->surface_data) {
28     tbm_surface_destroy(static_cast<tbm_surface_h>(packet->surface_data));
29     packet->surface_data = nullptr;
30   }
31 }
32 }  // namespace
33
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;
41 };
42 struct CmaBufferInfo {
43   void* tbm_surf = nullptr;
44   bool tbm_is_free = true;
45   bool destroy_flag = false;
46 };
47
48 class AbstractDecodedPacketList : public DecodedPacketManagerInterface {
49  public:
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*)>>;
55
56  public:
57   virtual bool TryToAdd(esplusplayer_decoded_video_packet* packet) override {
58     if (packet == nullptr) {
59       LOG_ERROR("packet is nullptr");
60       return false;
61     }
62     std::unique_lock<std::mutex> lk(mtx_);
63     auto pkt_ptr = DecodedPacketPtr(
64         packet, [this](esplusplayer_decoded_video_packet* pkt) {
65           DecodedPacketDeleter(pkt);
66           delete pkt;
67         });
68     if (IsAvailableInternal() == false) {
69       LOG_ERROR("not available to add a packet");
70       return false;
71     }
72     // LOG_DEBUG("packet[%p] added", packet);
73     list_.emplace_back(std::move(pkt_ptr));
74     return true;
75   }
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;
81       return false;
82     });
83   }
84   virtual void Clear() override {
85     std::unique_lock<std::mutex> lk(mtx_);
86     LOG_DEBUG("all packets are cleared");
87     list_.clear();
88   }
89
90   virtual void GetFreeTbmSurface(void** ptr, bool is_scale_change) override {
91     return;
92   }
93
94  protected:
95   const std::list<DecodedPacketPtr>& GetList() { return list_; }
96
97  protected:
98   virtual bool IsAvailableInternal() = 0;
99   virtual void DecodedPacketDeleter(
100       esplusplayer_decoded_video_packet* packet) = 0;
101
102  protected:
103   std::mutex mtx_;
104   std::list<DecodedPacketPtr> list_;
105 };
106
107 class DecodedReferencePacketList : public AbstractDecodedPacketList {
108  public:
109   explicit DecodedReferencePacketList() { LOG_DEBUG("created"); }
110   virtual ~DecodedReferencePacketList() { LOG_DEBUG("destroyed"); }
111
112  protected:
113   virtual bool IsAvailableInternal() override {
114     if (GetList().size() > kMaxAvailableSize_) return false;
115     return true;
116   }
117   virtual void DecodedPacketDeleter(
118       esplusplayer_decoded_video_packet* packet) override {
119     ::DecodedPacketDeleter(packet);
120   }
121
122  private:
123   const std::uint32_t kMaxAvailableSize_ = 5;
124 };
125
126 class DecodedCopiedPacketList : public AbstractDecodedPacketList {
127  public:
128   explicit DecodedCopiedPacketList() { LOG_DEBUG("created"); }
129   virtual ~DecodedCopiedPacketList() { LOG_DEBUG("destroyed"); }
130
131  protected:
132   virtual bool IsAvailableInternal() override { return true; }
133   virtual void DecodedPacketDeleter(
134       esplusplayer_decoded_video_packet* packet) override {
135     ::DecodedPacketDeleter(packet);
136   }
137 };
138
139 class DecodedScaledPacketList : public AbstractDecodedPacketList {
140  public:
141   explicit DecodedScaledPacketList() { LOG_DEBUG("created"); }
142   virtual ~DecodedScaledPacketList() { LOG_DEBUG("destroyed"); }
143   virtual void GetFreeTbmSurface(void** ptr, bool is_scale_change) {
144     std::unique_lock<std::mutex> lk(mtx_);
145     if (is_scale_change) {
146       for (std::vector<CmaBufferInfo>::iterator it = tbm_mgr_.begin();
147            it != tbm_mgr_.end();) {
148         if (it->tbm_is_free == true) {
149           LOG_ERROR("scale size changed, destroy the free tbm %p",
150                     it->tbm_surf);
151           tbm_surface_destroy(static_cast<tbm_surface_h>(it->tbm_surf));
152           it = tbm_mgr_.erase(it);
153         } else {
154           LOG_ERROR("scale size changed, using tbm will be destroy later%p",
155                     it->tbm_surf);
156           it->destroy_flag = true;
157           it++;
158         }
159       }
160       *ptr = nullptr;
161     } else {
162       auto tbm_is_free = [](const CmaBufferInfo& item) -> bool {
163         return item.tbm_is_free == true;
164       };
165       auto target = std::find_if(tbm_mgr_.begin(), tbm_mgr_.end(), tbm_is_free);
166       if (target != tbm_mgr_.end()) {
167         *ptr = target->tbm_surf;
168       }
169     }
170     return;
171   }
172
173   virtual bool TryToAdd(esplusplayer_decoded_video_packet* packet) override {
174     if (packet == nullptr) {
175       LOG_ERROR("packet is nullptr");
176       return false;
177     }
178     std::unique_lock<std::mutex> lk(mtx_);
179     auto pkt_ptr = DecodedPacketPtr(
180         packet, [this](esplusplayer_decoded_video_packet* pkt) {
181           DecodedPacketDeleter(pkt);
182           delete pkt;
183         });
184     if (IsAvailableInternal() == false) {
185       LOG_ERROR("not available to add a packet");
186       return false;
187     }
188     // traverse tbm_mgr to find the same tbm surf,if find, change that,if not,
189     // new one and add to vector.
190     void* tbm_ptr = packet->surface_data;
191     auto has_tbm = [tbm_ptr](const CmaBufferInfo& item) -> bool {
192       return item.tbm_surf == tbm_ptr;
193     };
194     auto target = std::find_if(tbm_mgr_.begin(), tbm_mgr_.end(), has_tbm);
195     if (target == tbm_mgr_.end()) {
196       CmaBufferInfo tmp_tbm_buffer;
197       tmp_tbm_buffer.tbm_surf = packet->surface_data;
198       tmp_tbm_buffer.tbm_is_free = false;
199       tmp_tbm_buffer.destroy_flag = false;
200       tbm_mgr_.push_back(tmp_tbm_buffer);
201       LOG_ERROR("add tbm surface %p to list", tmp_tbm_buffer.tbm_surf);
202     } else {
203       target->tbm_is_free = false;
204     }
205     list_.emplace_back(std::move(pkt_ptr));
206     return true;
207   }
208
209   virtual void Remove(esplusplayer_decoded_video_packet* packet) override {
210     if (packet == nullptr) return;
211     std::unique_lock<std::mutex> lk(mtx_);
212     // LOG_ERROR("Remove pkt %p ", packet->surface_data);
213     // before remove packet, set the tbm surf free.
214     void* tbm_ptr = packet->surface_data;
215     auto has_tbm = [tbm_ptr](const CmaBufferInfo& item) -> bool {
216       return item.tbm_surf == tbm_ptr;
217     };
218     auto target = std::find_if(tbm_mgr_.begin(), tbm_mgr_.end(), has_tbm);
219     if (target != tbm_mgr_.end()) {
220       if (target->destroy_flag == true) {
221         LOG_ERROR("destroy tbm surface %p", target->tbm_surf);
222         tbm_surface_destroy(static_cast<tbm_surface_h>(target->tbm_surf));
223         tbm_mgr_.erase(target);
224       } else {
225         target->tbm_is_free = true;
226       }
227     }
228     list_.remove_if([&packet](const DecodedPacketPtr& cur) {
229       if (cur.get() == packet) return true;
230       return false;
231     });
232   }
233
234   virtual void Clear() override {
235     std::unique_lock<std::mutex> lk(mtx_);
236     LOG_DEBUG("all packets are cleared");
237     list_.clear();
238     for (auto& iter : tbm_mgr_) {
239       LOG_ERROR("destroy tbm buffer in list %p", iter.tbm_surf);
240       tbm_surface_destroy(static_cast<tbm_surface_h>(iter.tbm_surf));
241     }
242     std::vector<CmaBufferInfo> tmp;
243     tbm_mgr_.swap(tmp);
244   }
245
246  protected:
247   virtual bool IsAvailableInternal() override {
248     if (GetList().size() > kMaxAvailableSize_) return false;
249     return true;
250   }
251
252   virtual void DecodedPacketDeleter(
253       esplusplayer_decoded_video_packet* packet) override {
254     // redesign, when pkt list is full, which means new tbm ptr can't add, so
255     // destroy it after create in trackrender.
256     if (GetList().size() > kMaxAvailableSize_) {
257       if (packet == nullptr || packet->surface_data == nullptr) return;
258       // only destroy the tbm surface new created but not added in tbm list
259       void* tbm_ptr = packet->surface_data;
260       auto has_tbm = [tbm_ptr](const CmaBufferInfo& item) -> bool {
261         return item.tbm_surf == tbm_ptr;
262       };
263       auto target = std::find_if(tbm_mgr_.begin(), tbm_mgr_.end(), has_tbm);
264       if (target == tbm_mgr_.end()) {
265         LOG_ERROR("tbm_surface_destroy[%p] deleted", packet->surface_data);
266         tbm_surface_destroy(static_cast<tbm_surface_h>(packet->surface_data));
267         packet->surface_data = NULL;
268       }
269     }
270   }
271
272  private:
273   const std::uint32_t kMaxAvailableSize_ = 5;
274   std::vector<CmaBufferInfo> tbm_mgr_;
275 };
276 }  // namespace plusplayer
277
278 #endif  // __PLUSPLAYER_SRC_ESPLAYER_DECODED_PACKET_LIST_H__