Defines the beginning and ending file positions of a layer in an LRCP-progression JPEG2000 file
        OpenJPEG.J2KLayerInfo[] CreateDefaultLayers(int j2kLength)
        {
            OpenJPEG.J2KLayerInfo[] layers = new OpenJPEG.J2KLayerInfo[5];

            for (int i = 0; i < layers.Length; i++)
                layers[i] = new OpenJPEG.J2KLayerInfo();

            // These default layer sizes are based on a small sampling of real-world texture data
            // with extra padding thrown in for good measure. This is a worst case fallback plan
            // and may not gracefully handle all real world data
            layers[0].Start = 0;
            layers[1].Start = (int) (j2kLength*0.02f);
            layers[2].Start = (int) (j2kLength*0.05f);
            layers[3].Start = (int) (j2kLength*0.20f);
            layers[4].Start = (int) (j2kLength*0.50f);

            layers[0].End = layers[1].Start - 1;
            layers[1].End = layers[2].Start - 1;
            layers[2].End = layers[3].Start - 1;
            layers[3].End = layers[4].Start - 1;
            layers[4].End = j2kLength;

            return layers;
        }
        bool TryLoadCacheForAsset(UUID assetId, out OpenJPEG.J2KLayerInfo[] layers)
        {
            if (m_decodedCache.TryGetValue(assetId, out layers))
            {
                return true;
            }
            else if (m_cache != null)
            {
                string assetName = "j2kCache_" + assetId;
                AssetBase layerDecodeAsset = m_cache.Get(assetName);

                if (layerDecodeAsset != null)
                {
                    #region Deserialize Layer Data

                    string readResult = Util.UTF8.GetString(layerDecodeAsset.Data);
                    string[] lines = readResult.Split(new[] {'\n'}, StringSplitOptions.RemoveEmptyEntries);

                    if (lines.Length == 0)
                    {
                        MainConsole.Instance.Warn("[J2KDecodeCache]: Expiring corrupted layer data (empty) " + assetName);
                        m_cache.Expire(assetName);
                        return false;
                    }

                    layers = new OpenJPEG.J2KLayerInfo[lines.Length];

                    for (int i = 0; i < lines.Length; i++)
                    {
                        string[] elements = lines[i].Split('|');
                        if (elements.Length == 3)
                        {
                            int element1, element2;

                            try
                            {
                                element1 = Convert.ToInt32(elements[0]);
                                element2 = Convert.ToInt32(elements[1]);
                            }
                            catch (FormatException)
                            {
                                MainConsole.Instance.Warn("[J2KDecodeCache]: Expiring corrupted layer data (format) " +
                                                          assetName);
                                m_cache.Expire(assetName);
                                return false;
                            }

                            layers[i] = new OpenJPEG.J2KLayerInfo {Start = element1, End = element2};
                        }
                        else
                        {
                            MainConsole.Instance.Warn("[J2KDecodeCache]: Expiring corrupted layer data (layout) " +
                                                      assetName);
                            m_cache.Expire(assetName);
                            return false;
                        }
                    }

                    #endregion Deserialize Layer Data

                    return true;
                }
            }

            return false;
        }
Exemplo n.º 3
0
        /// <summary>
        /// Decode Jpeg2000 Asset Data
        /// </summary>
        /// <param name="assetID">UUID of Asset</param>
        /// <param name="j2kData">JPEG2000 data</param>
        private void DoJ2KDecode(UUID assetID, byte[] j2kData)
        {
//            m_log.DebugFormat(
//                "[J2KDecoderModule]: Doing J2K decoding of {0} bytes for asset {1}", j2kData.Length, assetID);

            //int DecodeTime = 0;
            //DecodeTime = Environment.TickCount;
            OpenJPEG.J2KLayerInfo[] layers;

            if (!TryLoadCacheForAsset(assetID, out layers))
            {
                if (m_useCSJ2K)
                {
                    try
                    {
                        List<int> layerStarts = CSJ2K.J2kImage.GetLayerBoundaries(new MemoryStream(j2kData));

                        if (layerStarts != null && layerStarts.Count > 0)
                        {
                            layers = new OpenJPEG.J2KLayerInfo[layerStarts.Count];

                            for (int i = 0; i < layerStarts.Count; i++)
                            {
                                OpenJPEG.J2KLayerInfo layer = new OpenJPEG.J2KLayerInfo();

                                if (i == 0)
                                    layer.Start = 0;
                                else
                                    layer.Start = layerStarts[i];

                                if (i == layerStarts.Count - 1)
                                    layer.End = j2kData.Length;
                                else
                                    layer.End = layerStarts[i + 1] - 1;

                                layers[i] = layer;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        m_log.Warn("[J2KDecoderModule]: CSJ2K threw an exception decoding texture " + assetID + ": " + ex.Message);
                    }
                }
                else
                {
                    int components;
                    if (!OpenJPEG.DecodeLayerBoundaries(j2kData, out layers, out components))
                    {
                        m_log.Warn("[J2KDecoderModule]: OpenJPEG failed to decode texture " + assetID);
                    }
                }

                if (layers == null || layers.Length == 0)
                {
                    m_log.Warn("[J2KDecoderModule]: Failed to decode layer data for texture " + assetID + ", guessing sane defaults");
                    // Layer decoding completely failed. Guess at sane defaults for the layer boundaries
                    layers = CreateDefaultLayers(j2kData.Length);
                }

                // Cache Decoded layers
                SaveFileCacheForAsset(assetID, layers);
            }
            
            // Notify Interested Parties
            lock (m_notifyList)
            {
                if (m_notifyList.ContainsKey(assetID))
                {
                    foreach (DecodedCallback d in m_notifyList[assetID])
                    {
                        if (d != null)
                            d.DynamicInvoke(assetID, layers);
                    }
                    m_notifyList.Remove(assetID);
                }
            }
        }
        bool DoJ2KDecode(UUID assetID, byte[] j2kData, bool useCSJ2K)
        {
            //int DecodeTime = 0;
            //DecodeTime = Environment.TickCount;
            OpenJPEG.J2KLayerInfo[] layers;

            if (!TryLoadCacheForAsset(assetID, out layers))
            {
                // not in cache. If no data try to decode with some defaults
                if (j2kData == null || j2kData.Length == 0)
                {
                    // Layer decoding completely failed. Guess at sane defaults for the layer boundaries
                    if (j2kData != null)
                        layers = CreateDefaultLayers(j2kData.Length);
                    else
                        layers = CreateDefaultLayers (0);

                    // Notify Interested Parties
                    lock (m_notifyList)
                    {
                        if (m_notifyList.ContainsKey(assetID))
                        {
                            foreach (DecodedCallback d in m_notifyList[assetID].Where(d => d != null))
                                d.DynamicInvoke(assetID, layers);

                            m_notifyList.Remove(assetID);
                        }
                    }
                    return false;
                }

                if (m_useCSJ2K)
                {
                    try
                    {
                        List<int> layerStarts = J2kImage.GetLayerBoundaries(new MemoryStream(j2kData));

                        if (layerStarts != null && layerStarts.Count > 0)
                        {
                            layers = new OpenJPEG.J2KLayerInfo[layerStarts.Count];

                            for (int i = 0; i < layerStarts.Count; i++)
                            {
                                OpenJPEG.J2KLayerInfo layer = new OpenJPEG.J2KLayerInfo
                                                                  {Start = i == 0 ? 0 : layerStarts[i]};


                                if (i == layerStarts.Count - 1)
                                    layer.End = j2kData.Length;
                                else
                                    layer.End = layerStarts[i + 1] - 1;

                                layers[i] = layer;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        MainConsole.Instance.Warn("[J2KDecoderModule]: CSJ2K threw an exception decoding texture " +
                                                  assetID + ": " + ex.Message);
                    }
                }
                else
                {
                    int components;
                    if (!OpenJPEG.DecodeLayerBoundaries(j2kData, out layers, out components))
                    {
                        MainConsole.Instance.Warn("[J2KDecoderModule]: OpenJPEG failed to decode texture " + assetID);
                    }
                }

                if (layers == null || layers.Length == 0)
                {
                    if (useCSJ2K == m_useCSJ2K)
                    {
                        MainConsole.Instance.Warn("[J2KDecoderModule]: Failed to decode layer data with (" +
                                                  (m_useCSJ2K ? "CSJ2K" : "OpenJPEG") + ") for texture " + assetID +
                                                  ", length " + j2kData.Length +
                                                  " trying " + (!m_useCSJ2K ? "CSJ2K" : "OpenJPEG"));
                        DoJ2KDecode(assetID, j2kData, !m_useCSJ2K);
                    }
                    else
                    {
                        //Second attempt at decode with the other j2k decoder, give up
                        MainConsole.Instance.Warn("[J2KDecoderModule]: Failed to decode layer data (" +
                                                  (m_useCSJ2K ? "CSJ2K" : "OpenJPEG") + ") for texture " + assetID +
                                                  ", length " + j2kData.Length + " guessing sane defaults");
                        
                        // Layer decoding completely failed. Guess at sane defaults for the layer boundaries
                        layers = CreateDefaultLayers(j2kData.Length);
                        // Notify Interested Parties
                        lock (m_notifyList)
                        {
                            if (m_notifyList.ContainsKey(assetID))
                            {
                                foreach (DecodedCallback d in m_notifyList[assetID].Where(d => d != null))
                                {
                                    d.DynamicInvoke(assetID, layers);
                                }
                                m_notifyList.Remove(assetID);
                            }
                        }
                        return false;
                    }
                }
                else //Don't save the corrupt texture!
                {
                    // Cache Decoded layers
                    SaveFileCacheForAsset(assetID, layers);
                }
            }

            // Notify Interested Parties
            lock (m_notifyList)
            {
                if (m_notifyList.ContainsKey(assetID))
                {
                    foreach (DecodedCallback d in m_notifyList[assetID].Where(d => d != null))
                    {
                        d.DynamicInvoke(assetID, layers);
                    }
                    m_notifyList.Remove(assetID);
                }
            }
            return true;
        }
Exemplo n.º 5
0
        /// <summary>
        /// Loads the Layer data from the disk cache
        /// Returns true if load succeeded
        /// </summary>
        /// <param name="AssetId">AssetId that we're checking the cache for</param>
        /// <param name="Layers">out layers to save to</param>
        /// <returns>true if load succeeded</returns>
        public bool TryLoadCacheForAsset(UUID AssetId, out OpenJPEG.J2KLayerInfo[] Layers)
        {
            // Check if it's cached in memory
            if (m_decodedCache.TryGetValue(AssetId, out Layers))
            {
                return true;
            }
            
            // Look for it in the file cache
            string filename = String.Format("{0}/{1}", m_cacheDecodeFolder, FileNameFromAssetId(AssetId));
            Layers = new OpenJPEG.J2KLayerInfo[0];

            if ((File.Exists(filename) == false) || (enabled == false))
                return false;

            string readResult = String.Empty;

            try
            {
                using (FileStream fsCachefile = new FileStream(filename, FileMode.Open))
                {

                    using (StreamReader sr = new StreamReader(fsCachefile))
                    {
                        readResult = sr.ReadToEnd();

                        sr.Close();
                    }
                }

            }
            catch (IOException ioe)
            {
                if (ioe is PathTooLongException)
                {
                    m_log.Error(
                        "[J2KDecodeCache]: Cache Read failed. Path is too long.");
                }
                else if (ioe is DirectoryNotFoundException)
                {
                    m_log.Error(
                        "[J2KDecodeCache]: Cache Read failed. Cache Directory does not exist!");
                    enabled = false;
                }
                else
                {
                    m_log.Error(
                        "[J2KDecodeCache]: Cache Read failed. IO Exception.");
                }
                return false;

            }
            catch (UnauthorizedAccessException)
            {
                m_log.Error(
                    "[J2KDecodeCache]: Cache Read failed. UnauthorizedAccessException Exception. Do you have the proper permissions on this file?");
                return false;
            }
            catch (ArgumentException ae)
            {
                if (ae is ArgumentNullException)
                {
                    m_log.Error(
                        "[J2KDecodeCache]: Cache Read failed. No Filename provided");
                }
                else
                {
                    m_log.Error(
                   "[J2KDecodeCache]: Cache Read failed. Filname was invalid");
                }
                return false;
            }
            catch (NotSupportedException)
            {
                m_log.Error(
                    "[J2KDecodeCache]: Cache Read failed, not supported. Cache disabled!");
                enabled = false;

                return false;
            }
            catch (Exception e)
            {
                m_log.ErrorFormat(
                    "[J2KDecodeCache]: Cache Read failed, unknown exception.  Error: {0}",
                    e.ToString());
                return false;
            }

            string[] lines = readResult.Split('\n');

            if (lines.Length <= 0)
                return false;

            Layers = new OpenJPEG.J2KLayerInfo[lines.Length];
            
            for (int i = 0; i < lines.Length; i++)
            {
                string[] elements = lines[i].Split('|');
                if (elements.Length == 3)
                {
                    int element1, element2;

                    try
                    {
                        element1 = Convert.ToInt32(elements[0]);
                        element2 = Convert.ToInt32(elements[1]);
                    }
                    catch (FormatException)
                    {
                        m_log.WarnFormat("[J2KDecodeCache]: Cache Read failed with ErrorConvert for {0}", AssetId);
                        Layers = new OpenJPEG.J2KLayerInfo[0];
                        return false;
                    }

                    Layers[i] = new OpenJPEG.J2KLayerInfo();
                    Layers[i].Start = element1;
                    Layers[i].End = element2;

                }
                else
                {
                    // reading failed
                    m_log.WarnFormat("[J2KDecodeCache]: Cache Read failed for {0}", AssetId);
                    Layers = new OpenJPEG.J2KLayerInfo[0];
                    return false;
                }
            }

            return true;
        }
Exemplo n.º 6
0
        private static string GetLayerBoundariesHeader(UUID textureID, byte[] textureData)
        {
            OpenJPEG.J2KLayerInfo[] layers = null;

            // Decode this texture and get layer boundaries before storing it
            using (MemoryStream stream = new MemoryStream(textureData))
            {
                try
                {
                    List<int> layerStarts = J2kImage.GetLayerBoundaries(stream);

                    if (layerStarts != null && layerStarts.Count > 0)
                    {
                        layers = new OpenJPEG.J2KLayerInfo[layerStarts.Count];

                        for (int i = 0; i < layerStarts.Count; i++)
                        {
                            OpenJPEG.J2KLayerInfo layer = new OpenJPEG.J2KLayerInfo();

                            if (i == 0)
                                layer.Start = 0;
                            else
                                layer.Start = layerStarts[i];

                            if (i == layerStarts.Count - 1)
                                layer.End = textureData.Length;
                            else
                                layer.End = layerStarts[i + 1] - 1;

                            layers[i] = layer;
                        }
                    }
                }
                catch (Exception ex)
                {
                    m_log.WarnFormat("Error decoding layer boundaries from texture {0} ({1} bytes): {2}", textureID, textureData.Length, ex.Message);
                    layers = null;
                }
            }

            if (layers != null)
            {
                StringBuilder header = new StringBuilder();

                for (int i = 0; i < layers.Length; i++)
                {
                    OpenJPEG.J2KLayerInfo layer = layers[i];
                    header.AppendFormat("{0}-{1};", layer.Start, layer.End);
                }

                return header.ToString();
            }
            else
            {
                return null;
            }
        }
Exemplo n.º 7
0
        /// <summary>
        /// Decode Jpeg2000 Asset Data
        /// </summary>
        /// <param name="assetID">UUID of Asset</param>
        /// <param name="j2kData">JPEG2000 data</param>
        /// <param name="layers">layer data</param>
        /// <param name="components">number of components</param>
        /// <returns>true if decode was successful.  false otherwise.</returns>
        private bool DoJ2KDecode(UUID assetID, byte[] j2kData, out OpenJPEG.J2KLayerInfo[] layers)
        {
            bool decodedSuccessfully = true;
            int DecodeTime = Environment.TickCount;
            layers = new OpenJPEG.J2KLayerInfo[0]; // Dummy result for if it fails.  Informs that there's only full quality

            try
            {
                using (MemoryStream ms = new MemoryStream(j2kData))
                {
                    List<int> layerStarts = CSJ2K.J2kImage.GetLayerBoundaries(ms);

                    if (layerStarts != null && layerStarts.Count > 0)
                    {
                        layers = new OpenJPEG.J2KLayerInfo[layerStarts.Count];

                        for (int i = 0; i < layerStarts.Count; i++)
                        {
                            OpenJPEG.J2KLayerInfo layer = new OpenJPEG.J2KLayerInfo();

                            if (i == 0)
                                layer.Start = 0;
                            else
                                layer.Start = layerStarts[i];

                            if (i == layerStarts.Count - 1)
                                layer.End = j2kData.Length;
                            else
                                layer.End = layerStarts[i + 1] - 1;

                            layers[i] = layer;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                m_log.Warn("[J2KDecoderModule]: CSJ2K threw an exception decoding texture " + assetID + ": " + ex.Message);
                decodedSuccessfully = false;
            }

            if (layers.Length == 0)
            {
                m_log.Warn("[J2KDecoderModule]: Failed to decode layer data for texture " + assetID + ", guessing sane defaults");

                // Layer decoding completely failed. Guess at sane defaults for the layer boundaries
                layers = CreateDefaultLayers(j2kData.Length);
                decodedSuccessfully = false;
            }
            else
            {
                int elapsed = Environment.TickCount - DecodeTime;
                if (elapsed >= 50)
                    m_log.InfoFormat("[J2KDecoderModule]: {0} Decode Time: {1}", elapsed, assetID);
                // Cache Decoded layers
                fCache.SaveCacheForAsset(assetID, layers);
            }

            return decodedSuccessfully;
        }
        /// <summary>
        /// Decode Jpeg2000 Asset Data
        /// </summary>
        /// <param name="AssetId">UUID of Asset</param>
        /// <param name="j2kdata">Byte Array Asset Data </param>
        private void doJ2kDecode(UUID AssetId, byte[] j2kdata)
        {
            int DecodeTime = 0;
            DecodeTime = Environment.TickCount;
            OpenJPEG.J2KLayerInfo[] layers = new OpenJPEG.J2KLayerInfo[0]; // Dummy result for if it fails.  Informs that there's only full quality

            if (!OpenJpegFail)
            {
                if (!fCache.TryLoadCacheForAsset(AssetId, out layers))
                {
                    try
                    {

                        AssetTexture texture = new AssetTexture(AssetId, j2kdata);
                        if (texture.DecodeLayerBoundaries())
                        {
                            bool sane = true;

                            // Sanity check all of the layers
                            for (int i = 0; i < texture.LayerInfo.Length; i++)
                            {
                                if (texture.LayerInfo[i].End > texture.AssetData.Length)
                                {
                                    sane = false;
                                    break;
                                }
                            }

                            if (sane)
                            {
                                layers = texture.LayerInfo;
                                fCache.SaveFileCacheForAsset(AssetId, layers);
                               

                                    // Write out decode time
                                    m_log.InfoFormat("[J2KDecoderModule]: {0} Decode Time: {1}", Environment.TickCount - DecodeTime,
                                                     AssetId);
                               
                            }
                            else
                            {
                                m_log.WarnFormat(
                                    "[J2KDecoderModule]: JPEG2000 texture decoding succeeded, but sanity check failed for {0}",
                                    AssetId);
                            }
                        }

                        else
                        {
                            /*
                            Random rnd = new Random();
                             // scramble ends for test
                            for (int i = 0; i < texture.LayerInfo.Length; i++)
                            {
                                texture.LayerInfo[i].End = rnd.Next(999999);
                            }
                            */

                            // Try to do some heuristics error correction!  Yeah.
                            bool sane2Heuristics = true;


                            if (texture.Image == null)
                                sane2Heuristics = false;

                            if (texture.LayerInfo == null)
                                sane2Heuristics = false;

                            if (sane2Heuristics)
                            {


                                if (texture.LayerInfo.Length == 0)
                                    sane2Heuristics = false;
                            }

                            if (sane2Heuristics)
                            {
                                // Last layer start is less then the end of the file and last layer start is greater then 0
                                if (texture.LayerInfo[texture.LayerInfo.Length - 1].Start < texture.AssetData.Length && texture.LayerInfo[texture.LayerInfo.Length - 1].Start > 0)
                                {
                                }
                                else
                                {
                                    sane2Heuristics = false;
                                }

                            }

                            if (sane2Heuristics)
                            {
                                int start = 0;
                                
                                // try to fix it by using consistant data in the start field
                                for (int i = 0; i < texture.LayerInfo.Length; i++)
                                {
                                    if (i == 0)
                                        start = 0;

                                    if (i == texture.LayerInfo.Length - 1)
                                        texture.LayerInfo[i].End = texture.AssetData.Length;
                                    else
                                        texture.LayerInfo[i].End = texture.LayerInfo[i + 1].Start - 1;

                                    // in this case, the end of the next packet is less then the start of the last packet
                                    // after we've attempted to fix it which means the start of the last packet is borked
                                    // there's no recovery from this
                                    if (texture.LayerInfo[i].End < start)
                                    {
                                        sane2Heuristics = false;
                                        break;
                                    }
 
                                    if (texture.LayerInfo[i].End < 0 || texture.LayerInfo[i].End > texture.AssetData.Length)
                                    {
                                        sane2Heuristics = false;
                                        break;
                                    }

                                    if (texture.LayerInfo[i].Start < 0 || texture.LayerInfo[i].Start > texture.AssetData.Length)
                                    {
                                        sane2Heuristics = false;
                                        break;
                                    }

                                    start = texture.LayerInfo[i].Start;
                                }
                            }

                            if (sane2Heuristics)
                            {
                                layers = texture.LayerInfo;
                                fCache.SaveFileCacheForAsset(AssetId, layers);


                                // Write out decode time
                                m_log.InfoFormat("[J2KDecoderModule]: HEURISTICS SUCCEEDED {0} Decode Time: {1}", Environment.TickCount - DecodeTime,
                                                 AssetId);

                            }
                            else
                            {
                                m_log.WarnFormat("[J2KDecoderModule]: JPEG2000 texture decoding failed for {0}.   Is this a texture?  is it J2K?", AssetId);
                            }
                        }
                        texture = null; // dereference and dispose of ManagedImage
                    }
                    catch (DllNotFoundException)
                    {
                        m_log.Error(
                            "[J2KDecoderModule]: OpenJpeg is not installed properly. Decoding disabled!  This will slow down texture performance!  Often times this is because of an old version of GLIBC.  You must have version 2.4 or above!");
                        OpenJpegFail = true;
                    }
                    catch (Exception ex)
                    {
                        m_log.WarnFormat(
                            "[J2KDecoderModule]: JPEG2000 texture decoding threw an exception for {0}, {1}",
                            AssetId, ex);
                    }
                }
               
            }

            // Cache Decoded layers
            lock (m_cacheddecode)
            {
                if (m_cacheddecode.ContainsKey(AssetId))
                    m_cacheddecode.Remove(AssetId);
                m_cacheddecode.Add(AssetId, layers);

            }            

            // Notify Interested Parties
            lock (m_notifyList)
            {
                if (m_notifyList.ContainsKey(AssetId))
                {
                    foreach (DecodedCallback d in m_notifyList[AssetId])
                    {
                        if (d != null)
                            d.DynamicInvoke(AssetId, layers);
                    }
                    m_notifyList.Remove(AssetId);
                }
            }
        }
        public void decode(UUID AssetId, byte[] assetData, DecodedCallback decodedReturn)
        {
            // Dummy for if decoding fails.
            OpenJPEG.J2KLayerInfo[] result = new OpenJPEG.J2KLayerInfo[0];

            // Check if it's cached
            bool cached = false;
            lock (m_cacheddecode)
            {
                if (m_cacheddecode.ContainsKey(AssetId))
                {
                    cached = true;
                    result = m_cacheddecode[AssetId];
                }
            }

            // If it's cached, return the cached results
            if (cached)
            {
                decodedReturn(AssetId, result);
            }
            else
            {
                // not cached, so we need to decode it
                // Add to notify list and start decoding.
                // Next request for this asset while it's decoding will only be added to the notify list
                // once this is decoded, requests will be served from the cache and all clients in the notifylist will be updated
                bool decode = false;
                lock (m_notifyList)
                {
                    if (m_notifyList.ContainsKey(AssetId))
                    {
                        m_notifyList[AssetId].Add(decodedReturn);
                    }
                    else
                    {
                        List<DecodedCallback> notifylist = new List<DecodedCallback>();
                        notifylist.Add(decodedReturn);
                        m_notifyList.Add(AssetId, notifylist);
                        decode = true;
                    }
                }
                // Do Decode!
                if (decode)
                {
                    doJ2kDecode(AssetId, assetData);
                }
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// Decode Jpeg2000 Asset Data
        /// </summary>
        /// <param name="AssetId">UUID of Asset</param>
        /// <param name="j2kdata">Byte Array Asset Data </param>
        private bool DoJ2KDecode(UUID assetID, byte[] j2kdata, out OpenJPEG.J2KLayerInfo[] layers)
        {
			int DecodeTime = 0;
            DecodeTime = Environment.TickCount;
            bool decodedSuccessfully = true;
			
			layers = new OpenJPEG.J2KLayerInfo[0]; // Dummy result for if it fails.  Informs that there's only full quality

            try
            {

                AssetTexture texture = new AssetTexture(assetID, j2kdata);
                bool sane = false;

                if (texture.DecodeLayerBoundaries())
                {
                    sane = true;

                    // Sanity check all of the layers
                    for (int i = 0; i < texture.LayerInfo.Length; i++)
                    {
                        if (texture.LayerInfo[i].End > texture.AssetData.Length)
                        {
                            sane = false;
                            break;
                        }
                    }
                }

                if (sane)
                {
                    m_log.InfoFormat("[J2KDecoderModule]: {0} Decode Time: {1}", Environment.TickCount - DecodeTime, assetID); 
                    layers = texture.LayerInfo;
                }
                else
                {
                    m_log.Warn("[J2KDecoderModule]: Failed to decode layer data for texture " + assetID + ", guessing sane defaults");
                    decodedSuccessfully = false;
                    
                    // Layer decoding completely failed. Guess at sane defaults for the layer boundaries
                    layers = CreateDefaultLayers(j2kdata.Length);
                }
                
                fCache.SaveCacheForAsset(assetID, layers); 
                texture = null; // dereference and dispose of ManagedImage
            }
            catch (DllNotFoundException)
            {
                m_log.Error(
                    "[J2KDecoderModule]: OpenJpeg is not installed properly. Decoding disabled!  This will slow down texture performance!  Often times this is because of an old version of GLIBC.  You must have version 2.4 or above!");
                OpenJpegFail = true;
				decodedSuccessfully = false;
            }
            catch (Exception ex)
            {
                m_log.WarnFormat(
                    "[J2KDecoderModule]: JPEG2000 texture decoding threw an exception for {0}, {1}",
                    assetID, ex);
				decodedSuccessfully = false;
            }

			return (decodedSuccessfully);
        }
Exemplo n.º 11
0
        public bool Decode(UUID assetID, byte[] j2kData, out OpenJPEG.J2KLayerInfo[] layers)
        {
            bool decodedSuccessfully = true;
			layers = new OpenJPEG.J2KLayerInfo[0]; // Dummy result for if it fails.  Informs that there's only full quality

            if (! OpenJpegFail)
            {  
                lock (fCache)
                {
                    decodedSuccessfully = fCache.TryLoadCacheForAsset(assetID, out layers);
                }
                
                if (!decodedSuccessfully)
                    decodedSuccessfully = DoJ2KDecode(assetID, j2kData, out layers);
            }

            // Notify Interested Parties
            lock (m_notifyList)
            {
                if (m_notifyList.ContainsKey(assetID))
                {
                    foreach (DecodedCallback d in m_notifyList[assetID])
                    {
                        if (d != null)
                            d.DynamicInvoke(assetID, layers);
                    }
                    m_notifyList.Remove(assetID);
                }
            }
            
            return (decodedSuccessfully);    
        }