2 Copyright 2012 Marten Richter
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, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "osdvector.h"
22 #include "surfacevector.h"
24 #include "vdrresponsepacket.h"
28 // The next section is activated, if the magick++ PictureReader is provided, it should be available for many POSIX platforms
29 #ifdef PICTURE_DECODER_MAGICK
32 using namespace Magick;
34 class MagickDecoder: public OsdVector::PictureDecoder {
36 MagickDecoder(OsdVector::PictureReader* treader): OsdVector::PictureDecoder(treader) {pictInfValid=false;};
38 unsigned char *decodePicture(LoadIndex index, unsigned char * buffer, unsigned int length, bool freemem);
40 bool getDecodedPicture( struct OsdVector::PictureInfo& pict_inf);
42 void freeReference(void * ref);
45 OsdVector::PictureInfo pictInf;
49 unsigned char * MagickDecoder::decodePicture(LoadIndex index, unsigned char * buffer, unsigned int length, bool freemem)
51 if (pictInfValid) return buffer; // does support only one image at a Time;
53 Blob *imageblob = new Blob();
56 Log::getInstance()->log("MagickDecoder", Log::DEBUG, "decodePicture");
58 if (freemem) myblob.updateNoCopy(buffer,length,Blob::MallocAllocator);
59 else myblob.update(buffer,length);
60 magicimage.read(myblob);
62 magicimage.write(imageblob,"RGBA");
64 }catch( Exception &error_ )
66 Log::getInstance()->log("MagickDecoder", Log::DEBUG, "Libmagick: %s",error_.what());
68 Log::getInstance()->log("MagickDecoder", Log::DEBUG, "Libmagick: error mark2");
69 unsigned char* newbuffer=(unsigned char*) malloc(length);
70 memcpy(newbuffer,myblob.data(),length);
73 pictInf.reference = (void*) imageblob;
74 pictInf.width = magicimage.columns();
75 pictInf.height = magicimage.rows();
76 pictInf.image = imageblob->data();
77 pictInf.decoder = this;
78 pictInf.type = OsdVector::PictureInfo::RGBAMemBlock;
79 pictInf.lindex = index;
84 // I can handle everything, so the return value is always true
87 void MagickDecoder::freeReference(void * ref)
89 Blob *todelete = (Blob*) ref;
93 bool MagickDecoder::getDecodedPicture(struct OsdVector::PictureInfo& pict_inf)
95 if (!pictInfValid) return false;
104 OsdVector::OsdVector()
106 setlocale(LC_CTYPE,"C.UTF-8");
107 #ifdef PICTURE_DECODER_MAGICK
108 reader.addDecoder(new MagickDecoder(&reader));
111 for (int i=0;i<256;i++) {
112 byte_char_width[i]=0.f;
114 styles_lastit_valid=styles_ref_lastit_valid=false;
118 OsdVector::~OsdVector()
123 int OsdVector::getFD()
128 void OsdVector::screenShot(const char* fileName)
130 //Do nothing, if no libmagick is there
131 #ifdef PICTURE_DECODER_MAGICK
133 getRealScreenSize(width,height);
134 size_t length=width*height*4;
135 void *mem=malloc(length);
139 if (!screenShot(mem,width,height,true)) {
140 Log::getInstance()->log("OsdVector", Log::DEBUG, "Screenshot failed!");
144 myblob.updateNoCopy(mem,length,Blob::MallocAllocator);
145 Image image(myblob,Geometry(width,height),8,"RGBA");
146 image.write(fileName);
147 }catch( Exception &error_ )
149 Log::getInstance()->log("MagickEncoder", Log::DEBUG, "Libmagick: %s",error_.what());
156 Surface * OsdVector::createNewSurface()
158 return new SurfaceVector(this);
162 void OsdVector::Blank()
164 // do nothing? remove this one?
167 int OsdVector::restore()
169 // First clear the contents of all registered surfaces
170 surfaces_mutex.Lock();
172 //Now go through all surfaces and draw them
173 list<SurfaceCommands>::iterator curdraw=scommands.begin();
174 while (curdraw!=scommands.end()) {
175 (*curdraw).commands.clear();
176 (*curdraw).commands.reserve(2048);
179 //also clear all handles, they are now invalid, no need to release them
185 styles_lastit_valid=styles_ref_lastit_valid=false;
189 loadindex_ref.clear();
190 tvmedias_load.clear();
191 tvmedias_load_inv.clear();
192 tvmedias_loaded.clear();
194 surfaces_mutex.Unlock();
198 void OsdVector::drawSurfaces()
200 surfaces_mutex.Lock();
201 list<SurfaceCommands*> todraw; //First figure out if a surfaces is below another surface
202 list<SurfaceCommands>::iterator itty1=scommands.begin();
203 while (itty1!=scommands.end()) {
204 list<SurfaceCommands>::iterator itty2=itty1;
207 while (itty2!=scommands.end()) {
208 SurfaceCommands & ref1=*itty1;
209 SurfaceCommands & ref2=*itty2;
210 if (ref1.x>=ref2.x && ref1.y>=ref2.y
211 && (ref1.x+ref1.w) <= (ref2.x+ref2.w)
212 && (ref1.y+ref1.h) <= (ref2.y+ref2.h) ) {
218 if (!hidden) { // we are not hidden, perfect
219 todraw.push_back(&(*itty1));
224 getScreenSize(swidth,sheight);
225 //Now go through all surfaces and draw them
226 list<SurfaceCommands*>::iterator curdraw=todraw.begin();
227 while (curdraw!=todraw.end()) {
228 drawSetTrans(*(*curdraw));
229 std::vector<SVGCommand>::iterator commands=(*(*curdraw)).commands.begin();
230 std::vector<SVGCommand>::iterator end=(*(*curdraw)).commands.end();
231 while (commands!=end) {
232 // update any images loaded in the mean time
233 if ((*commands).instr==DrawImageLoading) {
234 LoadIndex loadindex=(*commands).target.loadindex;
235 if (tvmedias_loaded.find(loadindex)!=tvmedias_loaded.end()) {
236 (*commands).instr=DrawImage;
237 (*commands).target.image=tvmedias_loaded[loadindex];;
238 incImageRef((*commands).target.image);
239 removeLoadIndexRef(loadindex);
243 // Now check if the command is on screen!
244 if (!(*commands).Outside(0,0,swidth,sheight)) {
245 executeDrawCommand(*commands);
252 surfaces_mutex.Unlock();
255 void OsdVector::updateOrAddSurface(const SurfaceVector *surf,float x,float y,float height,float width,
256 std::vector<SVGCommand>& commands)
258 surfaces_mutex.Lock();
259 //First determine it is already in our system
260 list<SurfaceCommands>::iterator itty=scommands.begin();
261 while (itty!=scommands.end()) {
262 if ((*itty).surf==surf) {
263 //decrease the references
264 dereferenceSVGCommand((*itty).commands);
270 if (itty==scommands.end()) {
271 SurfaceCommands new_sc;
277 itty=scommands.insert(itty,new_sc);
279 // update any images loaded in the mean time
280 std::vector<SVGCommand>::iterator ilitty=commands.begin();
282 while (ilitty!=commands.end())
284 if ((*ilitty).instr==DrawImageLoading) {
285 LoadIndex loadindex=(*ilitty).target.loadindex;
286 if (tvmedias_loaded.find(loadindex)!=tvmedias_loaded.end()) {
288 (*ilitty).instr=DrawImage;
289 (*ilitty).target.image=tvmedias_loaded[loadindex];
290 incImageRef((*ilitty).target.image);
291 removeLoadIndexRef(loadindex);
298 // then clear and copy
299 (*itty).commands.clear();
300 (*itty).commands=commands;
301 //increase the references
302 referenceSVGCommand((*itty).commands);
303 cleanupOrphanedRefs();
305 surfaces_mutex.Unlock();
308 void OsdVector::removeSurface(const SurfaceVector *surf)
310 surfaces_mutex.Lock();
311 //First determine it is already in our system
312 list<SurfaceCommands>::iterator itty=scommands.begin();
313 while (itty!=scommands.end()) {
314 if ((*itty).surf==surf) {
315 dereferenceSVGCommand((*itty).commands);
316 (*itty).commands.clear();
317 scommands.erase(itty);
322 surfaces_mutex.Unlock();
326 void OsdVector::dereferenceSVGCommand(std::vector<SVGCommand>& commands )
329 std::vector<SVGCommand>::iterator sitty = commands.begin();
330 while (sitty != commands.end()) {
331 removeStyleRef((*sitty).getRef());
332 ImageIndex ii = (*sitty).getImageIndex();
333 if (ii) removeImageRef(ii);
334 LoadIndex li=(*sitty).getLoadIndex();
335 if (li) removeLoadIndexRef(li);
340 void OsdVector::referenceSVGCommand(std::vector<SVGCommand>& commands )
342 std::vector<SVGCommand>::iterator sitty=commands.begin();
343 while (sitty!=commands.end())
345 incStyleRef((*sitty).getRef());
346 ImageIndex ii=(*sitty).getImageIndex();
347 if (ii) incImageRef(ii);
348 LoadIndex li=(*sitty).getLoadIndex();
349 if (li) incLoadIndexRef(li);
355 void OsdVector::incImageRef(ImageIndex index)
357 if (images_ref.find(index)==images_ref.end()) {
364 void OsdVector::removeImageRef(const ImageIndex ref)
369 int OsdVector::getLoadIndexRef(LoadIndex index)
371 surfaces_mutex.Lock();
372 if (loadindex_ref.find(index)==loadindex_ref.end()) {
375 return loadindex_ref[index];
377 surfaces_mutex.Unlock();
380 void OsdVector::incLoadIndexRef(LoadIndex index)
382 if (loadindex_ref.find(index)==loadindex_ref.end()) {
383 loadindex_ref[index]=1;
385 loadindex_ref[index]++;
389 void OsdVector::removeLoadIndexRef(const LoadIndex ref)
391 loadindex_ref[ref]--;
392 if (loadindex_ref[ref]==0) {
393 //now check, if it is already loaded
394 map<LoadIndex,ImageIndex>::iterator itty=tvmedias_loaded.find(ref);
395 if ( itty != tvmedias_loaded.end()) {
396 removeImageRef((*itty).second); // remove lock
398 tvmedias_loaded.erase(ref);
399 // Log::getInstance()->log("OsdVector", Log::DEBUG, "TVMedia removeLoadIndexRef %d %llx",tvmedias_load.size(),ref);
400 tvmedias_load.erase(tvmedias_load_inv[ref]);
401 tvmedias_load_inv.erase(ref);
403 reader.invalidateLoadIndex(ref);
411 void OsdVector::cleanupOrphanedRefs()
412 { // Do some garbage collection
414 map<void *,ImageIndex>::iterator mitty=monobitmaps.begin();
415 while (mitty!=monobitmaps.end()) {
416 map<ImageIndex,int>::iterator curitty=images_ref.find((*mitty).second);
417 int count=(*curitty).second;
419 ImageIndex ref=(*curitty).first;
420 monobitmaps.erase(mitty++);
421 images_ref.erase(curitty++);
422 destroyImageRef(ref);
426 /*map<string,ImageIndex>::iterator jitty=jpegs.begin();
427 while (jitty!=jpegs.end()) {
428 map<ImageIndex,int>::iterator curitty=images_ref.find((*jitty).second);
429 int count=(*curitty).second;
431 ImageIndex ref=(*curitty).first;
432 jpegs.erase(jitty++);
433 images_ref.erase(curitty++);
434 destroyImageRef(ref);
438 map<TVMediaInfo,ImageIndex>::iterator titty=tvmedias.begin();
439 while (titty!=tvmedias.end()) {
440 map<ImageIndex,int>::iterator curitty=images_ref.find((*titty).second);
441 int count=(*curitty).second;
443 ImageIndex ref=(*curitty).first;
444 tvmedias.erase(titty++);
445 images_ref.erase(curitty);
446 destroyImageRef(ref);
451 map<TVMediaInfo,LoadIndex>::iterator litty=tvmedias_load.begin();
452 while (litty!=tvmedias_load.end()) {
453 map<LoadIndex,int>::iterator curitty=loadindex_ref.find((*litty).second);
454 int count=(*curitty).second;
456 tvmedias_load_inv.erase((*litty).second);
457 tvmedias_loaded.erase((*litty).second);
458 tvmedias_load.erase(litty++);
462 list<ImageIndex>::iterator pitty=palettepics.begin();
463 while (pitty!=palettepics.end()) {
464 map<ImageIndex,int>::iterator curitty=images_ref.find((*pitty));
465 int count=(*curitty).second;
467 ImageIndex ref=(*curitty).first;
468 palettepics.erase(pitty++);
469 images_ref.erase(curitty++);
470 destroyImageRef(ref);
474 map<ImageIndex,int>::iterator citty=images_ref.begin();
475 while (citty!=images_ref.end()) {
476 int count=(*citty).second;
478 ImageIndex ref=(*citty).first;
479 images_ref.erase(citty++);
480 destroyImageRef(ref);
485 map<DrawStyle, VectorHandle>::iterator sitty = styles.begin();
486 while (sitty!=styles.end()) {
487 map<VectorHandle, int>::iterator curitty = styles_ref.find((*sitty).second);
488 int count=(*curitty).second;
490 VectorHandle ref = (*curitty).first;
491 styles.erase(sitty++);
492 styles_ref.erase(curitty++);
493 styles_lastit_valid=styles_ref_lastit_valid=false;
494 destroyStyleRef(ref);
502 int OsdVector::getImageRef(ImageIndex index)
504 surfaces_mutex.Lock();
505 if (images_ref.find(index)==images_ref.end()) {
508 return images_ref[index];
510 surfaces_mutex.Unlock();
513 void OsdVector::incStyleRef(VectorHandle index)
515 if (!styles_ref_lastit_valid || (*styles_ref_lastit).first!=index) {
516 styles_ref_lastit_valid=false;
517 styles_ref_lastit=styles_ref.find(index);
519 if (styles_ref_lastit==styles_ref.end()) {
520 styles_ref_lastit = styles_ref.insert(std::pair<VectorHandle, int>(index, 1)).first;
522 (*styles_ref_lastit).second++;
524 styles_ref_lastit_valid=true;
527 void OsdVector::removeStyleRef(VectorHandle index)
529 if (!styles_ref_lastit_valid || (*styles_ref_lastit).first!=index) {
530 styles_ref_lastit_valid=false;
531 styles_ref_lastit=styles_ref.find(index);
533 if (styles_ref_lastit!=styles_ref.end()) {
534 styles_ref_lastit_valid=true;
535 (*styles_ref_lastit).second--;
539 VectorHandle OsdVector::getStyleRef(const DrawStyle &c)
541 surfaces_mutex.Lock();
542 VectorHandle style_handle = 0;
543 if (!styles_lastit_valid || (*styles_lastit).first!=c) {
544 styles_lastit_valid=false;
545 styles_lastit=styles.find(c);
548 if (styles_lastit==styles.end())
550 surfaces_mutex.Unlock();
551 style_handle=createStyleRef(c);
552 surfaces_mutex.Lock();
553 styles_lastit = styles.insert(std::pair<DrawStyle, VectorHandle>(c, style_handle)).first;
556 style_handle=(*styles_lastit).second;
557 //Now check if the handle is valid
558 if (!styles_ref_lastit_valid || (*styles_ref_lastit).first!=style_handle) {
559 styles_ref_lastit_valid=false;
560 styles_ref_lastit=styles_ref.find(style_handle);
563 if (styles_ref_lastit==styles_ref.end()) {
564 //invalid handle recreate
565 surfaces_mutex.Unlock();
566 style_handle=createStyleRef(c);
567 surfaces_mutex.Lock();
568 (*styles_lastit).second=style_handle;
569 } else styles_ref_lastit_valid=true;
571 styles_lastit_valid=true;
572 incStyleRef(style_handle);
573 surfaces_mutex.Unlock();
579 int OsdVector::getStyleRef(VectorHandle index)
581 if (!styles_ref_lastit_valid || (*styles_ref_lastit).first!=index) {
582 styles_ref_lastit_valid=false;
583 styles_ref_lastit=styles_ref.find(index);
585 if (styles_ref_lastit==styles_ref.end()) {
588 styles_ref_lastit_valid=true;
589 return (*styles_ref_lastit).second;
593 LoadIndex OsdVector::getTVMediaRef(TVMediaInfo& tvmedia, ImageIndex& image)
595 ImageIndex image_handle=0;
596 LoadIndex loadindex=0;
597 surfaces_mutex.Lock();
598 if (tvmedias.find(tvmedia)==tvmedias.end())
600 loadindex=loadTVMedia(tvmedia);
602 image_handle=tvmedias[tvmedia];
603 if (images_ref.find(image_handle)==images_ref.end()) {
604 //invalid handle recreate
605 loadindex=loadTVMedia(tvmedia);
608 incImageRef(image_handle);
611 /*tvmedias[tvmedia]=createTVMedia(tvmedia,width,height);
612 incImageRef(image_handle);*/
614 surfaces_mutex.Unlock();
618 LoadIndex OsdVector::loadTVMedia(TVMediaInfo& tvmedia)
622 if (tvmedias_load.find(tvmedia)==tvmedias_load.end())
624 switch (tvmedia.getType()) {
626 index=VDR::getInstance()->loadTVMediaRecThumb(tvmedia);
629 index = ((long long) tvmedia.getPrimaryID()) << 32LL;
630 reader.addStaticImage(tvmedia.getPrimaryID());
633 index=VDR::getInstance()->loadTVMediaEventThumb(tvmedia);
636 index=VDR::getInstance()->loadChannelLogo(tvmedia);
639 index=VDR::getInstance()->loadTVMedia(tvmedia);
642 if (tvmedia.getType()!=4 && tvmedia.getStaticFallback()>-1) {
643 reader.informFallback(index,tvmedia.getStaticFallback());
646 tvmedias_load[tvmedia]=index;
647 tvmedias_load_inv[index]=tvmedia;
649 index=tvmedias_load[tvmedia];
652 incLoadIndexRef(index);
659 void OsdVector::informPicture(LoadIndex index, ImageIndex imageIndex)
661 //Beware for thread safety
662 ImageIndex image_index=0;
664 Log::getInstance()->log("OsdVector", Log::DEBUG, "TVMedia Picture for request id %llx arrived %x",index, imageIndex);
665 surfaces_mutex.Lock();
666 TVMediaInfo tvmedia=tvmedias_load_inv[index];
668 map<LoadIndex,int>::iterator itty=loadindex_ref.find(index);
669 image_index=tvmedias[tvmedia]=imageIndex;
670 tvmedias_loaded[index]=image_index;
672 if (itty==loadindex_ref.end() || (*itty).second == 0) {
673 // we do not want the picture anymore . Really...
674 // fill images_ref in to not irritate the garbage collector
675 if (images_ref.find(image_index)==images_ref.end()) {
676 images_ref[image_index]=0;
679 incImageRef(image_index); // hold one index until all loadings refs are gone;
682 surfaces_mutex.Unlock();
691 ImageIndex OsdVector::getJpegRef(const char* fileName, int *width,int *height)
693 ImageIndex image_handle=0;
694 if (jpegs.find(fileName)==jpegs.end())
696 image_handle=jpegs[fileName]=createJpeg(fileName,width,height);
698 image_handle=jpegs[fileName];
701 if (images_ref.find(image_handle)==images_ref.end()) {
702 //invalid handle recreate
703 image_handle=jpegs[fileName]=createJpeg(fileName,width,height);
706 incImageRef(image_handle);
711 ImageIndex OsdVector::getMonoBitmapRef(void *base,int width,int height)
713 ImageIndex image_handle;
714 surfaces_mutex.Lock();
715 if (monobitmaps.find(base)==monobitmaps.end())
717 surfaces_mutex.Unlock();
718 image_handle=createMonoBitmap(base,width,height);
719 surfaces_mutex.Lock();
720 monobitmaps[base]=image_handle;
722 image_handle=monobitmaps[base];
723 if (images_ref.find(image_handle)==images_ref.end()) {
724 //invalid handle recreate
725 surfaces_mutex.Unlock();
726 image_handle=createMonoBitmap(base,width,height);
727 surfaces_mutex.Lock();
728 monobitmaps[base]=image_handle;
731 incImageRef(image_handle);
732 surfaces_mutex.Unlock();
736 ImageIndex OsdVector::getImagePalette(int width,int height,const unsigned char *image_data,const unsigned int*palette_data)
738 ImageIndex image_handle;
739 image_handle=createImagePalette(width,height,image_data,palette_data);
740 surfaces_mutex.Lock();
741 palettepics.push_back(image_handle);
742 incImageRef(image_handle);
743 surfaces_mutex.Unlock();
747 OsdVector::PictureReader::~PictureReader()
749 decoders_lock.Lock();
750 while ( decoders.size()) {
751 PictureDecoder* dec=decoders.front();
752 decoders.pop_front();
756 decoders_lock.Unlock();
759 void OsdVector::PictureReader::init()
764 void OsdVector::PictureReader::shutdown()
771 void OsdVector::PictureReader::addDecoder(PictureDecoder* decoder)
773 decoders_lock.Lock();
775 decoders.push_front(decoder);
776 decoders_lock.Unlock();
779 void OsdVector::PictureReader::removeDecoder(PictureDecoder* decoder)
781 decoders_lock.Lock();
782 std::list<PictureDecoder*>::iterator itty=decoders.begin();
783 while (itty!=decoders.end()) {
784 if ((*itty) == decoder)
786 decoders.erase(itty);
791 Log::getInstance()->log("OsdVector", Log::DEBUG, "removeDecoder");
794 decoders_lock.Unlock();
797 void OsdVector::PictureReader::threadMethod()
799 OsdVector *osdvector = dynamic_cast<OsdVector*>(Osd::getInstance());
800 Log::getInstance()->log("OsdVector", Log::DEBUG, "TVMedia Start Picture Reader");
802 if (!threadIsActive()) {
803 Log::getInstance()->log("OsdVector", Log::DEBUG, "TVMedia End Picture Reader");
812 decoders_lock.Lock();
813 std::list<PictureDecoder*>::iterator itty=decoders.begin();
815 while (itty!=decoders.end()) {
816 if ((*itty)->getDecodedPicture(pictinf)) {
818 osdvector->createPicture(pictinf);
823 if (processReceivedPictures())
828 decoders_lock.Unlock();
830 //Log::getInstance()->log("OsdVector", Log::DEBUG, "TVMedia Sleep Picture Reader");
832 struct timespec target_time;
833 getClockRealTime(&target_time);
835 target_time.tv_nsec+=1000000LL*10;
836 if (target_time.tv_nsec>999999999) {
837 target_time.tv_nsec-=1000000000L;
838 target_time.tv_sec+=1;
841 threadWaitForSignalTimed(&target_time);
843 //Log::getInstance()->log("OsdVector", Log::DEBUG, "TVMedia Sleep end Picture Reader");
847 void OsdVector::PictureReader::threadPostStopCleanup()
852 void OsdVector::PictureReader::invalidateLoadIndex(LoadIndex index)
854 pict_lock_incoming.Lock();
855 invalid_loadindex.insert(index);
856 pict_lock_incoming.Unlock();
859 void OsdVector::PictureReader::informFallback(LoadIndex index, int fallback)
861 pict_lock_incoming.Lock();
862 inform_fallback[index]=fallback;
863 pict_lock_incoming.Unlock();
866 void OsdVector::PictureReader::receivePicture(VDR_ResponsePacket *vresp)
868 pict_lock_incoming.Lock();
869 pict_incoming.push(vresp);
870 pict_lock_incoming.Unlock();
875 void OsdVector::PictureReader::addStaticImage(unsigned int id)
877 pict_lock_incoming.Lock();
878 pict_incoming_static.push(id);
879 invalid_loadindex.erase(((long long) id) << 32LL);
880 pict_lock_incoming.Unlock();
884 bool OsdVector::PictureReader::processReceivedPictures()
886 bool decoded = false;
888 pict_lock_incoming.Lock();
889 if (pict_incoming.size()) {
890 VDR_ResponsePacket *vresp=pict_incoming.front();
892 set<LoadIndex>::iterator setpos = invalid_loadindex.find(vresp->getStreamID());
893 if (setpos != invalid_loadindex.end()) {
895 invalid_loadindex.erase(setpos);
897 pict_lock_incoming.Unlock();
898 if (!valid) { // we do not want it anymore skip it;
902 // Log::getInstance()->log("OsdVector", Log::DEBUG, "TVMedia Pictures arrived VDR %x %d %d",
903 // vresp->getStreamID(),vresp->getUserDataLength(),vresp->getFlag());
909 if (vresp->getFlag() != 2) {
910 userdata=vresp->getUserData();
911 length=vresp->getUserDataLength();
916 pict_lock_incoming.Lock();
917 if (inform_fallback.find(vresp->getStreamID())!=inform_fallback.end()) {
918 fallback=inform_fallback[vresp->getStreamID()];
920 pict_lock_incoming.Unlock();
921 if (fallback >= 0 && ((OsdVector*)Osd::getInstance())->getStaticImageData(fallback, &userdata, &length))
929 std::list<PictureDecoder*>::iterator itty=decoders.begin();
930 while (itty!=decoders.end()) {
931 userdata=(*itty)->decodePicture(vresp->getStreamID(), userdata, length, freed);
938 if (!decoded && userdata && freed){
942 pict_lock_incoming.Lock();
943 inform_fallback.erase(vresp->getStreamID());
944 pict_lock_incoming.Unlock();
945 //else osd->informPicture(vresp->getStreamID(), 0);
947 } else if (pict_incoming_static.size()){
948 unsigned int static_id = pict_incoming_static.front();
949 pict_incoming_static.pop();
950 set<LoadIndex>::iterator setpos = invalid_loadindex.find(((long long) static_id) << 32LL);
951 if (setpos != invalid_loadindex.end()) {
953 invalid_loadindex.erase(setpos);
955 pict_lock_incoming.Unlock();
956 if (!valid) { // we do not want it anymore skip it;
962 if (((OsdVector*)Osd::getInstance())->getStaticImageData(static_id, &userdata, &length))
964 std::list<PictureDecoder*>::iterator itty=decoders.begin();
965 while (itty!=decoders.end()) {
966 if (!(*itty)->decodePicture(((long long) static_id) << 32LL,userdata, length, false)){
974 pict_lock_incoming.Unlock();
978 if (pict_incoming.size() || pict_incoming_static.size()) return true;