2 Copyright 2012 Marten Richter, 2020 Chris Tallon
4 This file is part of VOMP.
6 VOMP is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 VOMP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with VOMP. If not, see <https://www.gnu.org/licenses/>.
21 #include "surfacevector.h"
23 #include "vdrresponsepacket.h"
27 #include "osdvector.h"
29 // The next section is activated, if the magick++ PictureReader is provided, it should be available for many POSIX platforms
30 #ifdef PICTURE_DECODER_MAGICK
31 #define MAGICKCORE_QUANTUM_DEPTH 16
32 #define MAGICKCORE_HDRI_ENABLE 0
35 using namespace Magick;
37 static const char* TAG = "OsdVector";
39 class MagickDecoder: public OsdVector::PictureDecoder
42 MagickDecoder(OsdVector::PictureReader* treader): OsdVector::PictureDecoder(treader) {pictInfValid = false;};
44 unsigned char* decodePicture(LoadIndex index, unsigned char* buffer, unsigned int length, bool freemem);
46 bool getDecodedPicture( struct OsdVector::PictureInfo& pict_inf);
48 void freeReference(void* ref);
51 OsdVector::PictureInfo pictInf;
55 unsigned char* MagickDecoder::decodePicture(LoadIndex index, unsigned char* buffer, unsigned int length, bool freemem)
57 if (pictInfValid) return buffer; // does support only one image at a Time;
60 Blob* imageblob = new Blob();
65 LogNT::getInstance()->debug("MagickDecoder", "decodePicture");
67 if (freemem) myblob.updateNoCopy(buffer, length, Blob::MallocAllocator);
68 else myblob.update(buffer, length);
70 magicimage.read(myblob);
72 magicimage.write(imageblob, "RGBA");
75 catch ( Exception& error_ )
77 LogNT::getInstance()->debug("MagickDecoder", "Libmagick: {}", error_.what());
79 LogNT::getInstance()->debug("MagickDecoder", "Libmagick: error mark2");
80 unsigned char* newbuffer = (unsigned char*) malloc(length);
81 memcpy(newbuffer, myblob.data(), length);
85 pictInf.reference = (void*) imageblob;
86 pictInf.width = magicimage.columns();
87 pictInf.height = magicimage.rows();
88 pictInf.image = imageblob->data();
89 pictInf.decoder = this;
90 pictInf.type = OsdVector::PictureInfo::RGBAMemBlock;
91 pictInf.lindex = index;
96 // I can handle everything, so the return value is always true
99 void MagickDecoder::freeReference(void* ref)
101 Blob* todelete = (Blob*) ref;
105 bool MagickDecoder::getDecodedPicture(struct OsdVector::PictureInfo& pict_inf)
107 if (!pictInfValid) return false;
110 pictInfValid = false;
117 OsdVector::OsdVector()
119 setlocale(LC_CTYPE, "C.UTF-8");
120 #ifdef PICTURE_DECODER_MAGICK
121 reader.addDecoder(new MagickDecoder(&reader));
123 MessageQueue::getInstance()->addReceiver(this);
126 OsdVector::~OsdVector()
128 MessageQueue::getInstance()->removeReceiver(this);
131 bool OsdVector::screenShot(const char* fileName)
133 //Do nothing, if no libmagick is there
134 #ifdef PICTURE_DECODER_MAGICK
136 getRealScreenSize(width, height);
137 size_t length = width * height * 4;
138 void* mem = malloc(length);
144 if (!screenShotInternal(mem, width, height, true))
146 LogNT::getInstance()->debug(TAG, "Screenshot failed!");
151 myblob.updateNoCopy(mem, length, Blob::MallocAllocator);
152 Image image(myblob, Geometry(width, height), 8, "RGBA");
153 image.write(fileName);
155 catch ( Exception& error_ )
157 LogNT::getInstance()->debug("MagickEncoder", "Libmagick: {}", error_.what());
166 Surface* OsdVector::createNewSurface()
168 return new SurfaceVector(this);
171 void OsdVector::Blank()
173 // do nothing? remove this one?
176 int OsdVector::restore()
178 // First clear the contents of all registered surfaces
179 surfaces_mutex.lock();
181 //Now go through all surfaces and clear them
182 for (auto& surface : surfaces)
184 surface.commands.clear();
185 surface.commands.reserve(2048);
188 //also clear all handles, they are now invalid, no need to release them
192 drawstyleHandles.clear();
193 drawstyleHandlesRefCounts.clear();
194 drawstyleHandles_lastit_valid = drawstyleHandlesRefCounts_lastit_valid = false;
198 loadindex_ref.clear();
199 tvmedias_load.clear();
200 tvmedias_load_inv.clear();
201 tvmedias_loaded.clear();
203 surfaces_mutex.unlock();
207 void OsdVector::drawSurfaces()
209 surfaces_mutex.lock();
210 std::list<SurfaceInfo*> todraw; //First figure out if a surfaces is below another surface
211 std::list<SurfaceInfo>::iterator itty1 = surfaces.begin();
213 while (itty1 != surfaces.end())
215 std::list<SurfaceInfo>::iterator itty2 = itty1;
219 while (itty2 != surfaces.end())
221 SurfaceInfo& ref1 = *itty1;
222 SurfaceInfo& ref2 = *itty2;
224 if (ref1.x >= ref2.x && ref1.y >= ref2.y
225 && (ref1.x + ref1.w) <= (ref2.x + ref2.w)
226 && (ref1.y + ref1.h) <= (ref2.y + ref2.h) )
235 if (!hidden) // we are not hidden, perfect
237 todraw.push_back(&(*itty1));
244 getScreenSize(swidth, sheight);
245 //Now go through all surfaces and draw them
246 std::list<SurfaceInfo*>::iterator curdraw = todraw.begin();
248 while (curdraw != todraw.end())
250 drawSetTrans(*(*curdraw));
251 std::vector<SVGCommand>::iterator commands = (*(*curdraw)).commands.begin();
252 std::vector<SVGCommand>::iterator end = (*(*curdraw)).commands.end();
254 while (commands != end)
256 // update any images loaded in the mean time
257 if ((*commands).instr == DrawImageLoading)
259 LoadIndex loadindex = (*commands).target.loadindex;
261 if (tvmedias_loaded.find(loadindex) != tvmedias_loaded.end())
263 (*commands).instr = DrawImage;
264 (*commands).target.image = tvmedias_loaded[loadindex];;
265 incImageRef((*commands).target.image);
266 removeLoadIndexRef(loadindex);
271 // Now check if the command is on screen!
272 if (!(*commands).Outside(0, 0, swidth, sheight))
274 executeDrawCommand(*commands);
283 surfaces_mutex.unlock();
286 void OsdVector::updateOrAddSurface(const SurfaceVector* surf, float x, float y, float height, float width, std::vector<SVGCommand>& commands)
288 std::lock_guard<std::mutex> lg(surfaces_mutex);
292 LogNT::getInstance()->trace(TAG, "updateOrAddSurface, surfaces.length {}", surfaces.size());
296 // First determine it is already in our system
297 for(si = surfaces.begin(); si != surfaces.end(); si++)
299 if (si->surface == surf)
301 // If the surface given (surf) is already in our surfaces vector, reset our SurfaceInfo->commands vector
302 decrementAllRefCounts(si->commands);
303 si->commands.clear();
308 // if not found, make a new SurfaceInfo
309 if (si == surfaces.end())
312 new_sc.surface = surf;
317 si = surfaces.insert(si, new_sc);
320 // update any images loaded in the mean time
322 for (SVGCommand& command : commands)
324 if (command.instr == DrawImageLoading)
326 LoadIndex loadindex = command.target.loadindex;
328 if (tvmedias_loaded.find(loadindex) != tvmedias_loaded.end())
330 command.instr = DrawImage;
331 command.target.image = tvmedias_loaded[loadindex];
332 incImageRef(command.target.image);
333 removeLoadIndexRef(loadindex);
338 si->commands = commands; // Copy surf->commands to our SurfaceInfo->commands
339 incrementAllRefCounts(si->commands);
341 cleanupOrphanedRefs();
344 LogNT::getInstance()->trace(TAG, "After UOAS:");
348 // OSDOVG-ROD-EXPERIMENT
349 LogNT::getInstance()->trace(TAG, "EXPERIMENT - call doRender");
353 void OsdVector::removeSurface(const SurfaceVector* surf)
355 std::lock_guard<std::mutex> lg(surfaces_mutex); // FIXME - Can block here on shutdown if a timer is fired just as the wrong time
356 LogNT::getInstance()->trace("OsdVector-348", "EXPERIMENT - removeSurface");
357 for (auto i = surfaces.begin(); i != surfaces.end(); i++)
359 if (i->surface == surf)
361 decrementAllRefCounts(i->commands);
369 void OsdVector::decrementAllRefCounts(std::vector<SVGCommand>& commands)
371 for (SVGCommand& command : commands)
373 VectorHandle handle = command.getHandle();
374 if (handle != 0) // command might not have a handle
375 decrementDrawStyleHandleRefCount(handle);
377 ImageIndex ii = command.getImageIndex();
378 if (ii) removeImageRef(ii);
380 LoadIndex li = command.getLoadIndex();
381 if (li) removeLoadIndexRef(li);
385 void OsdVector::incrementAllRefCounts(std::vector<SVGCommand>& commands)
387 for (SVGCommand& command : commands)
389 VectorHandle handle = command.getHandle();
390 if (handle != 0) // command might not have a handle
391 incrementDrawStyleHandleRefCount(handle);
393 ImageIndex ii = command.getImageIndex();
394 if (ii) incImageRef(ii);
396 LoadIndex li = command.getLoadIndex();
397 if (li) incLoadIndexRef(li);
401 void OsdVector::incImageRef(ImageIndex index)
403 if (images_ref.find(index) == images_ref.end())
405 images_ref[index] = 1;
413 void OsdVector::removeImageRef(const ImageIndex ref)
418 int OsdVector::getLoadIndexRef(LoadIndex index)
420 surfaces_mutex.lock();
422 if (loadindex_ref.find(index) == loadindex_ref.end())
428 return loadindex_ref[index];
431 surfaces_mutex.unlock();
434 void OsdVector::incLoadIndexRef(LoadIndex index)
436 if (loadindex_ref.find(index) == loadindex_ref.end())
438 loadindex_ref[index] = 1;
442 loadindex_ref[index]++;
446 void OsdVector::removeLoadIndexRef(const LoadIndex ref)
448 loadindex_ref[ref]--;
450 if (loadindex_ref[ref] == 0)
452 //now check, if it is already loaded
453 std::map<LoadIndex, ImageIndex>::iterator itty = tvmedias_loaded.find(ref);
455 if ( itty != tvmedias_loaded.end())
457 removeImageRef((*itty).second); // remove lock
460 tvmedias_loaded.erase(ref);
461 // LogNT::getInstance()->debug(TAG, "TVMedia removeLoadIndexRef {} {:#x}",tvmedias_load.size(),ref);
462 tvmedias_load.erase(tvmedias_load_inv[ref]);
463 tvmedias_load_inv.erase(ref);
465 reader.invalidateLoadIndex(ref);
469 void OsdVector::cleanupOrphanedRefs()
471 // Do some garbage collection
473 std::map<void*, ImageIndex>::iterator mitty = monobitmaps.begin();
475 while (mitty != monobitmaps.end())
477 std::map<ImageIndex, int>::iterator curitty = images_ref.find((*mitty).second);
478 int count = (*curitty).second;
482 ImageIndex ref = (*curitty).first;
483 monobitmaps.erase(mitty++);
484 images_ref.erase(curitty++);
485 destroyImageRef(ref);
490 /*map<string,ImageIndex>::iterator jitty=jpegs.begin();
491 while (jitty!=jpegs.end()) {
492 map<ImageIndex,int>::iterator curitty=images_ref.find((*jitty).second);
493 int count=(*curitty).second;
495 ImageIndex ref=(*curitty).first;
496 jpegs.erase(jitty++);
497 images_ref.erase(curitty++);
498 destroyImageRef(ref);
502 std::map<TVMediaInfo, ImageIndex>::iterator titty = tvmedias.begin();
504 while (titty != tvmedias.end())
506 std::map<ImageIndex, int>::iterator curitty = images_ref.find((*titty).second);
507 int count = (*curitty).second;
511 ImageIndex ref = (*curitty).first;
512 tvmedias.erase(titty++);
513 images_ref.erase(curitty);
514 destroyImageRef(ref);
520 std::map<TVMediaInfo, LoadIndex>::iterator litty = tvmedias_load.begin();
522 while (litty != tvmedias_load.end())
524 std::map<LoadIndex, int>::iterator curitty = loadindex_ref.find((*litty).second);
525 int count = (*curitty).second;
529 tvmedias_load_inv.erase((*litty).second);
530 tvmedias_loaded.erase((*litty).second);
531 tvmedias_load.erase(litty++);
536 std::list<ImageIndex>::iterator pitty = palettepics.begin();
538 while (pitty != palettepics.end())
540 std::map<ImageIndex, int>::iterator curitty = images_ref.find((*pitty));
541 int count = (*curitty).second;
545 ImageIndex ref = (*curitty).first;
546 palettepics.erase(pitty++);
547 images_ref.erase(curitty++);
548 destroyImageRef(ref);
553 std::map<ImageIndex, int>::iterator citty = images_ref.begin();
555 while (citty != images_ref.end())
557 int count = (*citty).second;
561 ImageIndex ref = (*citty).first;
562 images_ref.erase(citty++);
563 destroyImageRef(ref);
569 std::map<DrawStyle, VectorHandle>::iterator sitty = drawstyleHandles.begin();
571 while (sitty != drawstyleHandles.end())
573 std::map<VectorHandle, int>::iterator curitty = drawstyleHandlesRefCounts.find((*sitty).second);
574 int count = (*curitty).second;
578 VectorHandle ref = (*curitty).first;
579 drawstyleHandles.erase(sitty++);
580 drawstyleHandlesRefCounts.erase(curitty++);
581 drawstyleHandles_lastit_valid = drawstyleHandlesRefCounts_lastit_valid = false;
582 destroyDrawStyleHandle(ref);
590 int OsdVector::getImageRef(ImageIndex index)
592 surfaces_mutex.lock();
594 if (images_ref.find(index) == images_ref.end())
600 return images_ref[index];
603 surfaces_mutex.unlock();
606 void OsdVector::incrementDrawStyleHandleRefCount(VectorHandle index)
608 if (!drawstyleHandlesRefCounts_lastit_valid || (drawstyleHandlesRefCounts_lastit->first != index))
610 drawstyleHandlesRefCounts_lastit = drawstyleHandlesRefCounts.find(index);
611 if (drawstyleHandlesRefCounts_lastit == drawstyleHandlesRefCounts.end())
613 drawstyleHandlesRefCounts_lastit = drawstyleHandlesRefCounts.insert(std::pair<VectorHandle, int>(index, 0)).first;
617 drawstyleHandlesRefCounts_lastit->second++;
618 drawstyleHandlesRefCounts_lastit_valid = true;
621 void OsdVector::decrementDrawStyleHandleRefCount(VectorHandle index)
623 if (!drawstyleHandlesRefCounts_lastit_valid || (drawstyleHandlesRefCounts_lastit->first != index))
625 drawstyleHandlesRefCounts_lastit_valid = false;
626 drawstyleHandlesRefCounts_lastit = drawstyleHandlesRefCounts.find(index);
629 if (drawstyleHandlesRefCounts_lastit != drawstyleHandlesRefCounts.end())
631 drawstyleHandlesRefCounts_lastit_valid = true;
632 drawstyleHandlesRefCounts_lastit->second--;
636 VectorHandle OsdVector::getDrawStyleHandle(const DrawStyle& c)
638 surfaces_mutex.lock();
639 VectorHandle style_handle = 0;
645 if (!drawstyleHandles_lastit_valid || (drawstyleHandles_lastit->first != c))
647 drawstyleHandles_lastit_valid = false;
648 drawstyleHandles_lastit = drawstyleHandles.find(c);
651 if (drawstyleHandles_lastit == drawstyleHandles.end())
653 surfaces_mutex.unlock();
654 style_handle = createDrawStyleHandle(c);
655 surfaces_mutex.lock();
656 drawstyleHandles_lastit = drawstyleHandles.insert(std::pair<DrawStyle, VectorHandle>(c, style_handle)).first;
660 style_handle = drawstyleHandles_lastit->second;
662 //Now check if the handle is valid
663 if (!drawstyleHandlesRefCounts_lastit_valid || (*drawstyleHandlesRefCounts_lastit).first != style_handle)
665 drawstyleHandlesRefCounts_lastit_valid = false;
666 drawstyleHandlesRefCounts_lastit = drawstyleHandlesRefCounts.find(style_handle);
669 if (drawstyleHandlesRefCounts_lastit == drawstyleHandlesRefCounts.end())
671 //invalid handle recreate
672 surfaces_mutex.unlock();
673 style_handle = createDrawStyleHandle(c);
674 surfaces_mutex.lock();
675 drawstyleHandles_lastit->second = style_handle;
677 else drawstyleHandlesRefCounts_lastit_valid = true;
680 drawstyleHandles_lastit_valid = true;
681 incrementDrawStyleHandleRefCount(style_handle);
682 surfaces_mutex.unlock();
687 void OsdVector::dumpStyles()
691 std::map<DrawStyle, VectorHandle>::iterator i;
692 for(i = drawstyleHandles.begin(); i != drawstyleHandles.end(); i++)
694 const DrawStyle* test = &(i->first);
695 LogNT::getInstance()->debug(TAG, "DumpStyles: {} {}", (void*)test , i->second);
698 std::map<VectorHandle, int>::iterator i2;
699 for (i2 = drawstyleHandlesRefCounts.begin(); i2 != drawstyleHandlesRefCounts.end(); i2++)
701 LogNT::getInstance()->debug(TAG, "DumpStylesRef: {} {}", i2->first, i2->second);
706 LoadIndex OsdVector::getTVMediaRef(TVMediaInfo& tvmedia, ImageIndex& image)
708 ImageIndex image_handle = 0;
709 LoadIndex loadindex = 0;
710 surfaces_mutex.lock();
712 if (tvmedias.find(tvmedia) == tvmedias.end())
714 loadindex = loadTVMedia(tvmedia);
718 image_handle = tvmedias[tvmedia];
720 if (images_ref.find(image_handle) == images_ref.end())
722 //invalid handle recreate
723 loadindex = loadTVMedia(tvmedia);
728 incImageRef(image_handle);
732 /*tvmedias[tvmedia]=createTVMedia(tvmedia,width,height);
733 incImageRef(image_handle);*/
734 image = image_handle;
735 surfaces_mutex.unlock();
739 LoadIndex OsdVector::loadTVMedia(TVMediaInfo& tvmedia)
743 if (tvmedias_load.find(tvmedia) == tvmedias_load.end())
745 switch (tvmedia.getType())
748 index = VDR::getInstance()->loadTVMediaRecThumb(tvmedia);
753 index = ((long long) tvmedia.getPrimaryID()) << 32LL;
754 reader.addStaticImage(tvmedia.getPrimaryID());
758 index = VDR::getInstance()->loadTVMediaEventThumb(tvmedia);
762 index = VDR::getInstance()->loadChannelLogo(tvmedia);
766 index = VDR::getInstance()->loadTVMedia(tvmedia);
770 if (tvmedia.getType() != 4 && tvmedia.getStaticFallback() > -1)
772 reader.informFallback(index, tvmedia.getStaticFallback());
775 tvmedias_load[tvmedia] = index;
776 tvmedias_load_inv[index] = tvmedia;
780 index = tvmedias_load[tvmedia];
783 incLoadIndexRef(index);
788 void OsdVector::informPicture(LoadIndex index, ImageIndex imageIndex)
790 //Beware for thread safety
791 ImageIndex image_index = 0;
793 LogNT::getInstance()->debug(TAG, "TVMedia Picture for request id {:#x} arrived {:#x}", index, imageIndex);
794 surfaces_mutex.lock();
795 TVMediaInfo tvmedia = tvmedias_load_inv[index];
799 std::map<LoadIndex, int>::iterator itty = loadindex_ref.find(index);
800 image_index = tvmedias[tvmedia] = imageIndex;
801 tvmedias_loaded[index] = image_index;
803 if (itty == loadindex_ref.end() || (*itty).second == 0)
805 // we do not want the picture anymore . Really...
806 // fill images_ref in to not irritate the garbage collector
807 if (images_ref.find(image_index) == images_ref.end())
809 images_ref[image_index] = 0;
814 incImageRef(image_index); // hold one index until all loadings refs are gone;
818 surfaces_mutex.unlock();
821 void OsdVector::processMessage(Message* m)
825 case Message::NEW_PICTURE:
827 //LogNT::getInstance()->debug(TAG, "TVMedia NEW_PICTURE");
828 informPicture(m->tag, reinterpret_cast<ImageIndex>(m->data));
831 case Message::NEW_PICTURE_STATIC:
833 //LogNT::getInstance()->debug(TAG, "TVMedia NEW_PICTURE {:#x} {:#x}", m->tag, m->parameter);
834 informPicture(static_cast<unsigned long long>(m->tag) << 32LL, reinterpret_cast<ImageIndex>(m->data));
841 ImageIndex OsdVector::getJpegRef(const char* fileName, int *width,int *height)
843 ImageIndex image_handle=0;
844 if (jpegs.find(fileName)==jpegs.end())
846 image_handle=jpegs[fileName]=createJpeg(fileName,width,height);
848 image_handle=jpegs[fileName];
851 if (images_ref.find(image_handle)==images_ref.end()) {
852 //invalid handle recreate
853 image_handle=jpegs[fileName]=createJpeg(fileName,width,height);
856 incImageRef(image_handle);
861 ImageIndex OsdVector::getMonoBitmapRef(void* base, int width, int height)
863 ImageIndex image_handle;
864 surfaces_mutex.lock();
866 if (monobitmaps.find(base) == monobitmaps.end())
868 surfaces_mutex.unlock();
869 image_handle = createMonoBitmap(base, width, height);
870 surfaces_mutex.lock();
871 monobitmaps[base] = image_handle;
875 image_handle = monobitmaps[base];
877 if (images_ref.find(image_handle) == images_ref.end())
879 //invalid handle recreate
880 surfaces_mutex.unlock();
881 image_handle = createMonoBitmap(base, width, height);
882 surfaces_mutex.lock();
883 monobitmaps[base] = image_handle;
887 incImageRef(image_handle);
888 surfaces_mutex.unlock();
892 ImageIndex OsdVector::getImagePalette(int width, int height, const unsigned char* image_data, const unsigned int* palette_data)
894 ImageIndex image_handle;
895 image_handle = createImagePalette(width, height, image_data, palette_data);
896 surfaces_mutex.lock();
897 palettepics.push_back(image_handle);
898 incImageRef(image_handle);
899 surfaces_mutex.unlock();
903 /// PictureReader Class
905 OsdVector::PictureReader::~PictureReader()
907 decoders_lock.lock();
909 while (decoders.size())
911 PictureDecoder* dec = decoders.front();
912 decoders.pop_front();
916 decoders_lock.unlock();
919 void OsdVector::PictureReader::init()
924 void OsdVector::PictureReader::shutdown()
929 void OsdVector::PictureReader::addDecoder(PictureDecoder* decoder)
931 decoders_lock.lock();
933 decoders.push_front(decoder);
934 decoders_lock.unlock();
937 void OsdVector::PictureReader::removeDecoder(PictureDecoder* decoder)
939 decoders_lock.lock();
940 std::list<PictureDecoder*>::iterator itty = decoders.begin();
942 while (itty != decoders.end())
944 if ((*itty) == decoder)
946 decoders.erase(itty);
953 LogNT::getInstance()->debug(TAG, "removeDecoder");
956 decoders_lock.unlock();
959 void OsdVector::PictureReader::threadMethod()
961 OsdVector* osdvector = dynamic_cast<OsdVector*>(Osd::getInstance());
962 LogNT::getInstance()->debug(TAG, "TVMedia Start Picture Reader");
966 if (!threadIsActive())
968 LogNT::getInstance()->debug(TAG, "TVMedia End Picture Reader");
978 decoders_lock.lock();
979 std::list<PictureDecoder*>::iterator itty = decoders.begin();
981 while (itty != decoders.end())
983 if ((*itty)->getDecodedPicture(pictinf))
986 osdvector->createPicture(pictinf);
992 if (processReceivedPictures())
997 decoders_lock.unlock();
1000 //LogNT::getInstance()->debug(TAG, "TVMedia Sleep Picture Reader");
1002 struct timespec target_time;
1003 getClockRealTime(&target_time);
1005 target_time.tv_nsec += 1000000LL * 10;
1007 if (target_time.tv_nsec > 999999999)
1009 target_time.tv_nsec -= 1000000000L;
1010 target_time.tv_sec += 1;
1014 threadWaitForSignalTimed(&target_time);
1016 //LogNT::getInstance()->debug(TAG, "TVMedia Sleep end Picture Reader");
1020 void OsdVector::PictureReader::invalidateLoadIndex(LoadIndex index)
1022 pict_lock_incoming.lock();
1023 invalid_loadindex.insert(index);
1024 pict_lock_incoming.unlock();
1027 void OsdVector::PictureReader::informFallback(LoadIndex index, int fallback)
1029 pict_lock_incoming.lock();
1030 inform_fallback[index] = fallback;
1031 pict_lock_incoming.unlock();
1034 void OsdVector::PictureReader::receivePicture(VDR_ResponsePacket* vresp)
1036 pict_lock_incoming.lock();
1037 pict_incoming.push(vresp);
1038 pict_lock_incoming.unlock();
1043 void OsdVector::PictureReader::addStaticImage(unsigned int id)
1045 pict_lock_incoming.lock();
1046 pict_incoming_static.push(id);
1047 invalid_loadindex.erase(((long long) id) << 32LL);
1048 pict_lock_incoming.unlock();
1054 #pragma warning(disable : 4703)
1057 bool OsdVector::PictureReader::processReceivedPictures()
1059 bool decoded = false;
1061 pict_lock_incoming.lock();
1063 if (pict_incoming.size())
1065 VDR_ResponsePacket* vresp = pict_incoming.front();
1066 pict_incoming.pop();
1067 std::set<LoadIndex>::iterator setpos = invalid_loadindex.find(vresp->getStreamID());
1069 if (setpos != invalid_loadindex.end())
1072 invalid_loadindex.erase(setpos);
1075 pict_lock_incoming.unlock();
1077 if (!valid) // we do not want it anymore skip it;
1083 // LogNT::getInstance()->debug(TAG, "TVMedia Pictures arrived VDR {:#x} {} {}",
1084 // vresp->getStreamID(),vresp->getUserDataLength(),vresp->getFlag());
1085 bool decode = false;
1090 if (vresp->getFlag() != 2)
1092 userdata = vresp->getUserData();
1093 length = vresp->getUserDataLength();
1100 pict_lock_incoming.lock();
1102 if (inform_fallback.find(vresp->getStreamID()) != inform_fallback.end())
1104 fallback = inform_fallback[vresp->getStreamID()];
1107 pict_lock_incoming.unlock();
1109 if (fallback >= 0 && ((OsdVector*)Osd::getInstance())->getStaticImageData(fallback, &userdata, &length))
1118 std::list<PictureDecoder*>::iterator itty = decoders.begin();
1120 while (itty != decoders.end())
1122 userdata = (*itty)->decodePicture(vresp->getStreamID(), userdata, length, freed);
1133 if (!decoded && userdata && freed)
1139 pict_lock_incoming.lock();
1140 inform_fallback.erase(vresp->getStreamID());
1141 pict_lock_incoming.unlock();
1142 //else osd->informPicture(vresp->getStreamID(), 0);
1145 else if (pict_incoming_static.size())
1147 unsigned int static_id = pict_incoming_static.front();
1148 pict_incoming_static.pop();
1149 std::set<LoadIndex>::iterator setpos = invalid_loadindex.find(((long long) static_id) << 32LL);
1151 if (setpos != invalid_loadindex.end())
1154 invalid_loadindex.erase(setpos);
1157 pict_lock_incoming.unlock();
1159 if (!valid) // we do not want it anymore skip it;
1167 if (((OsdVector*)Osd::getInstance())->getStaticImageData(static_id, &userdata, &length))
1169 std::list<PictureDecoder*>::iterator itty = decoders.begin();
1171 while (itty != decoders.end())
1173 if (!(*itty)->decodePicture(((long long) static_id) << 32LL, userdata, length, false))
1185 pict_lock_incoming.unlock();
1188 if (pict_incoming.size() || pict_incoming_static.size()) return true;