llimagej2c.cpp

Go to the documentation of this file.
00001 
00030 #include "linden_common.h"
00031 
00032 #include <apr-1/apr_pools.h>
00033 #include <apr-1/apr_dso.h>
00034 
00035 #include "lldir.h"
00036 #include "llimagej2c.h"
00037 #include "llmemtype.h"
00038 
00039 typedef LLImageJ2CImpl* (*CreateLLImageJ2CFunction)();
00040 typedef void (*DestroyLLImageJ2CFunction)(LLImageJ2CImpl*);
00041 typedef const char* (*EngineInfoLLImageJ2CFunction)();
00042 
00043 //some "private static" variables so we only attempt to load
00044 //dynamic libaries once
00045 CreateLLImageJ2CFunction j2cimpl_create_func;
00046 DestroyLLImageJ2CFunction j2cimpl_destroy_func;
00047 EngineInfoLLImageJ2CFunction j2cimpl_engineinfo_func;
00048 apr_pool_t *j2cimpl_dso_memory_pool;
00049 apr_dso_handle_t *j2cimpl_dso_handle;
00050 
00051 //Declare the prototype for theses functions here, their functionality
00052 //will be implemented in other files which define a derived LLImageJ2CImpl
00053 //but only ONE static library which has the implementation for this
00054 //function should ever be included
00055 LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl();
00056 void fallbackDestroyLLImageJ2CImpl(LLImageJ2CImpl* impl);
00057 const char* fallbackEngineInfoLLImageJ2CImpl();
00058 
00059 //static
00060 //Loads the required "create", "destroy" and "engineinfo" functions needed
00061 void LLImageJ2C::openDSO()
00062 {
00063         //attempt to load a DSO and get some functions from it
00064         std::string dso_name;
00065         std::string dso_path;
00066 
00067         bool all_functions_loaded = false;
00068         apr_status_t rv;
00069 
00070 #if LL_WINDOWS
00071         dso_name = "llkdu.dll";
00072 #elif LL_DARWIN
00073         dso_name = "libllkdu.dylib";
00074 #else
00075         dso_name = "libllkdu.so";
00076 #endif
00077 
00078         dso_path = gDirUtilp->findFile(dso_name,
00079                                        gDirUtilp->getAppRODataDir(),
00080                                        gDirUtilp->getExecutableDir());
00081 
00082         j2cimpl_dso_handle      = NULL;
00083         j2cimpl_dso_memory_pool = NULL;
00084 
00085         //attempt to load the shared library
00086         apr_pool_create(&j2cimpl_dso_memory_pool, NULL);
00087         rv = apr_dso_load(&j2cimpl_dso_handle,
00088                                           dso_path.c_str(),
00089                                           j2cimpl_dso_memory_pool);
00090 
00091         //now, check for success
00092         if ( rv == APR_SUCCESS )
00093         {
00094                 //found the dynamic library
00095                 //now we want to load the functions we're interested in
00096                 CreateLLImageJ2CFunction  create_func = NULL;
00097                 DestroyLLImageJ2CFunction dest_func = NULL;
00098                 EngineInfoLLImageJ2CFunction engineinfo_func = NULL;
00099 
00100                 rv = apr_dso_sym((apr_dso_handle_sym_t*)&create_func,
00101                                                  j2cimpl_dso_handle,
00102                                                  "createLLImageJ2CKDU");
00103                 if ( rv == APR_SUCCESS )
00104                 {
00105                         //we've loaded the create function ok
00106                         //we need to delete via the DSO too
00107                         //so lets check for a destruction function
00108                         rv = apr_dso_sym((apr_dso_handle_sym_t*)&dest_func,
00109                                                          j2cimpl_dso_handle,
00110                                                        "destroyLLImageJ2CKDU");
00111                         if ( rv == APR_SUCCESS )
00112                         {
00113                                 //we've loaded the destroy function ok
00114                                 rv = apr_dso_sym((apr_dso_handle_sym_t*)&engineinfo_func,
00115                                                  j2cimpl_dso_handle,
00116                                                  "engineInfoLLImageJ2CKDU");
00117                                 if ( rv == APR_SUCCESS )
00118                                 {
00119                                         //ok, everything is loaded alright
00120                                         j2cimpl_create_func  = create_func;
00121                                         j2cimpl_destroy_func = dest_func;
00122                                         j2cimpl_engineinfo_func = engineinfo_func;
00123                                         all_functions_loaded = true;
00124                                 }
00125                         }
00126                 }
00127         }
00128 
00129         if ( !all_functions_loaded )
00130         {
00131                 //something went wrong with the DSO or function loading..
00132                 //fall back onto our satefy impl creation function
00133 
00134 #if 0
00135                 // precious verbose debugging, sadly we can't use our
00136                 // 'llinfos' stream etc. this early in the initialisation seq.
00137                 char errbuf[256];
00138                 fprintf(stderr, "failed to load syms from DSO %s (%s)\n",
00139                         dso_name.c_str(), dso_path.c_str());
00140                 apr_strerror(rv, errbuf, sizeof(errbuf));
00141                 fprintf(stderr, "error: %d, %s\n", rv, errbuf);
00142                 apr_dso_error(j2cimpl_dso_handle, errbuf, sizeof(errbuf));
00143                 fprintf(stderr, "dso-error: %d, %s\n", rv, errbuf);
00144 #endif
00145 
00146                 if ( j2cimpl_dso_handle )
00147                 {
00148                         apr_dso_unload(j2cimpl_dso_handle);
00149                         j2cimpl_dso_handle = NULL;
00150                 }
00151 
00152                 if ( j2cimpl_dso_memory_pool )
00153                 {
00154                         apr_pool_destroy(j2cimpl_dso_memory_pool);
00155                         j2cimpl_dso_memory_pool = NULL;
00156                 }
00157         }
00158 }
00159 
00160 //static
00161 void LLImageJ2C::closeDSO()
00162 {
00163         if ( j2cimpl_dso_handle ) apr_dso_unload(j2cimpl_dso_handle);
00164         if (j2cimpl_dso_memory_pool) apr_pool_destroy(j2cimpl_dso_memory_pool);
00165 }
00166 
00167 //static
00168 std::string LLImageJ2C::getEngineInfo()
00169 {
00170         if (!j2cimpl_engineinfo_func)
00171                 j2cimpl_engineinfo_func = fallbackEngineInfoLLImageJ2CImpl;
00172 
00173         return j2cimpl_engineinfo_func();
00174 }
00175 
00176 LLImageJ2C::LLImageJ2C() :      LLImageFormatted(IMG_CODEC_J2C),
00177                                                         mMaxBytes(0),
00178                                                         mRawDiscardLevel(-1),
00179                                                         mRate(0.0f),
00180                                                         mReversible(FALSE)
00181         
00182 {
00183         //We assume here that if we wanted to create via
00184         //a dynamic library that the approriate open calls were made
00185         //before any calls to this constructor.
00186 
00187         //Therefore, a NULL creation function pointer here means
00188         //we either did not want to create using functions from the dynamic
00189         //library or there were issues loading it, either way
00190         //use our fall back
00191         if ( !j2cimpl_create_func )
00192         {
00193                 j2cimpl_create_func = fallbackCreateLLImageJ2CImpl;
00194         }
00195 
00196         mImpl = j2cimpl_create_func();
00197 }
00198 
00199 // virtual
00200 LLImageJ2C::~LLImageJ2C()
00201 {
00202         //We assume here that if we wanted to destroy via
00203         //a dynamic library that the approriate open calls were made
00204         //before any calls to this destructor.
00205 
00206         //Therefore, a NULL creation function pointer here means
00207         //we either did not want to destroy using functions from the dynamic
00208         //library or there were issues loading it, either way
00209         //use our fall back
00210         if ( !j2cimpl_destroy_func )
00211         {
00212                 j2cimpl_destroy_func = fallbackDestroyLLImageJ2CImpl;
00213         }
00214 
00215         if ( mImpl )
00216         {
00217                 j2cimpl_destroy_func(mImpl);
00218         }
00219 }
00220 
00221 // virtual
00222 S8  LLImageJ2C::getRawDiscardLevel()
00223 {
00224         return mRawDiscardLevel;
00225 }
00226 
00227 BOOL LLImageJ2C::updateData()
00228 {       
00229         resetLastError();
00230 
00231         // Check to make sure that this instance has been initialized with data
00232         if (!getData() || (getDataSize() < 16))
00233         {
00234                 setLastError("LLImageJ2C uninitialized");
00235                 return FALSE;
00236         }
00237 
00238         if (!mImpl->getMetadata(*this))
00239         {
00240                 return FALSE;
00241         }
00242         // SJB: override discard based on mMaxBytes elsewhere
00243         S32 max_bytes = getDataSize(); // mMaxBytes ? mMaxBytes : getDataSize();
00244         S32 discard = calcDiscardLevelBytes(max_bytes);
00245         setDiscardLevel(discard);
00246 
00247         return TRUE;
00248 }
00249 
00250 
00251 BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time)
00252 {
00253         return decode(raw_imagep, decode_time, 0, 4);
00254 }
00255 
00256 
00257 BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count )
00258 {
00259         LLMemType mt1((LLMemType::EMemType)mMemType);
00260 
00261         resetLastError();
00262 
00263         // Check to make sure that this instance has been initialized with data
00264         if (!getData() || (getDataSize() < 16))
00265         {
00266                 setLastError("LLImageJ2C uninitialized");
00267                 return FALSE;
00268         }
00269 
00270         // Update the raw discard level
00271         updateRawDiscardLevel();
00272 
00273         mDecoding = TRUE;
00274         BOOL res = mImpl->decodeImpl(*this, *raw_imagep, decode_time, first_channel, max_channel_count);
00275         if (res)
00276         {
00277                 if (!mDecoding)
00278                 {
00279                         // Failed
00280                         raw_imagep->deleteData();
00281                 }
00282                 else
00283                 {
00284                         mDecoding = FALSE;
00285                 }
00286                 return TRUE; // done
00287         }
00288         return FALSE;
00289 }
00290 
00291 
00292 BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, F32 encode_time)
00293 {
00294         return encode(raw_imagep, NULL, encode_time);
00295 }
00296 
00297 
00298 BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time)
00299 {
00300         LLMemType mt1((LLMemType::EMemType)mMemType);
00301         return mImpl->encodeImpl(*this, *raw_imagep, comment_text, encode_time, mReversible);
00302 }
00303 
00304 //static
00305 S32 LLImageJ2C::calcHeaderSizeJ2C()
00306 {
00307         return 600; //2048; // ??? hack... just needs to be >= actual header size...
00308 }
00309 
00310 //static
00311 S32 LLImageJ2C::calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 rate)
00312 {
00313         if (rate <= 0.f) rate = .125f;
00314         while (discard_level > 0)
00315         {
00316                 if (w < 1 || h < 1)
00317                         break;
00318                 w >>= 1;
00319                 h >>= 1;
00320                 discard_level--;
00321         }
00322         S32 bytes = (S32)((F32)(w*h*comp)*rate);
00323         bytes = llmax(bytes, calcHeaderSizeJ2C());
00324         return bytes;
00325 }
00326 
00327 S32 LLImageJ2C::calcHeaderSize()
00328 {
00329         return calcHeaderSizeJ2C();
00330 }
00331 
00332 S32 LLImageJ2C::calcDataSize(S32 discard_level)
00333 {
00334         return calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), discard_level, mRate);
00335 }
00336 
00337 S32 LLImageJ2C::calcDiscardLevelBytes(S32 bytes)
00338 {
00339         llassert(bytes >= 0);
00340         S32 discard_level = 0;
00341         if (bytes == 0)
00342         {
00343                 return MAX_DISCARD_LEVEL;
00344         }
00345         while (1)
00346         {
00347                 S32 bytes_needed = calcDataSize(discard_level); // virtual
00348                 if (bytes >= bytes_needed - (bytes_needed>>2)) // For J2c, up the res at 75% of the optimal number of bytes
00349                 {
00350                         break;
00351                 }
00352                 discard_level++;
00353                 if (discard_level >= MAX_DISCARD_LEVEL)
00354                 {
00355                         break;
00356                 }
00357         }
00358         return discard_level;
00359 }
00360 
00361 void LLImageJ2C::setRate(F32 rate)
00362 {
00363         mRate = rate;
00364 }
00365 
00366 void LLImageJ2C::setMaxBytes(S32 max_bytes)
00367 {
00368         mMaxBytes = max_bytes;
00369 }
00370 
00371 void LLImageJ2C::setReversible(const BOOL reversible)
00372 {
00373         mReversible = reversible;
00374 }
00375 
00376 
00377 BOOL LLImageJ2C::loadAndValidate(const LLString &filename)
00378 {
00379         resetLastError();
00380 
00381         S32 file_size = 0;
00382         apr_file_t* apr_file = ll_apr_file_open(filename, LL_APR_RB, &file_size);
00383         if (!apr_file)
00384         {
00385                 setLastError("Unable to open file for reading", filename);
00386                 return FALSE;
00387         }
00388         if (file_size == 0)
00389         {
00390                 setLastError("File is empty",filename);
00391                 apr_file_close(apr_file);
00392                 return FALSE;
00393         }
00394         
00395         U8 *data = new U8[file_size];
00396         apr_size_t bytes_read = file_size;
00397         apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read     
00398         if (s != APR_SUCCESS || (S32)bytes_read != file_size)
00399         {
00400                 delete[] data;
00401                 setLastError("Unable to read entire file");
00402                 return FALSE;
00403         }
00404         apr_file_close(apr_file);
00405 
00406         return validate(data, file_size);
00407 }
00408 
00409 
00410 BOOL LLImageJ2C::validate(U8 *data, U32 file_size)
00411 {
00412         LLMemType mt1((LLMemType::EMemType)mMemType);
00413 
00414         setData(data, file_size);
00415         BOOL res = updateData();
00416         if ( !res )
00417         {
00418                 return FALSE;
00419         }
00420 
00421         // Check to make sure that this instance has been initialized with data
00422         if (!getData() || (0 == getDataSize()))
00423         {
00424                 setLastError("LLImageJ2C uninitialized");
00425                 return FALSE;
00426         }
00427 
00428         return mImpl->getMetadata(*this);
00429 }
00430 
00431 void LLImageJ2C::decodeFailed()
00432 {
00433         mDecoding = FALSE;
00434 }
00435 
00436 void LLImageJ2C::updateRawDiscardLevel()
00437 {
00438         mRawDiscardLevel = mMaxBytes ? calcDiscardLevelBytes(mMaxBytes) : mDiscardLevel;
00439 }
00440 
00441 LLImageJ2CImpl::~LLImageJ2CImpl()
00442 {
00443 }

Generated on Thu Jul 1 06:08:43 2010 for Second Life Viewer by  doxygen 1.4.7