Ticket #1488: osdimage-caching-0.19-v1.diff
File osdimage-caching-0.19-v1.diff, 9.8 KB (added by , 18 years ago) |
---|
-
libs/libmythtv/osdtypes.h
8 8 #include <vector> 9 9 #include <qobject.h> 10 10 #include <qregexp.h> 11 #include <qmutex.h> 11 12 12 13 using namespace std; 13 14 … … 137 138 138 139 QString Name() { return m_name; } 139 140 141 virtual void Reinit(int xoff, int yoff, int dispw, int disph, 142 float wmult, float hmult); 143 140 144 virtual void Reinit(float wmult, float hmult) = 0; 141 145 142 146 virtual void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, … … 260 264 QString m_filename; 261 265 262 266 bool m_isvalid; 267 268 struct OSDImageCacheValue { 269 unsigned char *m_yuv; 270 unsigned char *m_ybuffer; 271 unsigned char *m_ubuffer; 272 unsigned char *m_vbuffer; 273 unsigned char *m_alpha; 274 QRect m_imagesize; 275 }; 263 276 277 QMap<QString, OSDImageCacheValue> m_imageCache; 278 QMutex m_cacheLock; 279 280 QString generateCacheKey(const QString &filename, float wmult, float hmult, 281 int scalew, int scaleh); 282 bool isCached(QString imageKey, bool useDiskCache); 283 void loadFromCache(QString imageKey, bool useDiskCache); 284 void saveToCache(QString imageKey, bool useDiskCache); 285 264 286 unsigned char *m_yuv; 265 287 unsigned char *m_ybuffer; 266 288 unsigned char *m_ubuffer; … … 272 294 273 295 int m_drawwidth; 274 296 bool m_onlyusefirst; 297 bool m_cached; 275 298 }; 276 299 277 300 class OSDTypePosSlider : public OSDTypeImage … … 483 506 int xoffset, yoffset, displaywidth, displayheight; 484 507 }; 485 508 509 486 510 #endif -
libs/libmythtv/osdtypes.cpp
2 2 #include <qmap.h> 3 3 #include <qregexp.h> 4 4 #include <math.h> 5 #include <qstring.h> 6 #include <qfile.h> 7 #include <qdatastream.h> 8 #include <qdir.h> 5 9 6 10 #include <iostream> 7 11 using namespace std; … … 382 386 383 387 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 384 388 389 void 390 OSDType::Reinit(int, int, int, int, float wmult, float hmult) 391 { 392 // The default implementation delegates the call to the Reinit(wmult, hmult) 393 // method. 394 // This allows cleaner dynamically bound call in OSDSet::Reinit() without 395 // the ugly (and slow!) dynamic_cast. 396 Reinit(wmult, hmult); 397 } 398 385 399 OSDType::OSDType(const QString &name) 386 400 { 387 401 m_hidden = false; … … 674 688 675 689 m_scalew = scalew; 676 690 m_scaleh = scaleh; 691 m_cached = false; 677 692 678 693 LoadImage(filename, wmult, hmult, scalew, scaleh); 679 694 } … … 750 765 751 766 OSDTypeImage::~OSDTypeImage() 752 767 { 753 if (m_yuv) 754 delete [] m_yuv; 755 if (m_alpha) 756 delete [] m_alpha; 768 // cleanup the OSD image cache in memory 769 m_cacheLock.lock(); 770 QMapIterator<QString, OSDImageCacheValue> i = m_imageCache.begin(); 771 while (i != m_imageCache.end()) { 772 OSDImageCacheValue& value = i.data(); 773 delete [] value.m_yuv; 774 delete [] value.m_alpha; 775 ++i; 776 } 777 m_imageCache.clear(); 778 m_cacheLock.unlock(); 757 779 } 758 780 759 781 void OSDTypeImage::SetName(const QString &name) … … 778 800 LoadImage(m_filename, wmult, hmult, m_scalew, m_scaleh); 779 801 } 780 802 803 #include <iostream> 804 805 /** 806 * Returns true in case cached OSD image was found in the cache. 807 * 808 * @param imageKey The key for this image. 809 * @param useDiskCache If true, also look from the disk cache. 810 */ 811 bool OSDTypeImage::isCached(QString imageKey, bool useDiskCache) { 812 813 QMutexLocker locker(&m_cacheLock); 814 815 if (m_imageCache.find(imageKey) != m_imageCache.end()) { 816 return true; 817 } 818 819 if (!useDiskCache) 820 return false; 821 822 QDir dir(MythContext::GetConfDir() + "/osdcache/"); 823 824 QFile cacheFile(dir.path() + "/" + imageKey); 825 if (cacheFile.exists()) { 826 return true; 827 } 828 return false; 829 } 830 831 /** 832 * Loads OSD image data from cache. 833 * 834 * @param imageKey The key for this image. 835 * @param useDiskCache If true, also look from the disk cache. 836 */ 837 void OSDTypeImage::loadFromCache(QString imageKey, bool useDiskCache) { 838 839 OSDImageCacheValue value; 840 841 QMutexLocker locker(&m_cacheLock); 842 843 if (m_imageCache.find(imageKey) != m_imageCache.end()) { 844 // the image was found in the memory cache 845 value = m_imageCache[imageKey]; 846 } else if (useDiskCache) { 847 848 QDir dir(MythContext::GetConfDir() + "/osdcache/"); 849 850 QFile cacheFile(dir.path() + "/" + imageKey); 851 if (!cacheFile.exists()) { 852 return; 853 } 854 855 cacheFile.open(IO_ReadOnly); 856 QDataStream stream(&cacheFile); 857 Q_INT32 imwidth = 0, imheight = 0; 858 stream >> imwidth >> imheight; 859 860 int yuv_size = imwidth * imheight * 3 / 2; 861 value.m_yuv = new unsigned char[yuv_size]; 862 value.m_ybuffer = value.m_yuv; 863 value.m_ubuffer = value.m_yuv + (imwidth * imheight); 864 value.m_vbuffer = value.m_yuv + (imwidth * imheight * 5 / 4); 865 866 unsigned expectedFileSize = 867 2*sizeof(Q_INT32) + yuv_size + imwidth*imheight; 868 if (cacheFile.size() != expectedFileSize) { 869 VERBOSE(VB_IMPORTANT, imageKey + " wrong cache file size!"); 870 std::cout << "LOG: " 871 << cacheFile.size() << " != " 872 << expectedFileSize << std::endl; 873 return; 874 } 875 876 stream.readRawBytes((char*)value.m_yuv, yuv_size); 877 878 value.m_alpha = new unsigned char[imwidth * imheight]; 879 880 stream.readRawBytes((char*)value.m_alpha, imwidth * imheight); 881 882 value.m_imagesize = QRect(0, 0, imwidth, imheight); 883 m_imageCache[imageKey] = value; 884 cacheFile.close(); 885 // the image was found and loaded from disk cache 886 } else { 887 // image was not found in neither of the caches 888 return; 889 } 890 m_yuv = value.m_yuv; 891 m_ybuffer = value.m_ybuffer; 892 m_ubuffer = value.m_ubuffer; 893 m_vbuffer = value.m_vbuffer; 894 m_alpha = value.m_alpha; 895 m_imagesize = value.m_imagesize; 896 m_isvalid = true; 897 } 898 899 /** 900 * Saves the current OSD image data from cache. 901 * 902 * @param imageKey The key for this image. 903 * @param useDiskCache If true, also save to the disk cache. 904 */ 905 void OSDTypeImage::saveToCache(QString imageKey, bool useDiskCache) { 906 907 if (isCached(imageKey, useDiskCache)) 908 return; 909 910 OSDImageCacheValue value; 911 912 value.m_yuv = m_yuv; 913 value.m_ybuffer = m_ybuffer; 914 value.m_ubuffer = m_ubuffer; 915 value.m_vbuffer = m_vbuffer; 916 value.m_alpha = m_alpha; 917 value.m_imagesize = m_imagesize; 918 919 m_cacheLock.lock(); 920 m_imageCache[imageKey] = value; 921 m_cacheLock.unlock(); 922 923 if (!useDiskCache) 924 return; 925 926 QDir dir(MythContext::GetConfDir() + "/osdcache/"); 927 928 if (!dir.exists()) { 929 if (!dir.mkdir(dir.path())) { 930 VERBOSE(VB_IMPORTANT, "Creating osdcache directory failed."); 931 return; 932 } 933 } 934 935 QFile cacheFile(dir.path() + "/" + imageKey); 936 937 if (!cacheFile.open(IO_WriteOnly | IO_Truncate)) { 938 VERBOSE(VB_IMPORTANT, "Creating osdcache file failed."); 939 return; 940 } 941 QDataStream stream(&cacheFile); 942 Q_INT32 imwidth = m_imagesize.width(), imheight = m_imagesize.height(); 943 stream << imwidth << imheight; 944 945 int yuv_size = imwidth * imheight * 3 / 2; 946 947 stream.writeRawBytes((const char*)m_yuv, yuv_size); 948 stream.writeRawBytes((const char*)m_alpha, imwidth * imheight); 949 // saved the image to disk cache 950 cacheFile.close(); 951 } 952 953 /** 954 * Generates a cache key from the given OSD image parameters. 955 * 956 * The returned key is a string that can be safely used as a file name. 957 */ 958 QString OSDTypeImage::generateCacheKey(const QString &filename, float wmult, 959 float hmult, int scalew, int scaleh) { 960 961 QString cacheKey = 962 QString("%1_%2_%3_%4_%5") 963 .arg(filename).arg(wmult).arg(hmult).arg(scalew).arg(scaleh) 964 .replace(QChar('/'), ".").replace(QChar(' '), ".") 965 .replace(QChar(' '), "."); 966 967 return cacheKey; 968 } 969 970 781 971 void OSDTypeImage::LoadImage(const QString &filename, float wmult, float hmult, 782 972 int scalew, int scaleh) 783 973 { 784 if (m_isvalid) 785 { 786 if (m_yuv) 787 delete [] m_yuv; 788 if (m_alpha) 789 delete [] m_alpha; 974 QString cacheKey = generateCacheKey(filename, wmult, hmult, scalew, 975 scaleh); 790 976 791 m_isvalid = false; 792 m_yuv = NULL; 793 m_alpha = NULL; 977 // if there's no filename, do not use file buffering (cannot 978 // generate an unique filename for the cache file), but only 979 // the memory cache as it's safe to do so, because the 980 // memory cache is per OSDTypeImage 981 if (isCached(cacheKey, !filename.isEmpty())) { 982 loadFromCache(cacheKey, !filename.isEmpty()); 983 m_cached = true; 984 return; 794 985 } 795 986 796 987 if (filename.length() < 2) … … 833 1024 imwidth, imheight, tmp2.width()); 834 1025 835 1026 m_imagesize = QRect(0, 0, imwidth, imheight); 1027 1028 saveToCache(cacheKey, !filename.isEmpty()); 1029 m_cached = true; 836 1030 } 837 1031 838 1032 void OSDTypeImage::LoadFromQImage(const QImage &img) 839 1033 { 840 if (m_isvalid) 1034 // this method is not cached as it's used mostly for 1035 // subtitles which are displayed only once anyways, caching 1036 // would probably only slow things down overall 1037 if (m_isvalid && !m_cached) 841 1038 { 842 1039 if (m_yuv) 843 1040 delete [] m_yuv; 844 1041 if (m_alpha) 845 1042 delete [] m_alpha; 846 847 1043 m_isvalid = false; 848 1044 m_yuv = NULL; 849 1045 m_alpha = NULL; … … 1159 1355 OSDTypeEditSlider::~OSDTypeEditSlider() 1160 1356 { 1161 1357 delete [] m_drawMap; 1162 1163 if (m_ryuv)1164 delete [] m_ryuv;1165 if (m_ralpha)1166 delete [] m_ralpha;1167 1358 } 1168 1359 1169 1360 void OSDTypeEditSlider::Reinit(float wmult, float hmult) … … 1184 1375 1185 1376 m_displaypos = m_displayrect.topLeft(); 1186 1377 1187 if (m_ryuv) 1188 delete [] m_ryuv; 1189 if (m_ralpha) 1190 delete [] m_ralpha; 1378 if (!m_cached) { 1379 if (m_ryuv) 1380 delete [] m_ryuv; 1381 if (m_ralpha) 1382 delete [] m_ralpha; 1383 } 1191 1384 1192 1385 LoadImage(m_redname, wmult, hmult, m_scalew, m_scaleh); 1193 1386 if (m_isvalid)