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 DecodedScaledPacketList : public AbstractDecodedPacketList {
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",
151 tbm_surface_destroy(static_cast<tbm_surface_h>(it->tbm_surf));
152 it = tbm_mgr_.erase(it);
154 LOG_ERROR("scale size changed, using tbm will be destroy later%p",
156 it->destroy_flag = true;
162 auto tbm_is_free = [](const CmaBufferInfo& item) -> bool {
163 return item.tbm_is_free == true;
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;
173 virtual bool TryToAdd(esplusplayer_decoded_video_packet* packet) override {
174 if (packet == nullptr) {
175 LOG_ERROR("packet is nullptr");
178 std::unique_lock<std::mutex> lk(mtx_);
179 auto pkt_ptr = DecodedPacketPtr(
180 packet, [this](esplusplayer_decoded_video_packet* pkt) {
181 DecodedPacketDeleter(pkt);
184 if (IsAvailableInternal() == false) {
185 LOG_ERROR("not available to add a packet");
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;
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);
203 target->tbm_is_free = false;
205 list_.emplace_back(std::move(pkt_ptr));
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;
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);
225 target->tbm_is_free = true;
228 list_.remove_if([&packet](const DecodedPacketPtr& cur) {
229 if (cur.get() == packet) return true;
234 virtual void Clear() override {
235 std::unique_lock<std::mutex> lk(mtx_);
236 LOG_DEBUG("all packets are cleared");
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));
242 std::vector<CmaBufferInfo> tmp;
247 virtual bool IsAvailableInternal() override {
248 if (GetList().size() > kMaxAvailableSize_) return false;
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;
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;
273 const std::uint32_t kMaxAvailableSize_ = 5;
274 std::vector<CmaBufferInfo> tbm_mgr_;
276 } // namespace plusplayer
278 #endif // __PLUSPLAYER_SRC_ESPLAYER_DECODED_PACKET_LIST_H__