Merge branch 'master' of github.com:singularity-viewer/SingularityViewer

This commit is contained in:
Drake Arconis
2013-01-05 20:50:49 -05:00
1413 changed files with 23754 additions and 12090 deletions

27
README
View File

@@ -9,15 +9,30 @@
Sin-gu-la-ri-ty (noun) - a distinctive feature, a uniqueness; a point at which
continuity breaks up; a point in history at which machine becomes smarter than
humanity and/or fuses with it indivisively; or simply a cool sounding word with
my initials in it :)
the initials S.G. in it :)
Singularity Viewer is a Second Life protocol compatible client application. It
can be used to access Second LIfe service as well as a number of other such as
those based upon OpenSim plattform. It is directly based upon source code of
Ascent Viewer by Balseraph Software Group, which is in turn based upon source
code released by Linden Lab, with contributions from various sources.
Singularity Viewer is a SecondLife(tm) protocol compatible client application.
It can be used to access SecondLife services as well as a number of others such
as those based upon the OpenSim platform.
Singulariy is maintained by a small group of volunteers who can be contacted
both, in-world (SingularityViewer group) as well on IRC (#SingularityViewer
@ FreeNode). Bug requests and features requests can be submitted through our
Issue Tracker (http://code.google.com/p/singularity-viewer/issues/list or from
the viewer menu: Help --> Bug Reporting --> Singularity Issue Tracker...)
As this Readme grows out of date, please refer to
http://www.singularityviewer.org/about
00000000011111111112222222222333333333344444444445555555555666666666677777777778
12345678901234567890123456789012345678901234567890123456789012345678901234567890
History
The Singularity viewer was started by Siana Gearz in November 2010 by forking it
from the Ascent Viewer, by Balseraph Software Group, which in turn was based upon
source code modified from the snowglobe source code released by Linden Lab.

View File

@@ -248,6 +248,7 @@ Celierra Darling
VWR-6975
Cron Stardust
VWR-10579
STORM-1919
Cypren Christenson
SNOW-129
SNOW-140

View File

@@ -378,6 +378,14 @@
<boolean>true</boolean>
</map>
<key>WindLightRefresh</key>
<map>
<key>flavor</key>
<string>llsd</string>
<key>trusted-sender</key>
<boolean>true</boolean>
</map>
<key>ParcelVoiceInfo</key>
<map>
<key>flavor</key>
@@ -386,7 +394,6 @@
<boolean>true</boolean>
</map>
<key>ParcelNavigateMedia</key>
<map>
<key>flavor</key>

View File

@@ -17,15 +17,25 @@ find_library(FMODEX_LIBRARY
if (NOT FMODEX_LIBRARY)
set(FMODEX_SDK_DIR CACHE PATH "Path to the FMOD Ex SDK.")
if (FMODEX_SDK_DIR)
find_library(FMODEX_LIBRARY
fmodex_vc fmodexL_vc fmodex fmodexL fmodex64 fmodexL64
PATHS
${FMODEX_SDK_DIR}/api/lib
${FMODEX_SDK_DIR}/api
${FMODEX_SDK_DIR}/lib
${FMODEX_SDK_DIR}
)
if(WORD_SIZE EQUAL 32)
find_library(FMODEX_LIBRARY
fmodex_vc fmodexL_vc fmodex fmodexL
PATHS
${FMODEX_SDK_DIR}/api/lib
${FMODEX_SDK_DIR}/api
${FMODEX_SDK_DIR}/lib
${FMODEX_SDK_DIR}
)
elseif(WORD_SIZE EQUAL 64)
find_library(FMODEX_LIBRARY
fmodex64 fmodexL64
PATHS
${FMODEX_SDK_DIR}/api/lib
${FMODEX_SDK_DIR}/api
${FMODEX_SDK_DIR}/lib
${FMODEX_SDK_DIR}
)
endif(WORD_SIZE EQUAL 32)
endif(FMODEX_SDK_DIR)
if(WINDOWS AND NOT FMODEX_LIBRARY)
set(FMODEX_PROG_DIR "$ENV{PROGRAMFILES}/FMOD SoundSystem/FMOD Programmers API Windows")

View File

@@ -3,16 +3,18 @@
# - Find JSONCpp
# Find the JSONCpp includes and library
# This module defines
# JSONCPP_INCLUDE_DIR, where to find json.h, etc.
# JSONCPP_LIBRARIES, the libraries needed to use jsoncpp.
# JSONCPP_FOUND, If false, do not try to use jsoncpp.
# also defined, but not for general use are
# JSONCPP_LIBRARY, where to find the jsoncpp library.
# JSONCPP_FOUND, System has libjsoncpp.
# JSONCPP_INCLUDE_DIRS - The libjsoncpp include directories.
# JSONCPP_LIBRARIES - The libraries needed to use libjsoncpp.
# JSONCPP_DEFINITIONS - Compiler switches required for using libjsoncpp.
FIND_PATH(JSONCPP_INCLUDE_DIR json/json.h
/usr/local/include
/usr/include
)
FIND_PACKAGE(PkgConfig)
PKG_CHECK_MODULES(PC_JSONCPP jsoncpp)
SET(JSONCPP_DEFINITIONS ${PC_JSONCPP_CFLAGS_OTHER})
FIND_PATH(JSONCPP_INCLUDE_DIR json/reader.h
HINTS ${PC_JSONCPP_INCLUDE_DIR} ${PC_JSONCPP_INCLUDE_DIRS}
PATH_SUFFIXES jsoncpp)
# Get the GCC compiler version
EXEC_PROGRAM(${CMAKE_CXX_COMPILER}
@@ -22,39 +24,16 @@ EXEC_PROGRAM(${CMAKE_CXX_COMPILER}
)
# Try to find a library that was compiled with the same compiler version as we currently use.
SET(JSONCPP_NAMES ${JSONCPP_NAMES} libjson_linux-gcc-${_gcc_COMPILER_VERSION}_libmt.so)
IF (STANDALONE)
# On standalone, assume that the system installed library was compiled with the used compiler.
SET(JSONCPP_NAMES ${JSONCPP_NAMES} libjson.so)
ENDIF (STANDALONE)
FIND_LIBRARY(JSONCPP_LIBRARY
NAMES ${JSONCPP_NAMES}
PATHS /usr/lib /usr/local/lib
)
NAMES libjson_linux-gcc-${_gcc_COMPILER_VERSION}_libmt.so libjsoncpp.so
HINTS ${PC_JSONCPP_LIBDIR} ${PC_JSONCPP_LIBRARY_DIRS}
PATHS /usr/lib /usr/local/lib)
IF (JSONCPP_LIBRARY AND JSONCPP_INCLUDE_DIR)
SET(JSONCPP_LIBRARIES ${JSONCPP_LIBRARY})
SET(JSONCPP_FOUND "YES")
ELSE (JSONCPP_LIBRARY AND JSONCPP_INCLUDE_DIR)
SET(JSONCPP_FOUND "NO")
ENDIF (JSONCPP_LIBRARY AND JSONCPP_INCLUDE_DIR)
SET(JSONCPP_LIBRARIES ${JSONCPP_LIBRARY})
SET(JSONCPP_INCLUDE_DIRS ${JSONCPP_INCLUDE_DIR})
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(JSONCPP DEFAULT_MSG
JSONCPP_LIBRARY JSONCPP_INCLUDE_DIR)
IF (JSONCPP_FOUND)
IF (NOT JSONCPP_FIND_QUIETLY)
MESSAGE(STATUS "Found JSONCpp: ${JSONCPP_LIBRARIES}")
ENDIF (NOT JSONCPP_FIND_QUIETLY)
ELSE (JSONCPP_FOUND)
IF (JSONCPP_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find JSONCpp library")
ENDIF (JSONCPP_FIND_REQUIRED)
ENDIF (JSONCPP_FOUND)
# Deprecated declarations.
SET (NATIVE_JSONCPP_INCLUDE_PATH ${JSONCPP_INCLUDE_DIR} )
GET_FILENAME_COMPONENT (NATIVE_JSONCPP_LIB_PATH ${JSONCPP_LIBRARY} PATH)
MARK_AS_ADVANCED(
JSONCPP_LIBRARY
JSONCPP_INCLUDE_DIR
)
MARK_AS_ADVANCED(JSONCPP_LIBRARY JSONCPP_INCLUDE_DIR)

View File

@@ -11,10 +11,10 @@ else (STANDALONE)
if (LINUX OR WINDOWS AND NOT WORD_SIZE EQUAL 64)
use_prebuilt_binary(gperftools)
endif (LINUX OR WINDOWS AND NOT WORD_SIZE EQUAL 64)
if (WINDOWS)
if (WINDOWS AND NOT DISABLE_TCMALLOC)
set(TCMALLOC_LIBRARIES libtcmalloc_minimal.lib)
set(TCMALLOC_LINKER_FLAGS "/INCLUDE:\"__tcmalloc\"")
endif (WINDOWS)
endif (WINDOWS AND NOT DISABLE_TCMALLOC)
if (LINUX)
if(USE_GOOGLE_PERFTOOLS)
set(TCMALLOC_LIBRARIES tcmalloc)

View File

@@ -2,7 +2,7 @@
include(Prebuilt)
set(JSONCPP_FIND_QUIETLY ON)
set(JSONCPP_FIND_QUIETLY OFF)
set(JSONCPP_FIND_REQUIRED ON)
if (STANDALONE)

View File

@@ -4,9 +4,9 @@ include(Prebuilt)
set(OpenSSL_FIND_QUIETLY ON)
set(OpenSSL_FIND_REQUIRED ON)
if (STANDALONE)
if (STANDALONE OR USE_SYSTEM_OPENSSL)
include(FindOpenSSL)
else (STANDALONE)
else (STANDALONE OR USE_SYSTEM_OPENSSL)
use_prebuilt_binary(openSSL)
if (WINDOWS)
set(OPENSSL_LIBRARIES ssleay32 libeay32)
@@ -14,7 +14,7 @@ else (STANDALONE)
set(OPENSSL_LIBRARIES ssl)
endif (WINDOWS)
set(OPENSSL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include)
endif (STANDALONE)
endif (STANDALONE OR USE_SYSTEM_OPENSSL)
if (LINUX OR DARWIN)
set(CRYPTO_LIBRARIES crypto)

View File

@@ -30,6 +30,7 @@ set(LIBS_SERVER_DIR ${CMAKE_SOURCE_DIR}/${LIBS_SERVER_PREFIX})
set(SCRIPTS_DIR ${CMAKE_SOURCE_DIR}/${SCRIPTS_PREFIX})
set(SERVER_DIR ${CMAKE_SOURCE_DIR}/${SERVER_PREFIX})
set(VIEWER_DIR ${CMAKE_SOURCE_DIR}/${VIEWER_PREFIX})
set(DISABLE_TCMALLOC OFF CACHE BOOL "Disable linkage of TCMalloc. (64bit builds automatically disable TCMalloc)")
set(LL_TESTS OFF CACHE BOOL "Build and run unit and integration tests (disable for build timing runs to reduce variation)")
set(VISTA_ICON OFF CACHE BOOL "Allow vista icon with pre 2008 Visual Studio IDEs. (Assumes replacement old rcdll.dll with new rcdll.dll from win sdk 7.0 or later)")

View File

@@ -236,8 +236,9 @@ void stop_recording_backtraces(void)
channel_ct backtrace DDCN("BACKTRACE"); //!< This debug channel is used for backtraces.
channel_ct statemachine DDCN("STATEMACHINE"); //!< This debug channel is used for output related to class AIStateMachine.
channel_ct caps DDCN("CAPS"); //!< This debug channel is used for output related to Capabilities.
channel_ct curl DDCN("CURL"); //!< This debug channel is used for output related to Curl.
channel_ct curlio DDCN("CURLIO"); //!< This debug channel is used to print debug output of libcurl.
channel_ct curl DDCN("CURL"); //!< This debug channel is used for output related to AICurl.
channel_ct curlio DDCN("CURLIO"); //!< This debug channel is used to print debug output of libcurl. This includes all HTTP network traffic.
channel_ct curltr DDCN("CURLTR"); //!< This debug channel is used to print libcurl API calls.
} // namespace dc
} // namespace DEBUGCHANNELS

View File

@@ -207,6 +207,7 @@ extern CWD_API channel_ct statemachine;
extern CWD_API channel_ct caps;
extern CWD_API channel_ct curl;
extern CWD_API channel_ct curlio;
extern CWD_API channel_ct curltr;
#endif

View File

@@ -766,13 +766,14 @@ Commands:
Command-options for "configure":
We use cmake variables to change the build configuration.
-DSERVER:BOOL=OFF Don't configure simulator/dataserver/etc
-DVIEWER:BOOL=OFF Don't configure the viewer
-DPACKAGE:BOOL=ON Create "package" target to make installers
-DLOCALIZESETUP:BOOL=ON Create one win_setup target per supported language
-DLL_TESTS:BOOL=OFF Don't generate unit test projects
-DEXAMPLEPLUGIN:BOOL=OFF Don't generate example plugin project
-VISTA_ICON:BOOL=ON Allow pre-2008 VS to use vista-optimized resource file. (Requires updated rcdll.dll!)
-DSERVER:BOOL=OFF Don't configure simulator/dataserver/etc
-DVIEWER:BOOL=OFF Don't configure the viewer
-DPACKAGE:BOOL=ON Create "package" target to make installers
-DLOCALIZESETUP:BOOL=ON Create one win_setup target per supported language
-DLL_TESTS:BOOL=OFF Don't generate unit test projects
-DEXAMPLEPLUGIN:BOOL=OFF Don't generate example plugin project
-DDISABLE_TCMALLOC:BOOL=ON Disable linkage of TCMalloc. (64bit builds automatically disable TCMalloc)
-DVISTA_ICON:BOOL=ON Allow pre-2008 VS to use vista-optimized resource file. (Requires updated rcdll.dll!)
Examples:
Set up a viewer-only project for your system:

View File

@@ -7,14 +7,15 @@ include(00-Common)
# OPENJPEG version number, useful for packaging and doxygen doc:
set(OPENJPEG_VERSION_MAJOR 1)
set(OPENJPEG_VERSION_MINOR 4)
set(OPENJPEG_VERSION_BUILD 0)
set(OPENJPEG_VERSION_MINOR 5)
set(OPENJPEG_VERSION_BUILD 2)
set(OPENJPEG_VERSION
"${OPENJPEG_VERSION_MAJOR}.${OPENJPEG_VERSION_MINOR}.${OPENJPEG_VERSION_BUILD}")
set(openjpeg_SOURCE_FILES
bio.c
cio.c
cidx_manager.c
dwt.c
event.c
image.c
@@ -26,20 +27,26 @@ set(openjpeg_SOURCE_FILES
mqc.c
openjpeg.c
pi.c
phix_manager.c
ppix_manager.c
raw.c
t1.c
t2.c
tcd.c
tgt.c
thix_manager.c
tpix_manager.c
)
set(openjpeg_HEADER_FILES
bio.h
cio.h
cidx_manager.h
dwt.h
event.h
event.h
fix.h
image.h
indexbox_manager.h
int.h
j2k.h
j2k_lib.h
@@ -48,6 +55,7 @@ set(openjpeg_HEADER_FILES
mct.h
mqc.h
openjpeg.h
opj_config.h
opj_includes.h
opj_malloc.h
pi.h

View File

@@ -0,0 +1,211 @@
/*
* $Id: cidx_manager.c 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $
*
* Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
* Copyright (c) 2002-2011, Professor Benoit Macq
* Copyright (c) 2003-2004, Yannick Verschueren
* Copyright (c) 2010-2011, Kaori Hagihara
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "opj_includes.h"
/*
* Write CPTR Codestream finder box
*
* @param[in] coff offset of j2k codestream
* @param[in] clen length of j2k codestream
* @param[in] cio file output handle
*/
void write_cptr(int coff, int clen, opj_cio_t *cio);
/*
* Write main header index table (box)
*
* @param[in] coff offset of j2k codestream
* @param[in] cstr_info codestream information
* @param[in] cio file output handle
* @return length of mainmhix box
*/
int write_mainmhix( int coff, opj_codestream_info_t cstr_info, opj_cio_t *cio);
/*
* Check if EPH option is used
*
* @param[in] coff offset of j2k codestream
* @param[in] markers marker information
* @param[in] marknum number of markers
* @param[in] cio file output handle
* @return true if EPH is used
*/
opj_bool check_EPHuse( int coff, opj_marker_info_t *markers, int marknum, opj_cio_t *cio);
int write_cidx( int offset, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t cstr_info, int j2klen)
{
int len, i, lenp;
opj_jp2_box_t *box;
int num_box = 0;
opj_bool EPHused;
(void)image; /* unused ? */
lenp = -1;
box = (opj_jp2_box_t *)opj_calloc( 32, sizeof(opj_jp2_box_t));
for (i=0;i<2;i++){
if(i)
cio_seek( cio, lenp);
lenp = cio_tell( cio);
cio_skip( cio, 4); /* L [at the end] */
cio_write( cio, JPIP_CIDX, 4); /* CIDX */
write_cptr( offset, cstr_info.codestream_size, cio);
write_manf( i, num_box, box, cio);
num_box = 0;
box[num_box].length = write_mainmhix( offset, cstr_info, cio);
box[num_box].type = JPIP_MHIX;
num_box++;
box[num_box].length = write_tpix( offset, cstr_info, j2klen, cio);
box[num_box].type = JPIP_TPIX;
num_box++;
box[num_box].length = write_thix( offset, cstr_info, cio);
box[num_box].type = JPIP_THIX;
num_box++;
EPHused = check_EPHuse( offset, cstr_info.marker, cstr_info.marknum, cio);
box[num_box].length = write_ppix( offset, cstr_info, EPHused, j2klen, cio);
box[num_box].type = JPIP_PPIX;
num_box++;
box[num_box].length = write_phix( offset, cstr_info, EPHused, j2klen, cio);
box[num_box].type = JPIP_PHIX;
num_box++;
len = cio_tell( cio)-lenp;
cio_seek( cio, lenp);
cio_write( cio, len, 4); /* L */
cio_seek( cio, lenp+len);
}
opj_free( box);
return len;
}
void write_cptr(int coff, int clen, opj_cio_t *cio)
{
int len, lenp;
lenp = cio_tell( cio);
cio_skip( cio, 4); /* L [at the end] */
cio_write( cio, JPIP_CPTR, 4); /* T */
cio_write( cio, 0, 2); /* DR A PRECISER !! */
cio_write( cio, 0, 2); /* CONT */
cio_write( cio, coff, 8); /* COFF A PRECISER !! */
cio_write( cio, clen, 8); /* CLEN */
len = cio_tell( cio) - lenp;
cio_seek( cio, lenp);
cio_write( cio, len, 4); /* L */
cio_seek( cio, lenp+len);
}
void write_manf(int second, int v, opj_jp2_box_t *box, opj_cio_t *cio)
{
int len, lenp, i;
lenp = cio_tell( cio);
cio_skip( cio, 4); /* L [at the end] */
cio_write( cio, JPIP_MANF,4); /* T */
if (second){ /* Write only during the second pass */
for( i=0; i<v; i++){
cio_write( cio, box[i].length, 4); /* Box length */
cio_write( cio, box[i].type, 4); /* Box type */
}
}
len = cio_tell( cio) - lenp;
cio_seek( cio, lenp);
cio_write( cio, len, 4); /* L */
cio_seek( cio, lenp+len);
}
int write_mainmhix( int coff, opj_codestream_info_t cstr_info, opj_cio_t *cio)
{
int i;
int len, lenp;
lenp = cio_tell( cio);
cio_skip( cio, 4); /* L [at the end] */
cio_write( cio, JPIP_MHIX, 4); /* MHIX */
cio_write( cio, cstr_info.main_head_end-cstr_info.main_head_start+1, 8); /* TLEN */
for(i = 1; i < cstr_info.marknum; i++){ /* Marker restricted to 1 apparition, skip SOC marker */
cio_write( cio, cstr_info.marker[i].type, 2);
cio_write( cio, 0, 2);
cio_write( cio, cstr_info.marker[i].pos-coff, 8);
cio_write( cio, cstr_info.marker[i].len, 2);
}
len = cio_tell( cio) - lenp;
cio_seek( cio, lenp);
cio_write( cio, len, 4); /* L */
cio_seek( cio, lenp+len);
return len;
}
opj_bool check_EPHuse( int coff, opj_marker_info_t *markers, int marknum, opj_cio_t *cio)
{
opj_bool EPHused = OPJ_FALSE;
int i=0;
int org_pos;
unsigned int Scod;
for(i = 0; i < marknum; i++){
if( markers[i].type == J2K_MS_COD){
org_pos = cio_tell( cio);
cio_seek( cio, coff+markers[i].pos+2);
Scod = cio_read( cio, 1);
if( ((Scod >> 2) & 1))
EPHused = OPJ_TRUE;
cio_seek( cio, org_pos);
break;
}
}
return EPHused;
}

View File

@@ -0,0 +1,56 @@
/*
* $Id: cidx_manager.h 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $
*
* Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
* Copyright (c) 2002-2011, Professor Benoit Macq
* Copyright (c) 2003-2004, Yannick Verschueren
* Copyright (c) 2010-2011, Kaori Hagihara
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*! \file
* \brief Modification of jpip.h from 2KAN indexer
*/
#ifndef CIDX_MANAGER_H_
# define CIDX_MANAGER_H_
#include "openjpeg.h"
/*
* Write Codestream index box (superbox)
*
* @param[in] offset offset of j2k codestream
* @param[in] cio file output handle
* @param[in] image image data
* @param[in] cstr_info codestream information
* @param[in] j2klen length of j2k codestream
* @return length of cidx box
*/
int write_cidx( int offset, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t cstr_info, int j2klen);
#endif /* !CIDX_MANAGER_H_ */

View File

@@ -126,13 +126,13 @@ unsigned char *cio_getbp(opj_cio_t *cio) {
/*
* Write a byte.
*/
bool cio_byteout(opj_cio_t *cio, unsigned char v) {
opj_bool cio_byteout(opj_cio_t *cio, unsigned char v) {
if (cio->bp >= cio->end) {
opj_event_msg(cio->cinfo, EVT_ERROR, "write error\n");
return false;
return OPJ_FALSE;
}
*cio->bp++ = v;
return true;
return OPJ_TRUE;
}
/*
@@ -152,7 +152,7 @@ unsigned char cio_bytein(opj_cio_t *cio) {
* v : value to write
* n : number of bytes to write
*/
unsigned int cio_write(opj_cio_t *cio, unsigned int v, int n) {
unsigned int cio_write(opj_cio_t *cio, unsigned int64 v, int n) {
int i;
for (i = n - 1; i >= 0; i--) {
if( !cio_byteout(cio, (unsigned char) ((v >> (i << 3)) & 0xff)) )

View File

@@ -31,6 +31,13 @@
#ifndef __CIO_H
#define __CIO_H
#if defined(_MSC_VER) || defined(__BORLANDC__)
#define int64 __int64
#else
#define int64 long long
#endif
/**
@file cio.h
@brief Implementation of a byte input-output process (CIO)
@@ -63,7 +70,7 @@ Write some bytes
@param n Number of bytes to write
@return Returns the number of bytes written or 0 if an error occured
*/
unsigned int cio_write(opj_cio_t *cio, unsigned int v, int n);
unsigned int cio_write(opj_cio_t *cio, unsigned int64 v, int n);
/**
Read some bytes
@param cio CIO handle

View File

@@ -64,12 +64,12 @@ typedef struct v4dwt_local {
int cas ;
} v4dwt_t ;
static const float dwt_alpha = 1.586134342f; // 12994
static const float dwt_beta = 0.052980118f; // 434
static const float dwt_gamma = -0.882911075f; // -7233
static const float dwt_delta = -0.443506852f; // -3633
static const float dwt_alpha = 1.586134342f; /* 12994 */
static const float dwt_beta = 0.052980118f; /* 434 */
static const float dwt_gamma = -0.882911075f; /* -7233 */
static const float dwt_delta = -0.443506852f; /* -3633 */
static const float K = 1.230174105f; // 10078
static const float K = 1.230174105f; /* 10078 */
/* FIXME: What is this constant? */
static const float c13318 = 1.625732422f;
@@ -527,7 +527,7 @@ static void dwt_decode_tile(opj_tcd_tilecomp_t* tilec, int numres, DWT1DFN dwt_1
int w = tilec->x1 - tilec->x0;
h.mem = (int *)opj_aligned_malloc(dwt_decode_max_resolution(tr, numres) * sizeof(int));
h.mem = (int*)opj_aligned_malloc(dwt_decode_max_resolution(tr, numres) * sizeof(int));
v.mem = h.mem;
while( --numres) {
@@ -570,7 +570,7 @@ static void v4dwt_interleave_h(v4dwt_t* restrict w, float* restrict a, int x, in
int count = w->sn;
int i, k;
for(k = 0; k < 2; ++k){
if (count + 3 * x < size && ((long) a & 0x0f) == 0 && ((long) bi & 0x0f) == 0 && (x & 0x0f) == 0) {
if (count + 3 * x < size && ((size_t) a & 0x0f) == 0 && ((size_t) bi & 0x0f) == 0 && (x & 0x0f) == 0) {
/* Fast code path */
for(i = 0; i < count; ++i){
int j = i;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, Hervé Drolon, FreeImage Team
* Copyright (c) 2005, Herve Drolon, FreeImage Team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,6 +26,42 @@
#include "opj_includes.h"
/* ==========================================================
Utility functions
==========================================================*/
#ifdef OPJ_CODE_NOT_USED
#ifndef _WIN32
static char*
i2a(unsigned i, char *a, unsigned r) {
if (i/r > 0) a = i2a(i/r,a,r);
*a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i%r];
return a+1;
}
/**
Transforms integer i into an ascii string and stores the result in a;
string is encoded in the base indicated by r.
@param i Number to be converted
@param a String result
@param r Base of value; must be in the range 2 - 36
@return Returns a
*/
static char *
_itoa(int i, char *a, int r) {
r = ((r < 2) || (r > 36)) ? 10 : r;
if(i < 0) {
*a = '-';
*i2a(-i, a+1, r) = 0;
}
else *i2a(i, a, r) = 0;
return a;
}
#endif /* !_WIN32 */
#endif
/* ----------------------------------------------------------------------- */
opj_event_mgr_t* OPJ_CALLCONV opj_set_event_mgr(opj_common_ptr cinfo, opj_event_mgr_t *event_mgr, void *context) {
if(cinfo) {
opj_event_mgr_t *previous = cinfo->event_mgr;
@@ -37,7 +73,7 @@ opj_event_mgr_t* OPJ_CALLCONV opj_set_event_mgr(opj_common_ptr cinfo, opj_event_
return NULL;
}
bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ...) {
opj_bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ...) {
#define MSG_SIZE 512 /* 512 bytes should be more than enough for a short message */
opj_msg_callback msg_handler = NULL;
@@ -57,30 +93,29 @@ bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ...) {
break;
}
if(msg_handler == NULL) {
return false;
return OPJ_FALSE;
}
} else {
return false;
return OPJ_FALSE;
}
if ((fmt != NULL) && (event_mgr != NULL)) {
va_list arg;
int str_length/*, i, j*/; /* UniPG */
char message[MSG_SIZE];
memset(message, 0, MSG_SIZE);
/* initialize the optional parameter list */
va_start(arg, fmt);
/* check the length of the format string */
str_length = (strlen(fmt) > MSG_SIZE) ? MSG_SIZE : strlen(fmt);
/* parse the format string and put the result in 'message' */
vsprintf(message, fmt, arg); /* UniPG */
str_length = vsnprintf(message, MSG_SIZE, fmt, arg); /* UniPG */
/* deinitialize the optional parameter list */
va_end(arg);
/* output the message to the user program */
msg_handler(message, cinfo->client_data);
if( str_length > -1 && str_length < MSG_SIZE )
msg_handler(message, cinfo->client_data);
else return OPJ_FALSE;
}
return true;
return OPJ_TRUE;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, Herv<EFBFBD> Drolon, FreeImage Team
* Copyright (c) 2005, Herve Drolon, FreeImage Team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -49,7 +49,7 @@ Write formatted data to a string and send the string to a user callback.
@param fmt Format-control string (plus optionnal arguments)
@return Returns true if successful, returns false otherwise
*/
bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ...);
opj_bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ...);
/* ----------------------------------------------------------------------- */
/*@}*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, Herv Drolon, FreeImage Team
* Copyright (c) 2005, Herve Drolon, FreeImage Team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,7 +28,6 @@
opj_image_t* opj_image_create0(void) {
opj_image_t *image = (opj_image_t*)opj_calloc(1, sizeof(opj_image_t));
image->comps=NULL;
return image;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, Herv<EFBFBD> Drolon, FreeImage Team
* Copyright (c) 2005, Herve Drolon, FreeImage Team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -0,0 +1,118 @@
/*
* $Id: indexbox_manager.h 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $
*
* Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
* Copyright (c) 2002-2011, Professor Benoit Macq
* Copyright (c) 2003-2004, Yannick Verschueren
* Copyright (c) 2010-2011, Kaori Hagihara
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*! \file
* \brief Modification of jpip.c from 2KAN indexer
*/
#ifndef INDEXBOX_MANAGER_H_
# define INDEXBOX_MANAGER_H_
#include "openjpeg.h"
#include "j2k.h" /* needed to use jp2.h */
#include "jp2.h"
#define JPIP_CIDX 0x63696478 /* Codestream index */
#define JPIP_CPTR 0x63707472 /* Codestream Finder Box */
#define JPIP_MANF 0x6d616e66 /* Manifest Box */
#define JPIP_FAIX 0x66616978 /* Fragment array Index box */
#define JPIP_MHIX 0x6d686978 /* Main Header Index Table */
#define JPIP_TPIX 0x74706978 /* Tile-part Index Table box */
#define JPIP_THIX 0x74686978 /* Tile header Index Table box */
#define JPIP_PPIX 0x70706978 /* Precinct Packet Index Table box */
#define JPIP_PHIX 0x70686978 /* Packet Header index Table */
#define JPIP_FIDX 0x66696478 /* File Index */
#define JPIP_FPTR 0x66707472 /* File Finder */
#define JPIP_PRXY 0x70727879 /* Proxy boxes */
#define JPIP_IPTR 0x69707472 /* Index finder box */
#define JPIP_PHLD 0x70686c64 /* Place holder */
/*
* Write tile-part Index table box (superbox)
*
* @param[in] coff offset of j2k codestream
* @param[in] cstr_info codestream information
* @param[in] j2klen length of j2k codestream
* @param[in] cio file output handle
* @return length of tpix box
*/
int write_tpix( int coff, opj_codestream_info_t cstr_info, int j2klen, opj_cio_t *cio);
/*
* Write tile header index table box (superbox)
*
* @param[in] coff offset of j2k codestream
* @param[in] cstr_info codestream information pointer
* @param[in] cio file output handle
* @return length of thix box
*/
int write_thix( int coff, opj_codestream_info_t cstr_info, opj_cio_t *cio);
/*
* Write precinct packet index table box (superbox)
*
* @param[in] coff offset of j2k codestream
* @param[in] cstr_info codestream information
* @param[in] EPHused true if EPH option used
* @param[in] j2klen length of j2k codestream
* @param[in] cio file output handle
* @return length of ppix box
*/
int write_ppix( int coff, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio);
/*
* Write packet header index table box (superbox)
*
* @param[in] coff offset of j2k codestream
* @param[in] cstr_info codestream information
* @param[in] EPHused true if EPH option used
* @param[in] j2klen length of j2k codestream
* @param[in] cio file output handle
* @return length of ppix box
*/
int write_phix( int coff, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio);
/*
* Wriet manifest box (box)
*
* @param[in] second number to be visited
* @param[in] v number of boxes
* @param[in] box box to be manifested
* @param[in] cio file output handle
*/
void write_manf(int second, int v, opj_jp2_box_t *box, opj_cio_t *cio);
#endif /* !INDEXBOX_MANAGER_H_ */

View File

@@ -6,6 +6,7 @@
* Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
* Copyright (c) 2005, Herve Drolon, FreeImage Team
* Copyright (c) 2006-2007, Parvatha Elangovan
* Copyright (c) 2010-2011, Kaori Hagihara
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -228,6 +229,23 @@ Read an unknown marker
@param j2k J2K handle
*/
static void j2k_read_unk(opj_j2k_t *j2k);
/**
Add main header marker information
@param cstr_info Codestream information structure
@param type marker type
@param pos byte offset of marker segment
@param len length of marker segment
*/
static void j2k_add_mhmarker(opj_codestream_info_t *cstr_info, unsigned short int type, int pos, int len);
/**
Add tile header marker information
@param tileno tile index number
@param cstr_info Codestream information structure
@param type marker type
@param pos byte offset of marker segment
@param len length of marker segment
*/
static void j2k_add_tlmarker( int tileno, opj_codestream_info_t *cstr_info, unsigned short int type, int pos, int len);
/*@}*/
@@ -258,80 +276,6 @@ char *j2k_convert_progression_order(OPJ_PROG_ORDER prg_order){
return po->str_prog;
}
void j2k_dump_image(FILE *fd, opj_image_t * img) {
int compno;
fprintf(fd, "image {\n");
fprintf(fd, " x0=%d, y0=%d, x1=%d, y1=%d\n", img->x0, img->y0, img->x1, img->y1);
fprintf(fd, " numcomps=%d\n", img->numcomps);
for (compno = 0; compno < img->numcomps; compno++) {
opj_image_comp_t *comp = &img->comps[compno];
fprintf(fd, " comp %d {\n", compno);
fprintf(fd, " dx=%d, dy=%d\n", comp->dx, comp->dy);
fprintf(fd, " prec=%d\n", comp->prec);
//fprintf(fd, " bpp=%d\n", comp->bpp);
fprintf(fd, " sgnd=%d\n", comp->sgnd);
fprintf(fd, " }\n");
}
fprintf(fd, "}\n");
}
void j2k_dump_cp(FILE *fd, opj_image_t * img, opj_cp_t * cp) {
int tileno, compno, layno, bandno, resno, numbands;
fprintf(fd, "coding parameters {\n");
fprintf(fd, " tx0=%d, ty0=%d\n", cp->tx0, cp->ty0);
fprintf(fd, " tdx=%d, tdy=%d\n", cp->tdx, cp->tdy);
fprintf(fd, " tw=%d, th=%d\n", cp->tw, cp->th);
for (tileno = 0; tileno < cp->tw * cp->th; tileno++) {
opj_tcp_t *tcp = &cp->tcps[tileno];
fprintf(fd, " tile %d {\n", tileno);
fprintf(fd, " csty=%x\n", tcp->csty);
fprintf(fd, " prg=%d\n", tcp->prg);
fprintf(fd, " numlayers=%d\n", tcp->numlayers);
fprintf(fd, " mct=%d\n", tcp->mct);
fprintf(fd, " rates=");
for (layno = 0; layno < tcp->numlayers; layno++) {
fprintf(fd, "%.1f ", tcp->rates[layno]);
}
fprintf(fd, "\n");
for (compno = 0; compno < img->numcomps; compno++) {
opj_tccp_t *tccp = &tcp->tccps[compno];
fprintf(fd, " comp %d {\n", compno);
fprintf(fd, " csty=%x\n", tccp->csty);
fprintf(fd, " numresolutions=%d\n", tccp->numresolutions);
fprintf(fd, " cblkw=%d\n", tccp->cblkw);
fprintf(fd, " cblkh=%d\n", tccp->cblkh);
fprintf(fd, " cblksty=%x\n", tccp->cblksty);
fprintf(fd, " qmfbid=%d\n", tccp->qmfbid);
fprintf(fd, " qntsty=%d\n", tccp->qntsty);
fprintf(fd, " numgbits=%d\n", tccp->numgbits);
fprintf(fd, " roishift=%d\n", tccp->roishift);
fprintf(fd, " stepsizes=");
numbands = tccp->qntsty == J2K_CCP_QNTSTY_SIQNT ? 1 : tccp->numresolutions * 3 - 2;
for (bandno = 0; bandno < numbands; bandno++) {
fprintf(fd, "(%d,%d) ", tccp->stepsizes[bandno].mant,
tccp->stepsizes[bandno].expn);
}
fprintf(fd, "\n");
if (tccp->csty & J2K_CCP_CSTY_PRT) {
fprintf(fd, " prcw=");
for (resno = 0; resno < tccp->numresolutions; resno++) {
fprintf(fd, "%d ", tccp->prcw[resno]);
}
fprintf(fd, "\n");
fprintf(fd, " prch=");
for (resno = 0; resno < tccp->numresolutions; resno++) {
fprintf(fd, "%d ", tccp->prch[resno]);
}
fprintf(fd, "\n");
}
fprintf(fd, " }\n");
}
fprintf(fd, " }\n");
}
fprintf(fd, "}\n");
}
/* ----------------------------------------------------------------------- */
static int j2k_get_num_tp(opj_cp_t *cp,int pino,int tileno){
char *prog;
@@ -371,6 +315,9 @@ static int j2k_get_num_tp(opj_cp_t *cp,int pino,int tileno){
/** mem allocation for TLM marker*/
int j2k_calculate_tp(opj_cp_t *cp,int img_numcomp,opj_image_t *image,opj_j2k_t *j2k ){
int pino,tileno,totnum_tp=0;
OPJ_ARG_NOT_USED(img_numcomp);
j2k->cur_totnum_tp = (int *) opj_malloc(cp->tw * cp->th * sizeof(int));
for (tileno = 0; tileno < cp->tw * cp->th; tileno++) {
int cur_totnum_tp = 0;
@@ -399,12 +346,14 @@ static void j2k_write_soc(opj_j2k_t *j2k) {
opj_cio_t *cio = j2k->cio;
cio_write(cio, J2K_MS_SOC, 2);
if(j2k->cstr_info)
j2k_add_mhmarker(j2k->cstr_info, J2K_MS_SOC, cio_tell(cio), 0);
/* UniPG>> */
#ifdef USE_JPWL
/* update markers struct */
j2k_add_marker(j2k->cstr_info, J2K_MS_SOC, cio_tell(cio) - 2, 2);
#endif /* USE_JPWL */
/* <<UniPG */
}
@@ -425,7 +374,7 @@ static void j2k_write_siz(opj_j2k_t *j2k) {
opj_cio_t *cio = j2k->cio;
opj_image_t *image = j2k->image;
opj_cp_t *cp = j2k->cp;
cio_write(cio, J2K_MS_SIZ, 2); /* SIZ */
lenp = cio_tell(cio);
cio_skip(cio, 2);
@@ -448,6 +397,9 @@ static void j2k_write_siz(opj_j2k_t *j2k) {
cio_seek(cio, lenp);
cio_write(cio, len, 2); /* Lsiz */
cio_seek(cio, lenp + len);
if(j2k->cstr_info)
j2k_add_mhmarker(j2k->cstr_info, J2K_MS_SIZ, lenp, len);
}
static void j2k_read_siz(opj_j2k_t *j2k) {
@@ -516,6 +468,12 @@ static void j2k_read_siz(opj_j2k_t *j2k) {
}
#endif /* USE_JPWL */
/* prevent division by zero */
if (!(cp->tdx * cp->tdy)) {
opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: invalid tile size (tdx: %d, tdy: %d)\n", cp->tdx, cp->tdy);
return;
}
image->comps = (opj_image_comp_t*) opj_calloc(image->numcomps, sizeof(opj_image_comp_t));
for (i = 0; i < image->numcomps; i++) {
int tmp, w, h;
@@ -554,6 +512,12 @@ static void j2k_read_siz(opj_j2k_t *j2k) {
}
#endif /* USE_JPWL */
/* prevent division by zero */
if (!(image->comps[i].dx * image->comps[i].dy)) {
opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: invalid component size (dx: %d, dy: %d)\n", image->comps[i].dx, image->comps[i].dy);
return;
}
/* TODO: unused ? */
w = int_ceildiv(image->x1 - image->x0, image->comps[i].dx);
h = int_ceildiv(image->y1 - image->y0, image->comps[i].dy);
@@ -606,7 +570,17 @@ static void j2k_read_siz(opj_j2k_t *j2k) {
#endif /* USE_JPWL */
cp->tcps = (opj_tcp_t*) opj_calloc(cp->tw * cp->th, sizeof(opj_tcp_t));
if (cp->tcps == NULL)
{
opj_event_msg(j2k->cinfo, EVT_ERROR, "Out of memory\n");
return;
}
cp->tileno = (int*) opj_malloc(cp->tw * cp->th * sizeof(int));
if (cp->tileno == NULL)
{
opj_event_msg(j2k->cinfo, EVT_ERROR, "Out of memory\n");
return;
}
cp->tileno_size = 0;
#ifdef USE_JPWL
@@ -678,6 +652,11 @@ static void j2k_write_com(opj_j2k_t *j2k) {
cio_seek(cio, lenp);
cio_write(cio, len, 2);
cio_seek(cio, lenp + len);
if(j2k->cstr_info)
j2k_add_mhmarker(j2k->cstr_info, J2K_MS_COM, lenp, len);
}
}
@@ -721,12 +700,18 @@ static void j2k_read_cox(opj_j2k_t *j2k, int compno) {
tccp->numresolutions = cio_read(cio, 1) + 1; /* SPcox (D) */
// If user wants to remove more resolutions than the codestream contains, return error
/* If user wants to remove more resolutions than the codestream contains, return error*/
if (cp->reduce >= tccp->numresolutions) {
opj_event_msg(j2k->cinfo, EVT_ERROR, "Error decoding component %d.\nThe number of resolutions to remove is higher than the number "
"of resolutions of this component\nModify the cp_reduce parameter.\n\n", compno);
j2k->state |= J2K_STATE_ERR;
}
if( tccp->numresolutions > J2K_MAXRLVLS ) {
opj_event_msg(j2k->cinfo, EVT_ERROR, "Error decoding component %d.\nThe number of resolutions is too big: %d vs max= %d. Truncating.\n\n",
compno, tccp->numresolutions, J2K_MAXRLVLS);
j2k->state |= J2K_STATE_ERR;
tccp->numresolutions = J2K_MAXRLVLS;
}
tccp->cblkw = cio_read(cio, 1) + 2; /* SPcox (E) */
tccp->cblkh = cio_read(cio, 1) + 2; /* SPcox (F) */
@@ -781,6 +766,10 @@ static void j2k_write_cod(opj_j2k_t *j2k) {
cio_seek(cio, lenp);
cio_write(cio, len, 2); /* Lcod */
cio_seek(cio, lenp + len);
if(j2k->cstr_info)
j2k_add_mhmarker(j2k->cstr_info, J2K_MS_COD, lenp, len);
}
static void j2k_read_cod(opj_j2k_t *j2k) {
@@ -846,6 +835,12 @@ static void j2k_read_coc(opj_j2k_t *j2k) {
len = cio_read(cio, 2); /* Lcoc */
compno = cio_read(cio, image->numcomps <= 256 ? 1 : 2); /* Ccoc */
if (compno >= image->numcomps) {
opj_event_msg(j2k->cinfo, EVT_ERROR,
"bad component number in COC (%d out of a maximum of %d)\n",
compno, image->numcomps);
return;
}
tcp->tccps[compno].csty = cio_read(cio, 1); /* Scoc */
j2k_read_cox(j2k, compno);
}
@@ -909,6 +904,15 @@ static void j2k_read_qcx(opj_j2k_t *j2k, int compno, int len) {
};
};
#else
/* We check whether there are too many subbands */
if ((numbands < 0) || (numbands >= J2K_MAXBANDS)) {
opj_event_msg(j2k->cinfo, EVT_WARNING ,
"bad number of subbands in Sqcx (%d) regarding to J2K_MAXBANDS (%d) \n"
"- limiting number of bands to J2K_MAXBANDS and try to move to the next markers\n", numbands, J2K_MAXBANDS);
}
#endif /* USE_JPWL */
for (bandno = 0; bandno < numbands; bandno++) {
@@ -921,8 +925,10 @@ static void j2k_read_qcx(opj_j2k_t *j2k, int compno, int len) {
expn = tmp >> 11;
mant = tmp & 0x7ff;
}
tccp->stepsizes[bandno].expn = expn;
tccp->stepsizes[bandno].mant = mant;
if (bandno < J2K_MAXBANDS){
tccp->stepsizes[bandno].expn = expn;
tccp->stepsizes[bandno].mant = mant;
}
}
/* Add Antonin : if scalar_derived -> compute other stepsizes */
@@ -950,6 +956,9 @@ static void j2k_write_qcd(opj_j2k_t *j2k) {
cio_seek(cio, lenp);
cio_write(cio, len, 2); /* Lqcd */
cio_seek(cio, lenp + len);
if(j2k->cstr_info)
j2k_add_mhmarker(j2k->cstr_info, J2K_MS_QCD, lenp, len);
}
static void j2k_read_qcd(opj_j2k_t *j2k) {
@@ -986,7 +995,7 @@ static void j2k_read_qcc(opj_j2k_t *j2k) {
int len, compno;
int numcomp = j2k->image->numcomps;
opj_cio_t *cio = j2k->cio;
len = cio_read(cio, 2); /* Lqcc */
compno = cio_read(cio, numcomp <= 256 ? 1 : 2); /* Cqcc */
@@ -1013,9 +1022,16 @@ static void j2k_read_qcc(opj_j2k_t *j2k) {
/* keep your private count of tiles */
backup_compno++;
};
}
#endif /* USE_JPWL */
if ((compno < 0) || (compno >= numcomp)) {
opj_event_msg(j2k->cinfo, EVT_ERROR,
"bad component number in QCC (%d out of a maximum of %d)\n",
compno, j2k->image->numcomps);
return;
}
j2k_read_qcx(j2k, compno, len - 2 - (numcomp <= 256 ? 1 : 2));
}
@@ -1271,6 +1287,10 @@ static void j2k_write_sot(opj_j2k_t *j2k) {
j2k_add_marker(j2k->cstr_info, J2K_MS_SOT, j2k->sot_start, len + 2);
#endif /* USE_JPWL */
/* <<UniPG */
if( j2k->cstr_info && j2k->cur_tp_num==0){
j2k_add_tlmarker( j2k->curtileno, j2k->cstr_info, J2K_MS_SOT, lenp, len);
}
}
static void j2k_read_sot(opj_j2k_t *j2k) {
@@ -1354,6 +1374,11 @@ static void j2k_read_sot(opj_j2k_t *j2k) {
partno = cio_read(cio, 1);
numparts = cio_read(cio, 1);
if (partno >= numparts) {
opj_event_msg(j2k->cinfo, EVT_WARNING, "SOT marker inconsistency in tile %d: tile-part index greater (%d) than number of tile-parts (%d)\n", tileno, partno, numparts);
numparts = partno+1;
}
j2k->curtileno = tileno;
j2k->cur_tp_num = partno;
@@ -1369,15 +1394,14 @@ static void j2k_read_sot(opj_j2k_t *j2k) {
j2k->cstr_info->tile[tileno].tileno = tileno;
j2k->cstr_info->tile[tileno].start_pos = cio_tell(cio) - 12;
j2k->cstr_info->tile[tileno].end_pos = j2k->cstr_info->tile[tileno].start_pos + totlen - 1;
j2k->cstr_info->tile[tileno].num_tps = numparts;
if (numparts)
j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_malloc(numparts * sizeof(opj_tp_info_t));
else
j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_malloc(10 * sizeof(opj_tp_info_t)); // Fixme (10)
}
else {
} else {
j2k->cstr_info->tile[tileno].end_pos += totlen;
}
}
j2k->cstr_info->tile[tileno].num_tps = numparts;
if (numparts)
j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_realloc(j2k->cstr_info->tile[tileno].tp, numparts * sizeof(opj_tp_info_t));
else
j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_realloc(j2k->cstr_info->tile[tileno].tp, 10 * sizeof(opj_tp_info_t)); /* Fixme (10)*/
j2k->cstr_info->tile[tileno].tp[partno].tp_start_pos = cio_tell(cio) - 12;
j2k->cstr_info->tile[tileno].tp[partno].tp_end_pos =
j2k->cstr_info->tile[tileno].tp[partno].tp_start_pos + totlen - 1;
@@ -1413,6 +1437,11 @@ static void j2k_write_sod(opj_j2k_t *j2k, void *tile_coder) {
tcd->cur_tp_num = j2k->cur_tp_num;
cio_write(cio, J2K_MS_SOD, 2);
if( j2k->cstr_info && j2k->cur_tp_num==0){
j2k_add_tlmarker( j2k->curtileno, j2k->cstr_info, J2K_MS_SOD, cio_tell(cio), 0);
}
if (j2k->curtileno == 0) {
j2k->sod_start = cio_tell(cio) + j2k->pos_correction;
}
@@ -1489,6 +1518,24 @@ static void j2k_read_sod(opj_j2k_t *j2k) {
truncate = 1; /* Case of a truncate codestream */
}
{/* chop padding bytes: */
unsigned char *s, *e;
s = cio_getbp(cio);
e = s + len;
if(len > 8) s = e - 8;
if(e[-2] == 0x00 && e[-1] == 0x00) /* padding bytes */
{
while(e > s)
{
if(e[-2] == 0xff && e[-1] == 0xd9) break;
--len; --e; truncate = 1;
}
}
}
data = j2k->tile_data[curtileno];
data = (unsigned char*) opj_realloc(data, (j2k->tile_len[curtileno] + len) * sizeof(unsigned char));
@@ -1548,6 +1595,13 @@ static void j2k_read_rgn(opj_j2k_t *j2k) {
};
#endif /* USE_JPWL */
if (compno >= numcomps) {
opj_event_msg(j2k->cinfo, EVT_ERROR,
"bad component number in RGN (%d out of a maximum of %d)\n",
compno, j2k->image->numcomps);
return;
}
tcp->tccps[compno].roishift = cio_read(cio, 1); /* SPrgn */
}
@@ -1566,7 +1620,7 @@ static void j2k_write_eoc(opj_j2k_t *j2k) {
static void j2k_read_eoc(opj_j2k_t *j2k) {
int i, tileno;
bool success;
opj_bool success = OPJ_FALSE;
/* if packets should be decoded */
if (j2k->cp->limit_decoding != DECODE_ALL_BUT_PACKETS) {
@@ -1574,12 +1628,17 @@ static void j2k_read_eoc(opj_j2k_t *j2k) {
tcd_malloc_decode(tcd, j2k->image, j2k->cp);
for (i = 0; i < j2k->cp->tileno_size; i++) {
tcd_malloc_decode_tile(tcd, j2k->image, j2k->cp, i, j2k->cstr_info);
tileno = j2k->cp->tileno[i];
success = tcd_decode_tile(tcd, j2k->tile_data[tileno], j2k->tile_len[tileno], tileno, j2k->cstr_info);
opj_free(j2k->tile_data[tileno]);
j2k->tile_data[tileno] = NULL;
tcd_free_decode_tile(tcd, i);
if (success == false) {
if (j2k->cp->tileno[i] != -1)
{
tileno = j2k->cp->tileno[i];
success = tcd_decode_tile(tcd, j2k->tile_data[tileno], j2k->tile_len[tileno], tileno, j2k->cstr_info);
opj_free(j2k->tile_data[tileno]);
j2k->tile_data[tileno] = NULL;
tcd_free_decode_tile(tcd, i);
}
else
success = OPJ_FALSE;
if (success == OPJ_FALSE) {
j2k->state |= J2K_STATE_ERR;
break;
}
@@ -1749,6 +1808,14 @@ void j2k_destroy_decompress(opj_j2k_t *j2k) {
opj_free(j2k->tile_len);
}
if(j2k->tile_data != NULL) {
if(j2k->cp != NULL) {
for (i = 0; i < j2k->cp->tileno_size; i++) {
int tileno = j2k->cp->tileno[i];
opj_free(j2k->tile_data[tileno]);
j2k->tile_data[tileno] = NULL;
}
}
opj_free(j2k->tile_data);
}
if(j2k->default_tcp != NULL) {
@@ -1834,7 +1901,7 @@ opj_image_t* j2k_decode(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *c
if (j2k->cp->correct) {
int orig_pos = cio_tell(cio);
bool status;
opj_bool status;
/* call the corrector */
status = jpwl_correct(j2k);
@@ -1868,18 +1935,24 @@ opj_image_t* j2k_decode(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *c
#endif /* USE_JPWL */
if (id >> 8 != 0xff) {
opj_image_destroy(image);
opj_event_msg(cinfo, EVT_ERROR, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id);
return 0;
if(cio_numbytesleft(cio) != 0) /* not end of file reached and no EOC */
{
opj_event_msg(cinfo, EVT_ERROR, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id);
opj_image_destroy(image);
return 0;
}
opj_event_msg(cinfo, EVT_WARNING, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id);
j2k->state = J2K_STATE_NEOC;
break;
}
e = j2k_dec_mstab_lookup(id);
// Check if the marker is known
/* Check if the marker is known*/
if (!(j2k->state & e->states)) {
opj_image_destroy(image);
opj_event_msg(cinfo, EVT_ERROR, "%.8x: unexpected marker %x\n", cio_tell(cio) - 2, id);
return 0;
}
// Check if the decoding is limited to the main header
/* Check if the decoding is limited to the main header*/
if (e->id == J2K_MS_SOT && j2k->cp->limit_decoding == LIMIT_TO_MAIN_HEADER) {
opj_event_msg(cinfo, EVT_INFO, "Main Header decoded.\n");
return image;
@@ -1889,7 +1962,10 @@ opj_image_t* j2k_decode(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *c
(*e->handler)(j2k);
}
if (j2k->state & J2K_STATE_ERR)
{
opj_image_destroy(image);
return NULL;
}
if (j2k->state == J2K_STATE_MT) {
break;
@@ -1905,7 +1981,6 @@ opj_image_t* j2k_decode(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *c
if (j2k->state != J2K_STATE_MT) {
opj_event_msg(cinfo, EVT_WARNING, "Incomplete bitstream\n");
}
return image;
}
@@ -1917,9 +1992,10 @@ opj_image_t* j2k_decode_jpt_stream(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestre
opj_image_t *image = NULL;
opj_jpt_msg_header_t header;
int position;
opj_common_ptr cinfo = j2k->cinfo;
OPJ_ARG_NOT_USED(cstr_info);
j2k->cio = cio;
/* create an empty image */
@@ -1961,9 +2037,15 @@ opj_image_t* j2k_decode_jpt_stream(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestre
id = cio_read(cio, 2);
if (id >> 8 != 0xff) {
opj_image_destroy(image);
opj_event_msg(cinfo, EVT_ERROR, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id);
return 0;
if(cio_numbytesleft(cio) != 0) /* no end of file reached and no EOC */
{
opj_event_msg(cinfo, EVT_ERROR, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id);
opj_image_destroy(image);
return 0;
}
opj_event_msg(cinfo, EVT_WARNING, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id);
j2k->state = J2K_STATE_NEOC;
break;
}
e = j2k_dec_mstab_lookup(id);
if (!(j2k->state & e->states)) {
@@ -2110,12 +2192,12 @@ void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_
int i;
/* set JPWL on */
cp->epc_on = true;
cp->info_on = false; /* no informative technique */
cp->epc_on = OPJ_TRUE;
cp->info_on = OPJ_FALSE; /* no informative technique */
/* set EPB on */
if ((parameters->jpwl_hprot_MH > 0) || (parameters->jpwl_hprot_TPH[0] > 0)) {
cp->epb_on = true;
cp->epb_on = OPJ_TRUE;
cp->hprot_MH = parameters->jpwl_hprot_MH;
for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) {
@@ -2136,7 +2218,7 @@ void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_
/* set ESD writing */
if ((parameters->jpwl_sens_size == 1) || (parameters->jpwl_sens_size == 2)) {
cp->esd_on = true;
cp->esd_on = OPJ_TRUE;
cp->sens_size = parameters->jpwl_sens_size;
cp->sens_addr = parameters->jpwl_sens_addr;
@@ -2150,10 +2232,10 @@ void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_
}
/* always set RED writing to false: we are at the encoder */
cp->red_on = false;
cp->red_on = OPJ_FALSE;
} else {
cp->epc_on = false;
cp->epc_on = OPJ_FALSE;
}
#endif /* USE_JPWL */
@@ -2226,10 +2308,10 @@ void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_
if(parameters->cp_cinema)
{
//Precinct size for lowest frequency subband=128
/*Precinct size for lowest frequency subband=128*/
tccp->prcw[0] = 7;
tccp->prch[0] = 7;
//Precinct size at all other resolutions = 256
/*Precinct size at all other resolutions = 256*/
for (j = 1; j < tccp->numresolutions; j++) {
tccp->prcw[j] = 8;
tccp->prch[j] = 8;
@@ -2271,7 +2353,7 @@ void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_
}
p++;
/*printf("\nsize precinct for level %d : %d,%d\n", j,tccp->prcw[j], tccp->prch[j]); */
} //end for
} /*end for*/
} else {
for (j = 0; j < tccp->numresolutions; j++) {
tccp->prcw[j] = 15;
@@ -2285,7 +2367,7 @@ void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_
}
}
bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) {
opj_bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) {
int tileno, compno;
opj_cp_t *cp = NULL;
@@ -2296,8 +2378,6 @@ bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, opj_codestre
cp = j2k->cp;
/* j2k_dump_cp(stdout, image, cp); */
/* INDEX >> */
j2k->cstr_info = cstr_info;
if (cstr_info) {
@@ -2394,6 +2474,9 @@ bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, opj_codestre
/* INDEX >> */
if(cstr_info) {
cstr_info->tile[j2k->curtileno].start_pos = cio_tell(cio) + j2k->pos_correction;
cstr_info->tile[j2k->curtileno].maxmarknum = 10;
cstr_info->tile[j2k->curtileno].marker = (opj_marker_info_t *) opj_malloc(cstr_info->tile[j2k->curtileno].maxmarknum * sizeof(opj_marker_info_t));
cstr_info->tile[j2k->curtileno].marknum = 0;
}
/* << INDEX */
@@ -2500,11 +2583,46 @@ bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, opj_codestre
}
#endif /* USE_JPWL */
return true;
return OPJ_TRUE;
}
static void j2k_add_mhmarker(opj_codestream_info_t *cstr_info, unsigned short int type, int pos, int len) {
if (!cstr_info)
return;
/* expand the list? */
if ((cstr_info->marknum + 1) > cstr_info->maxmarknum) {
cstr_info->maxmarknum = 100 + (int) ((float) cstr_info->maxmarknum * 1.0F);
cstr_info->marker = (opj_marker_info_t*)opj_realloc(cstr_info->marker, cstr_info->maxmarknum);
}
/* add the marker */
cstr_info->marker[cstr_info->marknum].type = type;
cstr_info->marker[cstr_info->marknum].pos = pos;
cstr_info->marker[cstr_info->marknum].len = len;
cstr_info->marknum++;
}
static void j2k_add_tlmarker( int tileno, opj_codestream_info_t *cstr_info, unsigned short int type, int pos, int len) {
opj_marker_info_t *marker;
if (!cstr_info)
return;
/* expand the list? */
if ((cstr_info->tile[tileno].marknum + 1) > cstr_info->tile[tileno].maxmarknum) {
cstr_info->tile[tileno].maxmarknum = 100 + (int) ((float) cstr_info->tile[tileno].maxmarknum * 1.0F);
cstr_info->tile[tileno].marker = (opj_marker_info_t*)opj_realloc(cstr_info->tile[tileno].marker, cstr_info->maxmarknum);
}
marker = &(cstr_info->tile[tileno].marker[cstr_info->tile[tileno].marknum]);
/* add the marker */
marker->type = type;
marker->pos = pos;
marker->len = len;
cstr_info->tile[tileno].marknum++;
}

View File

@@ -265,15 +265,15 @@ typedef struct opj_cp {
/* UniPG>> */
#ifdef USE_JPWL
/** enables writing of EPC in MH, thus activating JPWL */
bool epc_on;
opj_bool epc_on;
/** enables writing of EPB, in case of activated JPWL */
bool epb_on;
opj_bool epb_on;
/** enables writing of ESD, in case of activated JPWL */
bool esd_on;
opj_bool esd_on;
/** enables writing of informative techniques of ESD, in case of activated JPWL */
bool info_on;
opj_bool info_on;
/** enables writing of RED, in case of activated JPWL */
bool red_on;
opj_bool red_on;
/** error protection method for MH (0,1,16,32,37-128) */
int hprot_MH;
/** tile number of header protection specification (>=0) */
@@ -299,7 +299,7 @@ typedef struct opj_cp {
/** sensitivity methods for TPHs (-1,0-7) */
int sens_TPH[JPWL_MAX_NO_TILESPECS];
/** enables JPWL correction at the decoder */
bool correct;
opj_bool correct;
/** expected number of components at the decoder */
int exp_comps;
/** maximum number of tiles at the decoder */
@@ -436,10 +436,8 @@ Encode an image into a JPEG-2000 codestream
@param cstr_info Codestream information structure if required, NULL otherwise
@return Returns true if successful, returns false otherwise
*/
bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info);
opj_bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info);
void j2k_dump_image(FILE *fd, opj_image_t * img);
void j2k_dump_cp(FILE *fd, opj_image_t * img, opj_cp_t * cp);
/* ----------------------------------------------------------------------- */
/*@}*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, Herv<EFBFBD> Drolon, FreeImage Team
* Copyright (c) 2005, Herve Drolon, FreeImage Team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,18 +24,18 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef WIN32
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/times.h>
#endif /* WIN32 */
#endif /* _WIN32 */
#include "opj_includes.h"
double opj_clock(void) {
#ifdef WIN32
/* WIN32: use QueryPerformance (very accurate) */
#ifdef _WIN32
/* _WIN32: use QueryPerformance (very accurate) */
LARGE_INTEGER freq , t ;
/* freq is the clock speed of the CPU */
QueryPerformanceFrequency(&freq) ;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, Herv<EFBFBD> Drolon, FreeImage Team
* Copyright (c) 2005, Herve Drolon, FreeImage Team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

File diff suppressed because it is too large Load Diff

View File

@@ -46,11 +46,64 @@
#define JP2_COLR 0x636f6c72 /**< Colour specification box */
#define JP2_JP2C 0x6a703263 /**< Contiguous codestream box */
#define JP2_URL 0x75726c20 /**< URL box */
#define JP2_DBTL 0x6474626c /**< ??? */
#define JP2_DTBL 0x6474626c /**< Data Reference box */
#define JP2_BPCC 0x62706363 /**< Bits per component box */
#define JP2_JP2 0x6a703220 /**< File type fields */
#define JP2_PCLR 0x70636c72 /**< Palette box */
#define JP2_CMAP 0x636d6170 /**< Component Mapping box */
#define JP2_CDEF 0x63646566 /**< Channel Definition box */
/* ----------------------------------------------------------------------- */
/**
Channel description: channel index, type, assocation
*/
typedef struct opj_jp2_cdef_info
{
unsigned short cn, typ, asoc;
} opj_jp2_cdef_info_t;
/**
Channel descriptions and number of descriptions
*/
typedef struct opj_jp2_cdef
{
opj_jp2_cdef_info_t *info;
unsigned short n;
} opj_jp2_cdef_t;
/**
Component mappings: channel index, mapping type, palette index
*/
typedef struct opj_jp2_cmap_comp
{
unsigned short cmp;
unsigned char mtyp, pcol;
} opj_jp2_cmap_comp_t;
/**
Palette data: table entries, palette columns
*/
typedef struct opj_jp2_pclr
{
unsigned int *entries;
unsigned char *channel_sign;
unsigned char *channel_size;
opj_jp2_cmap_comp_t *cmap;
unsigned short nr_entries, nr_channels;
} opj_jp2_pclr_t;
/**
Collector for ICC profile, palette, component mapping, channel description
*/
typedef struct opj_jp2_color
{
unsigned char *icc_profile_buf;
int icc_profile_len;
opj_jp2_cdef_t *jp2_cdef;
opj_jp2_pclr_t *jp2_pclr;
unsigned char jp2_has_colr;
} opj_jp2_color_t;
/**
JP2 component
@@ -87,6 +140,8 @@ typedef struct opj_jp2 {
opj_jp2_comps_t *comps;
unsigned int j2k_codestream_offset;
unsigned int j2k_codestream_length;
opj_bool jpip_on;
opj_bool ignore_pclr_cmap_cdef;
} opj_jp2_t;
/**
@@ -111,9 +166,10 @@ void jp2_write_jp2h(opj_jp2_t *jp2, opj_cio_t *cio);
Read the JP2H box - JP2 Header box (used in MJ2)
@param jp2 JP2 handle
@param cio Input buffer stream
@param ext Collector for profile, cdef and pclr data
@return Returns true if successful, returns false otherwise
*/
bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio);
opj_bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio, opj_jp2_color_t *color);
/**
Creates a JP2 decompression structure
@param cinfo Codec context info
@@ -139,7 +195,7 @@ Decode an image from a JPEG-2000 file stream
@param cstr_info Codestream information structure if required, NULL otherwise
@return Returns a decoded image if successful, returns NULL otherwise
*/
opj_image_t* jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio, opj_codestream_info_t *cstr_info);
opj_image_t* opj_jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio, opj_codestream_info_t *cstr_info);
/**
Creates a JP2 compression structure
@param cinfo Codec context info
@@ -167,7 +223,8 @@ Encode an image into a JPEG-2000 file stream
@param cstr_info Codestream information structure if required, NULL otherwise
@return Returns true if successful, returns false otherwise
*/
bool jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info);
opj_bool opj_jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info);
/* ----------------------------------------------------------------------- */
/*@}*/

View File

@@ -521,22 +521,21 @@ void mqc_init_dec(opj_mqc_t *mqc, unsigned char *bp, int len) {
unsigned int c;
unsigned int *ip;
unsigned char *end = mqc->end - 1;
mqc->buffer = opj_realloc(mqc->buffer, (2 * len + 1) * sizeof(unsigned int));
mqc->buffer = opj_realloc(mqc->buffer, (len + 1) * sizeof(unsigned int));
ip = (unsigned int *) mqc->buffer;
while (bp != end) {
while (bp < end) {
c = *(bp + 1);
if (*bp == 0xff) {
if (c > 0x8f) {
*ip = 0x0000ff18;
break;
} else {
bp++;
*ip = 0x00000017 | (c << 9);
}
} else {
bp++;
*ip = 0x00000018 | (c << 8);
}
bp++;
ip++;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, Herv<EFBFBD> Drolon, FreeImage Team
* Copyright (c) 2005, Herve Drolon, FreeImage Team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,17 +24,22 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef WIN32
#ifdef _WIN32
#include <windows.h>
#endif /* WIN32 */
#endif /* _WIN32 */
#include "opj_config.h"
#include "opj_includes.h"
/* ---------------------------------------------------------------------- */
#ifdef WIN32
#ifdef _WIN32
#ifndef OPJ_STATIC
BOOL APIENTRY
DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
OPJ_ARG_NOT_USED(lpReserved);
OPJ_ARG_NOT_USED(hModule);
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH :
break;
@@ -48,19 +53,19 @@ DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
return TRUE;
}
#endif /* OPJ_STATIC */
#endif /* WIN32 */
#endif /* _WIN32 */
/* ---------------------------------------------------------------------- */
const char* OPJ_CALLCONV opj_version(void) {
return OPENJPEG_VERSION;
return PACKAGE_VERSION;
}
opj_dinfo_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT format) {
opj_dinfo_t *dinfo = (opj_dinfo_t*)opj_calloc(1, sizeof(opj_dinfo_t));
if(!dinfo) return NULL;
dinfo->is_decompressor = true;
dinfo->is_decompressor = OPJ_TRUE;
switch(format) {
case CODEC_J2K:
case CODEC_JPT:
@@ -120,9 +125,10 @@ void OPJ_CALLCONV opj_set_default_decoder_parameters(opj_dparameters_t *paramete
parameters->decod_format = -1;
parameters->cod_format = -1;
parameters->flags = 0;
/* UniPG>> */
#ifdef USE_JPWL
parameters->jpwl_correct = false;
parameters->jpwl_correct = OPJ_FALSE;
parameters->jpwl_exp_comps = JPWL_EXPECTED_COMPONENTS;
parameters->jpwl_max_tiles = JPWL_MAXIMUM_TILES;
#endif /* USE_JPWL */
@@ -159,7 +165,7 @@ opj_image_t* OPJ_CALLCONV opj_decode_with_info(opj_dinfo_t *dinfo, opj_cio_t *ci
case CODEC_JPT:
return j2k_decode_jpt_stream((opj_j2k_t*)dinfo->j2k_handle, cio, cstr_info);
case CODEC_JP2:
return jp2_decode((opj_jp2_t*)dinfo->jp2_handle, cio, cstr_info);
return opj_jp2_decode((opj_jp2_t*)dinfo->jp2_handle, cio, cstr_info);
case CODEC_UNKNOWN:
default:
break;
@@ -171,7 +177,7 @@ opj_image_t* OPJ_CALLCONV opj_decode_with_info(opj_dinfo_t *dinfo, opj_cio_t *ci
opj_cinfo_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT format) {
opj_cinfo_t *cinfo = (opj_cinfo_t*)opj_calloc(1, sizeof(opj_cinfo_t));
if(!cinfo) return NULL;
cinfo->is_decompressor = false;
cinfo->is_decompressor = OPJ_FALSE;
switch(format) {
case CODEC_J2K:
/* get a J2K coder handle */
@@ -243,10 +249,10 @@ void OPJ_CALLCONV opj_set_default_encoder_parameters(opj_cparameters_t *paramete
parameters->cp_disto_alloc = 0;
parameters->cp_fixed_alloc = 0;
parameters->cp_fixed_quality = 0;
parameters->jpip_on = OPJ_FALSE;
/* UniPG>> */
#ifdef USE_JPWL
parameters->jpwl_epc_on = false;
parameters->jpwl_epc_on = OPJ_FALSE;
parameters->jpwl_hprot_MH = -1; /* -1 means unassigned */
{
int i;
@@ -296,7 +302,7 @@ void OPJ_CALLCONV opj_setup_encoder(opj_cinfo_t *cinfo, opj_cparameters_t *param
}
}
bool OPJ_CALLCONV opj_encode(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, char *index) {
opj_bool OPJ_CALLCONV opj_encode(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, char *index) {
if (index != NULL)
opj_event_msg((opj_common_ptr)cinfo, EVT_WARNING, "Set index to NULL when calling the opj_encode function.\n"
"To extract the index, use the opj_encode_with_info() function.\n"
@@ -304,20 +310,20 @@ bool OPJ_CALLCONV opj_encode(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *im
return opj_encode_with_info(cinfo, cio, image, NULL);
}
bool OPJ_CALLCONV opj_encode_with_info(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) {
opj_bool OPJ_CALLCONV opj_encode_with_info(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) {
if(cinfo && cio && image) {
switch(cinfo->codec_format) {
case CODEC_J2K:
return j2k_encode((opj_j2k_t*)cinfo->j2k_handle, cio, image, cstr_info);
case CODEC_JP2:
return jp2_encode((opj_jp2_t*)cinfo->jp2_handle, cio, image, cstr_info);
return opj_jp2_encode((opj_jp2_t*)cinfo->jp2_handle, cio, image, cstr_info);
case CODEC_JPT:
case CODEC_UNKNOWN:
default:
break;
}
}
return false;
return OPJ_FALSE;
}
void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_t *cstr_info) {
@@ -328,6 +334,7 @@ void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_t *cstr_info) {
opj_free(tile_info->thresh);
opj_free(tile_info->packet);
opj_free(tile_info->tp);
opj_free(tile_info->marker);
}
opj_free(cstr_info->tile);
opj_free(cstr_info->marker);

View File

@@ -6,6 +6,7 @@
* Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
* Copyright (c) 2005, Herve Drolon, FreeImage Team
* Copyright (c) 2006-2007, Parvatha Elangovan
* Copyright (c) 2010-2011, Kaori Hagihara
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,7 +33,6 @@
#ifndef OPENJPEG_H
#define OPENJPEG_H
#define OPENJPEG_VERSION "1.4.0.635"
/*
==========================================================
@@ -40,7 +40,7 @@
==========================================================
*/
#if defined(OPJ_STATIC) || !(defined(WIN32) || defined(__WIN32__))
#if defined(OPJ_STATIC) || !defined(_WIN32)
#define OPJ_API
#define OPJ_CALLCONV
#else
@@ -53,38 +53,19 @@ that uses this DLL. This way any other project whose source files include this f
OPJ_API functions as being imported from a DLL, wheras this DLL sees symbols
defined with this macro as being exported.
*/
#ifdef OPJ_EXPORTS
#if defined(OPJ_EXPORTS) || defined(DLL_EXPORT)
#define OPJ_API __declspec(dllexport)
#else
#define OPJ_API __declspec(dllimport)
#endif /* OPJ_EXPORTS */
#endif /* !OPJ_STATIC || !WIN32 */
#endif /* !OPJ_STATIC || !_WIN32 */
#ifndef __cplusplus
#if defined(HAVE_STDBOOL_H)
/*
The C language implementation does correctly provide the standard header
file "stdbool.h".
*/
#include <stdbool.h>
#else
/*
The C language implementation does not provide the standard header file
"stdbool.h" as required by ISO/IEC 9899:1999. Try to compensate for this
braindamage below.
*/
#if !defined(bool)
#define bool int
#endif
#if !defined(true)
#define true 1
#endif
#if !defined(false)
#define false 0
#endif
#endif
#endif /* __cplusplus */
typedef int opj_bool;
#define OPJ_TRUE 1
#define OPJ_FALSE 0
/* Avoid compile-time warning because parameter is not used */
#define OPJ_ARG_NOT_USED(x) (void)(x)
/*
==========================================================
Useful constant definitions
@@ -154,14 +135,18 @@ typedef enum COLOR_SPACE {
CLRSPC_SYCC = 3 /**< YUV */
} OPJ_COLOR_SPACE;
#define ENUMCS_SRGB 16
#define ENUMCS_GRAY 17
#define ENUMCS_SYCC 18
/**
Supported codec
*/
typedef enum CODEC_FORMAT {
CODEC_UNKNOWN = -1, /**< place-holder */
CODEC_J2K = 0, /**< JPEG-2000 codestream : read/write */
CODEC_JPT = 1, /**< JPT-stream (JPEG 2000, JPIP) : read only */
CODEC_JP2 = 2 /**< JPEG-2000 file format : read/write */
CODEC_J2K = 0, /**< JPEG-2000 codestream : read/write */
CODEC_JPT = 1, /**< JPT-stream (JPEG 2000, JPIP) : read only */
CODEC_JP2 = 2 /**< JPEG-2000 file format : read/write */
} OPJ_CODEC_FORMAT;
/**
@@ -244,7 +229,7 @@ Compression parameters
*/
typedef struct opj_cparameters {
/** size of tile: tile_size_on = false (not in argument) or = true (in argument) */
bool tile_size_on;
opj_bool tile_size_on;
/** XTOsiz */
int cp_tx0;
/** YTOsiz */
@@ -326,7 +311,7 @@ typedef struct opj_cparameters {
/**@name JPWL encoding parameters */
/*@{*/
/** enables writing of EPC in MH, thus activating JPWL */
bool jpwl_epc_on;
opj_bool jpwl_epc_on;
/** error protection method for MH (0,1,16,32,37-128) */
int jpwl_hprot_MH;
/** tile number of header protection specification (>=0) */
@@ -366,8 +351,12 @@ typedef struct opj_cparameters {
char tp_flag;
/** MCT (multiple component transform) */
char tcp_mct;
/** Enable JPIP indexing*/
opj_bool jpip_on;
} opj_cparameters_t;
#define OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG 0x0001
/**
Decompression parameters
*/
@@ -404,7 +393,7 @@ typedef struct opj_dparameters {
/**@name JPWL decoding parameters */
/*@{*/
/** activates the JPWL correction capabilities */
bool jpwl_correct;
opj_bool jpwl_correct;
/** expected number of components */
int jpwl_exp_comps;
/** maximum number of tiles */
@@ -420,6 +409,7 @@ typedef struct opj_dparameters {
*/
OPJ_LIMIT_DECODING cp_limit_decoding;
unsigned int flags;
} opj_dparameters_t;
/** Common fields between JPEG-2000 compression and decompression master structs. */
@@ -427,7 +417,7 @@ typedef struct opj_dparameters {
#define opj_common_fields \
opj_event_mgr_t *event_mgr; /**< pointer to the event manager */\
void * client_data; /**< Available for use by application */\
bool is_decompressor; /**< So common code can tell which is which */\
opj_bool is_decompressor; /**< So common code can tell which is which */\
OPJ_CODEC_FORMAT codec_format; /**< selected codec */\
void *j2k_handle; /**< pointer to the J2K codec */\
void *jp2_handle; /**< pointer to the JP2 codec */\
@@ -555,6 +545,10 @@ typedef struct opj_image {
OPJ_COLOR_SPACE color_space;
/** image components */
opj_image_comp_t *comps;
/** 'restricted' ICC profile */
unsigned char *icc_profile_buf;
/** size of ICC profile */
int icc_profile_len;
} opj_image_t;
/**
@@ -601,6 +595,21 @@ typedef struct opj_packet_info {
double disto;
} opj_packet_info_t;
/* UniPG>> */
/**
Marker structure
*/
typedef struct opj_marker_info_t {
/** marker type */
unsigned short int type;
/** position in codestream */
int pos;
/** length, marker val included */
int len;
} opj_marker_info_t;
/* <<UniPG */
/**
Index structure : Information concerning tile-parts
*/
@@ -645,26 +654,18 @@ typedef struct opj_tile_info {
int numpix;
/** add fixed_quality */
double distotile;
/** number of markers */
int marknum;
/** list of markers */
opj_marker_info_t *marker;
/** actual size of markers array */
int maxmarknum;
/** number of tile parts */
int num_tps;
/** information concerning tile parts */
opj_tp_info_t *tp;
} opj_tile_info_t;
/* UniPG>> */
/**
Marker structure
*/
typedef struct opj_marker_info_t {
/** marker type */
unsigned short int type;
/** position in codestream */
int pos;
/** length, marker val included */
int len;
} opj_marker_info_t;
/* <<UniPG */
/**
Index structure of the codestream
*/
@@ -883,13 +884,13 @@ Setup the encoder parameters using the current image and using user parameters.
OPJ_API void OPJ_CALLCONV opj_setup_encoder(opj_cinfo_t *cinfo, opj_cparameters_t *parameters, opj_image_t *image);
/**
Encode an image into a JPEG-2000 codestream
@param cinfo compressor handle
3@param cinfo compressor handle
@param cio Output buffer stream
@param image Image to encode
@param index Depreacted -> Set to NULL. To extract index, used opj_encode_wci()
@return Returns true if successful, returns false otherwise
*/
OPJ_API bool OPJ_CALLCONV opj_encode(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, char *index);
OPJ_API opj_bool OPJ_CALLCONV opj_encode(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, char *index);
/**
Encode an image into a JPEG-2000 codestream and extract the codestream information
@param cinfo compressor handle
@@ -898,13 +899,14 @@ Encode an image into a JPEG-2000 codestream and extract the codestream informati
@param cstr_info Codestream information structure if needed afterwards, NULL otherwise
@return Returns true if successful, returns false otherwise
*/
OPJ_API bool OPJ_CALLCONV opj_encode_with_info(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info);
OPJ_API opj_bool OPJ_CALLCONV opj_encode_with_info(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info);
/**
Destroy Codestream information after compression or decompression
@param cstr_info Codestream information structure
*/
OPJ_API void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_t *cstr_info);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,36 @@
/* create config.h for CMake */
#define PACKAGE_VERSION "1.5.2"
#define HAVE_INTTYPES_H
#define HAVE_MEMORY_H
#define HAVE_STDINT_H
#define HAVE_STDLIB_H
#define HAVE_STRINGS_H
#define HAVE_STRING_H
#define HAVE_SYS_STAT_H
#define HAVE_SYS_TYPES_H
#define HAVE_UNISTD_H
/* #define HAVE_LIBPNG */
/* #define HAVE_PNG_H */
/* #define HAVE_LIBTIFF */
/* #define HAVE_TIFF_H */
/* #undef HAVE_LIBLCMS1 */
/* #undef HAVE_LIBLCMS2 */
/* #undef HAVE_LCMS1_H */
/* #undef HAVE_LCMS2_H */
/* Byte order. */
/* All compilers that support Mac OS X define either __BIG_ENDIAN__ or
* __LITTLE_ENDIAN__ to match the endianness of the architecture being
* compiled for. This is not necessarily the same as the architecture of the
* machine doing the building. In order to support Universal Binaries on
* Mac OS X, we prefer those defines to decide the endianness.
* On other platforms we use the result of the TRY_RUN. */
#if !defined(__APPLE__)
/* #undef OPJ_BIG_ENDIAN */
#elif defined(__BIG_ENDIAN__)
# define OPJ_BIG_ENDIAN
#endif

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, Herv<EFBFBD> Drolon, FreeImage Team
* Copyright (c) 2005, Herve Drolon, FreeImage Team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -89,20 +89,25 @@ Most compilers implement their own version of this keyword ...
/* MSVC and Borland C do not have lrintf */
#if defined(_MSC_VER) || defined(__BORLANDC__)
static INLINE long lrintf(float f){
int i;
_asm{
fld f
fistp i
};
return i;
#ifdef _M_X64
return (long)((f>0.0f) ? (f + 0.5f):(f -0.5f));
#else
int i;
_asm{
fld f
fistp i
};
return i;
#endif
}
#endif
#include "j2k_lib.h"
#include "opj_malloc.h"
#include "event.h"
#include "bio.h"
#include "cio.h"
#include "image.h"
@@ -123,9 +128,12 @@ static INLINE long lrintf(float f){
#include "int.h"
#include "fix.h"
#include "cidx_manager.h"
#include "indexbox_manager.h"
/* JPWL>> */
#ifdef USE_JPWL
#include "../jpwl/jpwl.h"
#include "./jpwl/jpwl.h"
#endif /* USE_JPWL */
/* <<JPWL */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, Herv<EFBFBD> Drolon, FreeImage Team
* Copyright (c) 2005, Herve Drolon, FreeImage Team
* Copyright (c) 2007, Callum Lerwick <seg@haxxed.com>
* All rights reserved.
*
@@ -69,7 +69,7 @@ Allocate memory aligned to a 16 byte boundry
@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available
*/
/* FIXME: These should be set with cmake tests, but we're currently not requiring use of cmake */
#ifdef WIN32
#ifdef _WIN32
/* Someone should tell the mingw people that their malloc.h ought to provide _mm_malloc() */
#ifdef __GNUC__
#include <mm_malloc.h>
@@ -80,11 +80,13 @@ Allocate memory aligned to a 16 byte boundry
#define HAVE_MM_MALLOC
#endif
#endif
#else /* Not WIN32 */
#else /* Not _WIN32 */
#if defined(__sun)
#define HAVE_MEMALIGN
#elif defined(__FreeBSD__)
#define HAVE_POSIX_MEMALIGN
/* Linux x86_64 and OSX always align allocations to 16 bytes */
#elif !defined(__amd64__) && !defined(__APPLE__)
#elif !defined(__amd64__) && !defined(__APPLE__) && !defined(_AIX)
#define HAVE_MEMALIGN
#include <malloc.h>
#endif
@@ -130,22 +132,22 @@ Allocate memory aligned to a 16 byte boundry
/**
Reallocate memory blocks.
@param memblock Pointer to previously allocated memory block
@param size New size in bytes
@param m Pointer to previously allocated memory block
@param s New size in bytes
@return Returns a void pointer to the reallocated (and possibly moved) memory block
*/
#ifdef ALLOC_PERF_OPT
void * OPJ_CALLCONV opj_realloc(void * _Memory, size_t NewSize);
void * OPJ_CALLCONV opj_realloc(void * m, size_t s);
#else
#define opj_realloc(m, s) realloc(m, s)
#endif
/**
Deallocates or frees a memory block.
@param memblock Previously allocated memory block to be freed
@param m Previously allocated memory block to be freed
*/
#ifdef ALLOC_PERF_OPT
void OPJ_CALLCONV opj_free(void * _Memory);
void OPJ_CALLCONV opj_free(void * m);
#else
#define opj_free(m) free(m)
#endif

View File

@@ -0,0 +1,170 @@
/*
* $Id: phix_manager.c 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $
*
* Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
* Copyright (c) 2002-2011, Professor Benoit Macq
* Copyright (c) 2003-2004, Yannick Verschueren
* Copyright (c) 2010-2011, Kaori Hagihara
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*! \file
* \brief Modification of jpip.c from 2KAN indexer
*/
#include <stdlib.h>
#include <math.h>
#include "opj_includes.h"
/*
* Write faix box of phix
*
* @param[in] coff offset of j2k codestream
* @param[in] compno component number
* @param[in] cstr_info codestream information
* @param[in] EPHused true if if EPH option used
* @param[in] j2klen length of j2k codestream
* @param[in] cio file output handle
* @return length of faix box
*/
int write_phixfaix( int coff, int compno, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio);
int write_phix( int coff, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio)
{
int len, lenp=0, compno, i;
opj_jp2_box_t *box;
box = (opj_jp2_box_t *)opj_calloc( cstr_info.numcomps, sizeof(opj_jp2_box_t));
for( i=0;i<2;i++){
if (i) cio_seek( cio, lenp);
lenp = cio_tell( cio);
cio_skip( cio, 4); /* L [at the end] */
cio_write( cio, JPIP_PHIX, 4); /* PHIX */
write_manf( i, cstr_info.numcomps, box, cio);
for( compno=0; compno<cstr_info.numcomps; compno++){
box[compno].length = write_phixfaix( coff, compno, cstr_info, EPHused, j2klen, cio);
box[compno].type = JPIP_FAIX;
}
len = cio_tell( cio)-lenp;
cio_seek( cio, lenp);
cio_write( cio, len, 4); /* L */
cio_seek( cio, lenp+len);
}
opj_free(box);
return len;
}
int write_phixfaix( int coff, int compno, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio)
{
int len, lenp, tileno, version, i, nmax, size_of_coding; /* 4 or 8 */
opj_tile_info_t *tile_Idx;
opj_packet_info_t packet;
int resno, precno, layno, num_packet;
int numOfres, numOfprec, numOflayers;
packet.end_ph_pos = packet.start_pos = -1;
(void)EPHused; /* unused ? */
if( j2klen > pow( 2.0, 32)){
size_of_coding = 8;
version = 1;
}
else{
size_of_coding = 4;
version = 0;
}
lenp = cio_tell( cio);
cio_skip( cio, 4); /* L [at the end] */
cio_write( cio, JPIP_FAIX, 4); /* FAIX */
cio_write( cio, version,1); /* Version 0 = 4 bytes */
nmax = 0;
for( i=0; i<=cstr_info.numdecompos[compno]; i++)
nmax += cstr_info.tile[0].ph[i] * cstr_info.tile[0].pw[i] * cstr_info.numlayers;
cio_write( cio, nmax, size_of_coding); /* NMAX */
cio_write( cio, cstr_info.tw*cstr_info.th, size_of_coding); /* M */
for( tileno=0; tileno<cstr_info.tw*cstr_info.th; tileno++){
tile_Idx = &cstr_info.tile[ tileno];
num_packet = 0;
numOfres = cstr_info.numdecompos[compno] + 1;
for( resno=0; resno<numOfres ; resno++){
numOfprec = tile_Idx->pw[resno]*tile_Idx->ph[resno];
for( precno=0; precno<numOfprec; precno++){
numOflayers = cstr_info.numlayers;
for( layno=0; layno<numOflayers; layno++){
switch ( cstr_info.prog){
case LRCP:
packet = tile_Idx->packet[ ((layno*numOfres+resno)*cstr_info.numcomps+compno)*numOfprec+precno];
break;
case RLCP:
packet = tile_Idx->packet[ ((resno*numOflayers+layno)*cstr_info.numcomps+compno)*numOfprec+precno];
break;
case RPCL:
packet = tile_Idx->packet[ ((resno*numOfprec+precno)*cstr_info.numcomps+compno)*numOflayers+layno];
break;
case PCRL:
packet = tile_Idx->packet[ ((precno*cstr_info.numcomps+compno)*numOfres+resno)*numOflayers + layno];
break;
case CPRL:
packet = tile_Idx->packet[ ((compno*numOfprec+precno)*numOfres+resno)*numOflayers + layno];
break;
default:
fprintf( stderr, "failed to ppix indexing\n");
}
cio_write( cio, packet.start_pos-coff, size_of_coding); /* start position */
cio_write( cio, packet.end_ph_pos-packet.start_pos+1, size_of_coding); /* length */
num_packet++;
}
}
}
/* PADDING */
while( num_packet < nmax){
cio_write( cio, 0, size_of_coding); /* start position */
cio_write( cio, 0, size_of_coding); /* length */
num_packet++;
}
}
len = cio_tell( cio)-lenp;
cio_seek( cio, lenp);
cio_write( cio, len, 4); /* L */
cio_seek( cio, lenp+len);
return len;
}

View File

@@ -43,31 +43,31 @@ Get next packet in layer-resolution-component-precinct order.
@param pi packet iterator to modify
@return returns false if pi pointed to the last packet or else returns true
*/
static bool pi_next_lrcp(opj_pi_iterator_t * pi);
static opj_bool pi_next_lrcp(opj_pi_iterator_t * pi);
/**
Get next packet in resolution-layer-component-precinct order.
@param pi packet iterator to modify
@return returns false if pi pointed to the last packet or else returns true
*/
static bool pi_next_rlcp(opj_pi_iterator_t * pi);
static opj_bool pi_next_rlcp(opj_pi_iterator_t * pi);
/**
Get next packet in resolution-precinct-component-layer order.
@param pi packet iterator to modify
@return returns false if pi pointed to the last packet or else returns true
*/
static bool pi_next_rpcl(opj_pi_iterator_t * pi);
static opj_bool pi_next_rpcl(opj_pi_iterator_t * pi);
/**
Get next packet in precinct-component-resolution-layer order.
@param pi packet iterator to modify
@return returns false if pi pointed to the last packet or else returns true
*/
static bool pi_next_pcrl(opj_pi_iterator_t * pi);
static opj_bool pi_next_pcrl(opj_pi_iterator_t * pi);
/**
Get next packet in component-precinct-resolution-layer order.
@param pi packet iterator to modify
@return returns false if pi pointed to the last packet or else returns true
*/
static bool pi_next_cprl(opj_pi_iterator_t * pi);
static opj_bool pi_next_cprl(opj_pi_iterator_t * pi);
/*@}*/
@@ -79,7 +79,7 @@ static bool pi_next_cprl(opj_pi_iterator_t * pi);
==========================================================
*/
static bool pi_next_lrcp(opj_pi_iterator_t * pi) {
static opj_bool pi_next_lrcp(opj_pi_iterator_t * pi) {
opj_pi_comp_t *comp = NULL;
opj_pi_resolution_t *res = NULL;
long index = 0;
@@ -108,7 +108,7 @@ static bool pi_next_lrcp(opj_pi_iterator_t * pi) {
index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p;
if (!pi->include[index]) {
pi->include[index] = 1;
return true;
return OPJ_TRUE;
}
LABEL_SKIP:;
}
@@ -116,10 +116,10 @@ LABEL_SKIP:;
}
}
return false;
return OPJ_FALSE;
}
static bool pi_next_rlcp(opj_pi_iterator_t * pi) {
static opj_bool pi_next_rlcp(opj_pi_iterator_t * pi) {
opj_pi_comp_t *comp = NULL;
opj_pi_resolution_t *res = NULL;
long index = 0;
@@ -147,7 +147,7 @@ static bool pi_next_rlcp(opj_pi_iterator_t * pi) {
index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p;
if (!pi->include[index]) {
pi->include[index] = 1;
return true;
return OPJ_TRUE;
}
LABEL_SKIP:;
}
@@ -155,10 +155,10 @@ LABEL_SKIP:;
}
}
return false;
return OPJ_FALSE;
}
static bool pi_next_rpcl(opj_pi_iterator_t * pi) {
static opj_bool pi_next_rpcl(opj_pi_iterator_t * pi) {
opj_pi_comp_t *comp = NULL;
opj_pi_resolution_t *res = NULL;
long index = 0;
@@ -229,7 +229,7 @@ if (!pi->tp_on){
index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p;
if (!pi->include[index]) {
pi->include[index] = 1;
return true;
return OPJ_TRUE;
}
LABEL_SKIP:;
}
@@ -238,10 +238,10 @@ LABEL_SKIP:;
}
}
return false;
return OPJ_FALSE;
}
static bool pi_next_pcrl(opj_pi_iterator_t * pi) {
static opj_bool pi_next_pcrl(opj_pi_iterator_t * pi) {
opj_pi_comp_t *comp = NULL;
opj_pi_resolution_t *res = NULL;
long index = 0;
@@ -310,7 +310,7 @@ static bool pi_next_pcrl(opj_pi_iterator_t * pi) {
index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p;
if (!pi->include[index]) {
pi->include[index] = 1;
return true;
return OPJ_TRUE;
}
LABEL_SKIP:;
}
@@ -319,10 +319,10 @@ LABEL_SKIP:;
}
}
return false;
return OPJ_FALSE;
}
static bool pi_next_cprl(opj_pi_iterator_t * pi) {
static opj_bool pi_next_cprl(opj_pi_iterator_t * pi) {
opj_pi_comp_t *comp = NULL;
opj_pi_resolution_t *res = NULL;
long index = 0;
@@ -389,7 +389,7 @@ static bool pi_next_cprl(opj_pi_iterator_t * pi) {
index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p;
if (!pi->include[index]) {
pi->include[index] = 1;
return true;
return OPJ_TRUE;
}
LABEL_SKIP:;
}
@@ -398,7 +398,7 @@ LABEL_SKIP:;
}
}
return false;
return OPJ_FALSE;
}
/*
@@ -707,7 +707,7 @@ void pi_destroy(opj_pi_iterator_t *pi, opj_cp_t *cp, int tileno) {
}
}
bool pi_next(opj_pi_iterator_t * pi) {
opj_bool pi_next(opj_pi_iterator_t * pi) {
switch (pi->poc.prg) {
case LRCP:
return pi_next_lrcp(pi);
@@ -720,13 +720,13 @@ bool pi_next(opj_pi_iterator_t * pi) {
case CPRL:
return pi_next_cprl(pi);
case PROG_UNKNOWN:
return false;
return OPJ_FALSE;
}
return false;
return OPJ_FALSE;
}
bool pi_create_encode( opj_pi_iterator_t *pi, opj_cp_t *cp,int tileno, int pino,int tpnum, int tppos, J2K_T2_MODE t2_mode,int cur_totnum_tp){
opj_bool pi_create_encode( opj_pi_iterator_t *pi, opj_cp_t *cp,int tileno, int pino,int tpnum, int tppos, J2K_T2_MODE t2_mode,int cur_totnum_tp){
char prog[4];
int i;
int incr_top=1,resetX=0;
@@ -748,7 +748,7 @@ bool pi_create_encode( opj_pi_iterator_t *pi, opj_cp_t *cp,int tileno, int pino,
case RPCL: strncpy(prog, "RPCL",4);
break;
case PROG_UNKNOWN:
return true;
return OPJ_TRUE;
}
if(!(cp->tp_on && ((!cp->cinema && (t2_mode == FINAL_PASS)) || cp->cinema))){
@@ -958,6 +958,6 @@ bool pi_create_encode( opj_pi_iterator_t *pi, opj_cp_t *cp,int tileno, int pino,
}
}
}
return false;
return OPJ_FALSE;
}

View File

@@ -115,12 +115,14 @@ Modify the packet iterator for enabling tile part generation
@param pi Handle to the packet iterator generated in pi_initialise_encode
@param cp Coding parameters
@param tileno Number that identifies the tile for which to list the packets
@param pino Iterator index for pi
@param tpnum Tile part number of the current tile
@param tppos The position of the tile part flag in the progression order
@param t2_mode If == 0 In Threshold calculation ,If == 1 Final pass
@param cur_totnum_tp The total number of tile parts in the current tile
@return Returns true if an error is detected
*/
bool pi_create_encode(opj_pi_iterator_t *pi, opj_cp_t *cp,int tileno, int pino,int tpnum, int tppos, J2K_T2_MODE t2_mode,int cur_totnum_tp);
opj_bool pi_create_encode(opj_pi_iterator_t *pi, opj_cp_t *cp,int tileno, int pino,int tpnum, int tppos, J2K_T2_MODE t2_mode,int cur_totnum_tp);
/**
Create a packet iterator for Decoder
@param image Raw image for which the packets will be listed
@@ -145,7 +147,7 @@ Modify the packet iterator to point to the next packet
@param pi Packet iterator to modify
@return Returns false if pi pointed to the last packet or else returns true
*/
bool pi_next(opj_pi_iterator_t * pi);
opj_bool pi_next(opj_pi_iterator_t * pi);
/* ----------------------------------------------------------------------- */
/*@}*/

View File

@@ -0,0 +1,173 @@
/*
* $Id: ppix_manager.c 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $
*
* Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
* Copyright (c) 2002-2011, Professor Benoit Macq
* Copyright (c) 2003-2004, Yannick Verschueren
* Copyright (c) 2010-2011, Kaori Hagihara
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*! \file
* \brief Modification of jpip.c from 2KAN indexer
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "opj_includes.h"
/*
* Write faix box of ppix
*
* @param[in] coff offset of j2k codestream
* @param[in] compno component number
* @param[in] cstr_info codestream information
* @param[in] EPHused true if if EPH option used
* @param[in] j2klen length of j2k codestream
* @param[in] cio file output handle
* @return length of faix box
*/
int write_ppixfaix( int coff, int compno, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio);
int write_ppix( int coff, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio)
{
int len, lenp, compno, i;
opj_jp2_box_t *box;
/* printf("cstr_info.packno %d\n", cstr_info.packno); //NMAX? */
lenp = -1;
box = (opj_jp2_box_t *)opj_calloc( cstr_info.numcomps, sizeof(opj_jp2_box_t));
for (i=0;i<2;i++){
if (i) cio_seek( cio, lenp);
lenp = cio_tell( cio);
cio_skip( cio, 4); /* L [at the end] */
cio_write( cio, JPIP_PPIX, 4); /* PPIX */
write_manf( i, cstr_info.numcomps, box, cio);
for (compno=0; compno<cstr_info.numcomps; compno++){
box[compno].length = write_ppixfaix( coff, compno, cstr_info, EPHused, j2klen, cio);
box[compno].type = JPIP_FAIX;
}
len = cio_tell( cio)-lenp;
cio_seek( cio, lenp);
cio_write( cio, len, 4); /* L */
cio_seek( cio, lenp+len);
}
opj_free(box);
return len;
}
int write_ppixfaix( int coff, int compno, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio)
{
int len, lenp, tileno, version, i, nmax, size_of_coding; /* 4 or 8*/
opj_tile_info_t *tile_Idx;
opj_packet_info_t packet;
int resno, precno, layno, num_packet;
int numOfres, numOfprec, numOflayers;
packet.end_pos = packet.end_ph_pos = packet.start_pos = -1;
(void)EPHused; /* unused ? */
if( j2klen > pow( 2.0, 32)){
size_of_coding = 8;
version = 1;
}
else{
size_of_coding = 4;
version = 0;
}
lenp = cio_tell( cio);
cio_skip( cio, 4); /* L [at the end] */
cio_write( cio, JPIP_FAIX, 4); /* FAIX */
cio_write( cio, version, 1); /* Version 0 = 4 bytes */
nmax = 0;
for( i=0; i<=cstr_info.numdecompos[compno]; i++)
nmax += cstr_info.tile[0].ph[i] * cstr_info.tile[0].pw[i] * cstr_info.numlayers;
cio_write( cio, nmax, size_of_coding); /* NMAX */
cio_write( cio, cstr_info.tw*cstr_info.th, size_of_coding); /* M */
for( tileno=0; tileno<cstr_info.tw*cstr_info.th; tileno++){
tile_Idx = &cstr_info.tile[ tileno];
num_packet=0;
numOfres = cstr_info.numdecompos[compno] + 1;
for( resno=0; resno<numOfres ; resno++){
numOfprec = tile_Idx->pw[resno]*tile_Idx->ph[resno];
for( precno=0; precno<numOfprec; precno++){
numOflayers = cstr_info.numlayers;
for( layno=0; layno<numOflayers; layno++){
switch ( cstr_info.prog){
case LRCP:
packet = tile_Idx->packet[ ((layno*numOfres+resno)*cstr_info.numcomps+compno)*numOfprec+precno];
break;
case RLCP:
packet = tile_Idx->packet[ ((resno*numOflayers+layno)*cstr_info.numcomps+compno)*numOfprec+precno];
break;
case RPCL:
packet = tile_Idx->packet[ ((resno*numOfprec+precno)*cstr_info.numcomps+compno)*numOflayers+layno];
break;
case PCRL:
packet = tile_Idx->packet[ ((precno*cstr_info.numcomps+compno)*numOfres+resno)*numOflayers + layno];
break;
case CPRL:
packet = tile_Idx->packet[ ((compno*numOfprec+precno)*numOfres+resno)*numOflayers + layno];
break;
default:
fprintf( stderr, "failed to ppix indexing\n");
}
cio_write( cio, packet.start_pos-coff, size_of_coding); /* start position */
cio_write( cio, packet.end_pos-packet.start_pos+1, size_of_coding); /* length */
num_packet++;
}
}
}
while( num_packet < nmax){ /* PADDING */
cio_write( cio, 0, size_of_coding); /* start position */
cio_write( cio, 0, size_of_coding); /* length */
num_packet++;
}
}
len = cio_tell( cio)-lenp;
cio_seek( cio, lenp);
cio_write( cio, len, 4); /* L */
cio_seek( cio, lenp+len);
return len;
}

View File

@@ -123,20 +123,20 @@ static void t1_enc_refpass_step(
/**
Decode refinement pass
*/
static void INLINE t1_dec_refpass_step_raw(
static INLINE void t1_dec_refpass_step_raw(
opj_t1_t *t1,
flag_t *flagsp,
int *datap,
int poshalf,
int neghalf,
int vsc);
static void INLINE t1_dec_refpass_step_mqc(
static INLINE void t1_dec_refpass_step_mqc(
opj_t1_t *t1,
flag_t *flagsp,
int *datap,
int poshalf,
int neghalf);
static void INLINE t1_dec_refpass_step_mqc_vsc(
static INLINE void t1_dec_refpass_step_mqc_vsc(
opj_t1_t *t1,
flag_t *flagsp,
int *datap,
@@ -240,6 +240,7 @@ Encode 1 code-block
@param stepsize
@param cblksty Code-block style
@param numcomps
@param mct
@param tile
*/
static void t1_encode_cblk(
@@ -381,9 +382,10 @@ static INLINE void t1_dec_sigpass_step_raw(
int vsc)
{
int v, flag;
opj_raw_t *raw = t1->raw; /* RAW component */
OPJ_ARG_NOT_USED(orient);
flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp);
if ((flag & T1_SIG_OTH) && !(flag & (T1_SIG | T1_VISIT))) {
if (raw_decode(raw)) {
@@ -822,9 +824,10 @@ static void t1_dec_clnpass_step_partial(
int oneplushalf)
{
int v, flag;
opj_mqc_t *mqc = t1->mqc; /* MQC component */
OPJ_ARG_NOT_USED(orient);
flag = *flagsp;
mqc_setcurctx(mqc, t1_getctxno_sc(flag));
v = mqc_decode(mqc) ^ t1_getspb(flag);
@@ -1088,34 +1091,21 @@ static double t1_getwmsedec(
int numcomps,
int mct)
{
double w1 = 1, w2, wmsedec;
// Prevent running an MCT on more than 3 components. NB openjpeg v2.0 will support this via
// custom MCT tables that can be passed as encode parameters, 1.3 cannot support this as it
// uses a static table of 3 entries and there for can only cope with 3 components with out an
// array overflow
if(numcomps==3) {
if (qmfbid == 1) {
w1 = (numcomps > 1) ? mct_getnorm(compno) : 1.0;
} else {
w1 = (numcomps > 1) ? mct_getnorm_real(compno) : 1.0;
}
}
double w1, w2, wmsedec;
if (qmfbid == 1) {
w1 = (mct && numcomps==3) ? mct_getnorm(compno) : 1.0;
w2 = dwt_getnorm(level, orient);
} else { /* if (qmfbid == 0) */
w1 = (mct && numcomps==3) ? mct_getnorm_real(compno) : 1.0;
w2 = dwt_getnorm_real(level, orient);
}
wmsedec = w1 * w2 * stepsize * (1 << bpno);
wmsedec *= wmsedec * nmsedec / 8192.0;
return wmsedec;
}
static bool allocate_buffers(
static opj_bool allocate_buffers(
opj_t1_t *t1,
int w,
int h)
@@ -1127,7 +1117,7 @@ static bool allocate_buffers(
opj_aligned_free(t1->data);
t1->data = (int*) opj_aligned_malloc(datasize * sizeof(int));
if(!t1->data){
return false;
return OPJ_FALSE;
}
t1->datasize=datasize;
}
@@ -1140,7 +1130,7 @@ static bool allocate_buffers(
opj_aligned_free(t1->flags);
t1->flags = (flag_t*) opj_aligned_malloc(flagssize * sizeof(flag_t));
if(!t1->flags){
return false;
return OPJ_FALSE;
}
t1->flagssize=flagssize;
}
@@ -1149,7 +1139,7 @@ static bool allocate_buffers(
t1->w=w;
t1->h=h;
return true;
return OPJ_TRUE;
}
/** mod fixed_quality */
@@ -1425,6 +1415,7 @@ void t1_encode_cblks(
for (bandno = 0; bandno < res->numbands; ++bandno) {
opj_tcd_band_t* restrict band = &res->bands[bandno];
int bandconst = 8192 * 8192 / ((int) floor(band->stepsize * 8192));
for (precno = 0; precno < res->pw * res->ph; ++precno) {
opj_tcd_precinct_t *prc = &band->precincts[precno];
@@ -1475,7 +1466,7 @@ void t1_encode_cblks(
datap[(j * cblk_w) + i] =
fix_mul(
tmp,
8192 * 8192 / ((int) floor(band->stepsize * 8192))) >> (11 - T1_NMSEDEC_FRACBITS);
bandconst) >> (11 - T1_NMSEDEC_FRACBITS);
}
}
}
@@ -1586,6 +1577,7 @@ void t1_decode_cblks(
opj_free(cblk->segs);
} /* cblkno */
opj_free(precinct->cblks.dec);
precinct->cblks.dec = NULL;
} /* precno */
} /* bandno */
} /* resno */

View File

@@ -135,8 +135,8 @@ void t1_encode_cblks(opj_t1_t *t1, opj_tcd_tile_t *tile, opj_tcp_t *tcp);
/**
Decode the code-blocks of a tile
@param t1 T1 handle
@param tile The tile to decode
@param tcp Tile coding parameters
@param tilec The tile to decode
@param tccp Tile coding parameters
*/
void t1_decode_cblks(opj_t1_t* t1, opj_tcd_tilecomp_t* tilec, opj_tccp_t* tccp);
/* ----------------------------------------------------------------------- */

View File

@@ -59,11 +59,12 @@ Encode a packet of a tile to a destination buffer
*/
static int t2_encode_packet(opj_tcd_tile_t *tile, opj_tcp_t *tcp, opj_pi_iterator_t *pi, unsigned char *dest, int len, opj_codestream_info_t *cstr_info, int tileno);
/**
@param seg
@param cblk
@param index
@param cblksty
@param first
*/
static void t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first);
static opj_bool t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first);
/**
Decode a packet of a tile from a source buffer
@param t2 T2 handle
@@ -72,6 +73,7 @@ Decode a packet of a tile from a source buffer
@param tile Tile for which to write the packets
@param tcp Tile coding parameters
@param pi Packet identity
@param pack_info Packet information
@return
*/
static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_tile_t *tile,
@@ -147,8 +149,8 @@ static int t2_encode_packet(opj_tcd_tile_t * tile, opj_tcp_t * tcp, opj_pi_itera
c[1] = 145;
c[2] = 0;
c[3] = 4;
c[4] = (tile->packno % 65536) / 256;
c[5] = (tile->packno % 65536) % 256;
c[4] = (unsigned char)((tile->packno % 65536) / 256);
c[5] = (unsigned char)((tile->packno % 65536) % 256);
c += 6;
}
/* </SOP> */
@@ -253,8 +255,8 @@ static int t2_encode_packet(opj_tcd_tile_t * tile, opj_tcp_t * tcp, opj_pi_itera
/* </EPH> */
/* << INDEX */
// End of packet header position. Currently only represents the distance to start of packet
// Will be updated later by incrementing with packet start value
/* End of packet header position. Currently only represents the distance to start of packet
// Will be updated later by incrementing with packet start value */
if(cstr_info && cstr_info->index_write) {
opj_packet_info_t *info_PK = &cstr_info->tile[tileno].packet[cstr_info->packno];
info_PK->end_ph_pos = (int)(c - dest);
@@ -294,9 +296,17 @@ static int t2_encode_packet(opj_tcd_tile_t * tile, opj_tcp_t * tcp, opj_pi_itera
return (c - dest);
}
static void t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first) {
static opj_bool t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first) {
opj_tcd_seg_t* seg;
cblk->segs = (opj_tcd_seg_t*) opj_realloc(cblk->segs, (index + 1) * sizeof(opj_tcd_seg_t));
opj_tcd_seg_t* segs;
segs = (opj_tcd_seg_t*) opj_realloc(cblk->segs, (index + 1) * sizeof(opj_tcd_seg_t));
if (segs == NULL)
{
return OPJ_FALSE;
}
cblk->segs = segs;
seg = &cblk->segs[index];
seg->data = NULL;
seg->dataindex = 0;
@@ -314,6 +324,8 @@ static void t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int fi
} else {
seg->maxpasses = 109;
}
return OPJ_TRUE;
}
static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_tile_t *tile,
@@ -401,8 +413,8 @@ static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_t
}
/* << INDEX */
// End of packet header position. Currently only represents the distance to start of packet
// Will be updated later by incrementing with packet start value
/* End of packet header position. Currently only represents the distance to start of packet
// Will be updated later by incrementing with packet start value*/
if(pack_info) {
pack_info->end_ph_pos = (int)(c - src);
}
@@ -460,12 +472,22 @@ static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_t
cblk->numlenbits += increment;
segno = 0;
if (!cblk->numsegs) {
t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 1);
if (!t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 1))
{
opj_event_msg(t2->cinfo, EVT_ERROR, "Out of memory\n");
bio_destroy(bio);
return -999;
}
} else {
segno = cblk->numsegs - 1;
if (cblk->segs[segno].numpasses == cblk->segs[segno].maxpasses) {
++segno;
t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0);
if (!t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0))
{
opj_event_msg(t2->cinfo, EVT_ERROR, "Out of memory\n");
bio_destroy(bio);
return -999;
}
}
}
n = cblk->numnewpasses;
@@ -476,7 +498,12 @@ static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_t
n -= cblk->segs[segno].numnewpasses;
if (n > 0) {
++segno;
t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0);
if (!t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0))
{
opj_event_msg(t2->cinfo, EVT_ERROR, "Out of memory\n");
bio_destroy(bio);
return -999;
}
}
} while (n > 0);
}
@@ -494,14 +521,15 @@ static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_t
if (tcp->csty & J2K_CP_CSTY_EPH) {
if ((*hd) != 0xff || (*(hd + 1) != 0x92)) {
opj_event_msg(t2->cinfo, EVT_ERROR, "Expected EPH marker\n");
return -999;
} else {
hd += 2;
}
}
/* << INDEX */
// End of packet header position. Currently only represents the distance to start of packet
// Will be updated later by incrementing with packet start value
/* End of packet header position. Currently only represents the distance to start of packet
// Will be updated later by incrementing with packet start value*/
if(pack_info) {
pack_info->end_ph_pos = (int)(hd - src);
}
@@ -565,7 +593,7 @@ static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_t
#endif /* USE_JPWL */
cblk->data = (unsigned char*) opj_realloc(cblk->data, (cblk->len + seg->newlen) * sizeof(unsigned char*));
cblk->data = (unsigned char*) opj_realloc(cblk->data, (cblk->len + seg->newlen) * sizeof(unsigned char));
memcpy(cblk->data + cblk->len, c, seg->newlen);
if (seg->numpasses == 0) {
seg->data = &cblk->data;
@@ -659,8 +687,8 @@ int t2_encode_packets(opj_t2_t* t2,int tileno, opj_tcd_tile_t *tile, int maxlaye
info_PK->start_pos = ((cp->tp_on | tcp->POC)&& info_PK->start_pos) ? info_PK->start_pos : info_TL->packet[cstr_info->packno - 1].end_pos + 1;
}
info_PK->end_pos = info_PK->start_pos + e - 1;
info_PK->end_ph_pos += info_PK->start_pos - 1; // End of packet header which now only represents the distance
// to start of packet is incremented by value of start of packet
info_PK->end_ph_pos += info_PK->start_pos - 1; /* End of packet header which now only represents the distance
// to start of packet is incremented by value of start of packet*/
}
cstr_info->packno++;
@@ -711,7 +739,11 @@ int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj
} else {
e = 0;
}
if(e == -999)
{
pi_destroy(pi, cp, tileno);
return -999;
}
/* progression in resolution */
image->comps[pi[pino].compno].resno_decoded =
(e > 0) ?
@@ -725,8 +757,9 @@ int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj
opj_packet_info_t *info_PK = &info_TL->packet[cstr_info->packno];
if (!cstr_info->packno) {
info_PK->start_pos = info_TL->end_header + 1;
} else if (info_TL->packet[cstr_info->packno-1].end_pos >= (int)cstr_info->tile[tileno].tp[curtp].tp_end_pos){ // New tile part
info_TL->tp[curtp].tp_numpacks = cstr_info->packno - tp_start_packno; // Number of packets in previous tile-part
} else if (info_TL->packet[cstr_info->packno-1].end_pos >= (int)cstr_info->tile[tileno].tp[curtp].tp_end_pos){ /* New tile part*/
info_TL->tp[curtp].tp_numpacks = cstr_info->packno - tp_start_packno; /* Number of packets in previous tile-part*/
info_TL->tp[curtp].tp_start_pack = tp_start_packno;
tp_start_packno = cstr_info->packno;
curtp++;
info_PK->start_pos = cstr_info->tile[tileno].tp[curtp].tp_end_header+1;
@@ -734,8 +767,8 @@ int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj
info_PK->start_pos = (cp->tp_on && info_PK->start_pos) ? info_PK->start_pos : info_TL->packet[cstr_info->packno - 1].end_pos + 1;
}
info_PK->end_pos = info_PK->start_pos + e - 1;
info_PK->end_ph_pos += info_PK->start_pos - 1; // End of packet header which now only represents the distance
// to start of packet is incremented by value of start of packet
info_PK->end_ph_pos += info_PK->start_pos - 1; /* End of packet header which now only represents the distance
// to start of packet is incremented by value of start of packet*/
cstr_info->packno++;
}
/* << INDEX */
@@ -749,7 +782,8 @@ int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj
}
/* INDEX >> */
if(cstr_info) {
cstr_info->tile[tileno].tp[curtp].tp_numpacks = cstr_info->packno - tp_start_packno; // Number of packets in last tile-part
cstr_info->tile[tileno].tp[curtp].tp_numpacks = cstr_info->packno - tp_start_packno; /* Number of packets in last tile-part*/
cstr_info->tile[tileno].tp[curtp].tp_start_pack = tp_start_packno;
}
/* << INDEX */

View File

@@ -67,6 +67,7 @@ Encode the packets of a tile to a destination buffer
@param cstr_info Codestream information structure
@param tpnum Tile part number of the current tile
@param tppos The position of the tile part flag in the progression order
@param pino
@param t2_mode If == 0 In Threshold calculation ,If == 1 Final pass
@param cur_totnum_tp The total number of tile parts in the current tile
*/
@@ -78,6 +79,7 @@ Decode the packets of a tile from a source buffer
@param len length of the source buffer
@param tileno number that identifies the tile for which to decode the packets
@param tile tile for which to decode the packets
@param cstr_info Codestream information structure
*/
int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj_tcd_tile_t *tile, opj_codestream_info_t *cstr_info);

View File

@@ -30,10 +30,11 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#define _ISOC99_SOURCE /* lrintf is C99 */
#include "opj_includes.h"
void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t * img) {
int tileno, compno, resno, bandno, precno;//, cblkno;
int tileno, compno, resno, bandno, precno;/*, cblkno;*/
fprintf(fd, "image {\n");
fprintf(fd, " tw=%d, th=%d x0=%d x1=%d y0=%d y1=%d\n",
@@ -290,6 +291,7 @@ void tcd_malloc_encode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int c
for (i = 0; i < res->pw * res->ph * 3; i++) {
band->precincts[i].imsbtree = NULL;
band->precincts[i].incltree = NULL;
band->precincts[i].cblks.enc = NULL;
}
for (precno = 0; precno < res->pw * res->ph; precno++) {
@@ -332,8 +334,10 @@ void tcd_malloc_encode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int c
cblk->y0 = int_max(cblkystart, prc->y0);
cblk->x1 = int_min(cblkxend, prc->x1);
cblk->y1 = int_min(cblkyend, prc->y1);
cblk->data = (unsigned char*) opj_calloc(8192+2, sizeof(unsigned char));
cblk->data = (unsigned char*) opj_calloc(9728+2, sizeof(unsigned char));
/* FIXME: mqc_init_enc and mqc_byteout underrun the buffer if we don't do this. Why? */
cblk->data[0] = 0;
cblk->data[1] = 0;
cblk->data += 2;
cblk->layers = (opj_tcd_layer_t*) opj_calloc(100, sizeof(opj_tcd_layer_t));
cblk->passes = (opj_tcd_pass_t*) opj_calloc(100, sizeof(opj_tcd_pass_t));
@@ -593,6 +597,8 @@ void tcd_init_encode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int cur
cblk->y1 = int_min(cblkyend, prc->y1);
cblk->data = (unsigned char*) opj_calloc(8192+2, sizeof(unsigned char));
/* FIXME: mqc_init_enc and mqc_byteout underrun the buffer if we don't do this. Why? */
cblk->data[0] = 0;
cblk->data[1] = 0;
cblk->data += 2;
cblk->layers = (opj_tcd_layer_t*) opj_calloc(100, sizeof(opj_tcd_layer_t));
cblk->passes = (opj_tcd_pass_t*) opj_calloc(100, sizeof(opj_tcd_pass_t));
@@ -613,7 +619,7 @@ void tcd_malloc_decode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp) {
tcd->image = image;
tcd->tcd_image->tw = cp->tw;
tcd->tcd_image->th = cp->th;
tcd->tcd_image->tiles = (opj_tcd_tile_t *) opj_malloc(cp->tw * cp->th * sizeof(opj_tcd_tile_t));
tcd->tcd_image->tiles = (opj_tcd_tile_t *) opj_calloc(cp->tw * cp->th, sizeof(opj_tcd_tile_t));
/*
Allocate place to store the decoded data = final image
@@ -656,7 +662,7 @@ void tcd_malloc_decode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp) {
tilec->y1 = int_ceildiv(tile->y1, image->comps[i].dy);
x0 = j == 0 ? tilec->x0 : int_min(x0, (unsigned int) tilec->x0);
y0 = j == 0 ? tilec->y0 : int_min(y0, (unsigned int) tilec->x0);
y0 = j == 0 ? tilec->y0 : int_min(y0, (unsigned int) tilec->y0);
x1 = j == 0 ? tilec->x1 : int_max(x1, (unsigned int) tilec->x1);
y1 = j == 0 ? tilec->y1 : int_max(y1, (unsigned int) tilec->y1);
}
@@ -676,6 +682,8 @@ void tcd_malloc_decode_tile(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp,
opj_tcp_t *tcp;
opj_tcd_tile_t *tile;
OPJ_ARG_NOT_USED(cstr_info);
tcd->cp = cp;
tcp = &(cp->tcps[cp->tileno[tileno]]);
@@ -687,6 +695,12 @@ void tcd_malloc_decode_tile(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp,
opj_tccp_t *tccp = &tcp->tccps[compno];
opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
if (tccp->numresolutions <= 0)
{
cp->tileno[tileno] = -1;
return;
}
/* border of each tile component (global) */
tilec->x0 = int_ceildiv(tile->x0, image->comps[compno].dx);
tilec->y0 = int_ceildiv(tile->y0, image->comps[compno].dy);
@@ -997,7 +1011,7 @@ void tcd_makelayer(opj_tcd_t *tcd, int layno, double thresh, int final) {
}
}
bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_codestream_info_t *cstr_info) {
opj_bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_codestream_info_t *cstr_info) {
int compno, resno, bandno, precno, cblkno, passno, layno;
double min, max;
double cumdisto[100]; /* fixed_quality */
@@ -1149,7 +1163,7 @@ bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_codestre
}
if (!success) {
return false;
return OPJ_FALSE;
}
if(cstr_info) { /* Threshold for Marcela Index */
@@ -1161,7 +1175,7 @@ bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_codestre
cumdisto[layno] = (layno == 0) ? tcd_tile->distolayer[0] : (cumdisto[layno - 1] + tcd_tile->distolayer[layno]);
}
return true;
return OPJ_TRUE;
}
int tcd_encode_tile(opj_tcd_t *tcd, int tileno, unsigned char *dest, int len, opj_codestream_info_t *cstr_info) {
@@ -1313,7 +1327,7 @@ int tcd_encode_tile(opj_tcd_t *tcd, int tileno, unsigned char *dest, int len, op
return l;
}
bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, opj_codestream_info_t *cstr_info) {
opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, opj_codestream_info_t *cstr_info) {
int l;
int compno;
int eof = 0;
@@ -1349,7 +1363,7 @@ bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, op
}
else {
cstr_info->tile[tileno].pdx[resno] = 15;
cstr_info->tile[tileno].pdx[resno] = 15;
cstr_info->tile[tileno].pdy[resno] = 15;
}
}
}
@@ -1373,14 +1387,24 @@ bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, op
t1_time = opj_clock(); /* time needed to decode a tile */
t1 = t1_create(tcd->cinfo);
if (t1 == NULL)
{
opj_event_msg(tcd->cinfo, EVT_ERROR, "Out of memory\n");
t1_destroy(t1);
return OPJ_FALSE;
}
for (compno = 0; compno < tile->numcomps; ++compno) {
opj_tcd_tilecomp_t* tilec = &tile->comps[compno];
/* The +3 is headroom required by the vectorized DWT */
tilec->data = (int*) opj_aligned_malloc((((tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0))+3) * sizeof(int));
if(tilec->data)
t1_decode_cblks(t1, tilec, &tcd->tcp->tccps[compno]);
else
opj_event_msg(tcd->cinfo, EVT_ERROR, "tcd_decode: tile size invalid\n");
if (tilec->data == NULL)
{
opj_event_msg(tcd->cinfo, EVT_ERROR, "Out of memory\n");
return OPJ_FALSE;
}
t1_decode_cblks(t1, tilec, &tcd->tcp->tccps[compno]);
}
t1_destroy(t1);
t1_time = opj_clock() - t1_time;
@@ -1394,18 +1418,15 @@ bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, op
int numres2decode;
if (tcd->cp->reduce != 0) {
tcd->image->comps[compno].resno_decoded =
tile->comps[compno].numresolutions - tcd->cp->reduce - 1;
if (tcd->image->comps[compno].resno_decoded < 0) {
if ( tile->comps[compno].numresolutions < ( tcd->cp->reduce - 1 ) ) {
opj_event_msg(tcd->cinfo, EVT_ERROR, "Error decoding tile. The number of resolutions to remove [%d+1] is higher than the number "
" of resolutions in the original codestream [%d]\nModify the cp_reduce parameter.\n", tcd->cp->reduce, tile->comps[compno].numresolutions);
return false;
return OPJ_FALSE;
}
}
if(!tilec->data) {
opj_event_msg(tcd->cinfo, EVT_ERROR, "Error decoding tile. null data\n");
return false;
else {
tcd->image->comps[compno].resno_decoded =
tile->comps[compno].numresolutions - tcd->cp->reduce - 1;
}
}
numres2decode = tcd->image->comps[compno].resno_decoded + 1;
@@ -1424,18 +1445,23 @@ bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, op
if (tcd->tcp->mct) {
int n = (tile->comps[0].x1 - tile->comps[0].x0) * (tile->comps[0].y1 - tile->comps[0].y0);
if (tcd->tcp->tccps[0].qmfbid == 1) {
mct_decode(
tile->comps[0].data,
tile->comps[1].data,
tile->comps[2].data,
n);
} else {
mct_decode_real(
(float*)tile->comps[0].data,
(float*)tile->comps[1].data,
(float*)tile->comps[2].data,
n);
if (tile->numcomps >= 3 ){
if (tcd->tcp->tccps[0].qmfbid == 1) {
mct_decode(
tile->comps[0].data,
tile->comps[1].data,
tile->comps[2].data,
n);
} else {
mct_decode_real(
(float*)tile->comps[0].data,
(float*)tile->comps[1].data,
(float*)tile->comps[2].data,
n);
}
} else{
opj_event_msg(tcd->cinfo, EVT_WARNING,"Number of components (%d) is inconsistent with a MCT. Skip the MCT step.\n",tile->numcomps);
}
}
@@ -1459,6 +1485,11 @@ bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, op
if(!imagec->data){
imagec->data = (int*) opj_malloc(imagec->w * imagec->h * sizeof(int));
}
if (!imagec->data)
{
opj_event_msg(tcd->cinfo, EVT_ERROR, "Out of memory\n");
return OPJ_FALSE;
}
if(tcd->tcp->tccps[compno].qmfbid == 1) {
for(j = res->y0; j < res->y1; ++j) {
for(i = res->x0; i < res->x1; ++i) {
@@ -1484,40 +1515,59 @@ bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, op
opj_event_msg(tcd->cinfo, EVT_INFO, "- tile decoded in %f s\n", tile_time);
if (eof) {
return false;
return OPJ_FALSE;
}
return true;
return OPJ_TRUE;
}
void tcd_free_decode(opj_tcd_t *tcd) {
opj_tcd_image_t *tcd_image = tcd->tcd_image;
int i = 0;
for (i = 0; i < tcd_image->tw * tcd_image->th; i++)
{
tcd_free_decode_tile(tcd, i);
}
opj_free(tcd_image->tiles);
}
void tcd_free_decode_tile(opj_tcd_t *tcd, int tileno) {
int compno,resno,bandno,precno;
int compno,resno,bandno,precno,cblkno;
opj_tcd_image_t *tcd_image = tcd->tcd_image;
opj_tcd_tile_t *tile = &tcd_image->tiles[tileno];
for (compno = 0; compno < tile->numcomps; compno++) {
opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
for (resno = 0; resno < tilec->numresolutions; resno++) {
opj_tcd_resolution_t *res = &tilec->resolutions[resno];
for (bandno = 0; bandno < res->numbands; bandno++) {
opj_tcd_band_t *band = &res->bands[bandno];
for (precno = 0; precno < res->ph * res->pw; precno++) {
opj_tcd_precinct_t *prec = &band->precincts[precno];
if (prec->imsbtree != NULL) tgt_destroy(prec->imsbtree);
if (prec->incltree != NULL) tgt_destroy(prec->incltree);
if (tile->comps != NULL) {
for (compno = 0; compno < tile->numcomps; compno++) {
opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
for (resno = 0; resno < tilec->numresolutions; resno++) {
opj_tcd_resolution_t *res = &tilec->resolutions[resno];
for (bandno = 0; bandno < res->numbands; bandno++) {
opj_tcd_band_t *band = &res->bands[bandno];
for (precno = 0; precno < res->ph * res->pw; precno++) {
opj_tcd_precinct_t *prec = &band->precincts[precno];
if (prec->cblks.dec != NULL) {
for (cblkno = 0; cblkno < prec->cw * prec->ch; ++cblkno) {
opj_tcd_cblk_dec_t* cblk = &prec->cblks.dec[cblkno];
opj_free(cblk->data);
opj_free(cblk->segs);
}
opj_free(prec->cblks.dec);
}
if (prec->imsbtree != NULL) tgt_destroy(prec->imsbtree);
if (prec->incltree != NULL) tgt_destroy(prec->incltree);
}
opj_free(band->precincts);
}
opj_free(band->precincts);
}
opj_free(tilec->resolutions);
}
opj_free(tilec->resolutions);
opj_free(tile->comps);
tile->comps = NULL;
}
opj_free(tile->comps);
}

View File

@@ -251,7 +251,7 @@ void tcd_malloc_decode_tile(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp,
void tcd_makelayer_fixed(opj_tcd_t *tcd, int layno, int final);
void tcd_rateallocate_fixed(opj_tcd_t *tcd);
void tcd_makelayer(opj_tcd_t *tcd, int layno, double thresh, int final);
bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_codestream_info_t *cstr_info);
opj_bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_codestream_info_t *cstr_info);
/**
Encode a tile from the raw image into a buffer
@param tcd TCD handle
@@ -268,8 +268,9 @@ Decode a tile from a buffer into a raw image
@param src Source buffer
@param len Length of source buffer
@param tileno Number that identifies one of the tiles to be decoded
@param cstr_info Codestream information structure
*/
bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, opj_codestream_info_t *cstr_info);
opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, opj_codestream_info_t *cstr_info);
/**
Free the memory allocated for decoding
@param tcd TCD handle

View File

@@ -0,0 +1,120 @@
/*
* $Id: thix_manager.c 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $
*
* Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
* Copyright (c) 2002-2011, Professor Benoit Macq
* Copyright (c) 2003-2004, Yannick Verschueren
* Copyright (c) 2010-2011, Kaori Hagihara
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*! \file
* \brief Modification of jpip.c from 2KAN indexer
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "opj_includes.h"
/*
* Write tile-part headers mhix box
*
* @param[in] coff offset of j2k codestream
* @param[in] cstr_info codestream information
* @param[in] tileno tile number
* @param[in] cio file output handle
* @return length of mhix box
*/
int write_tilemhix( int coff, opj_codestream_info_t cstr_info, int tileno, opj_cio_t *cio);
int write_thix( int coff, opj_codestream_info_t cstr_info, opj_cio_t *cio)
{
int len, lenp, i;
int tileno;
opj_jp2_box_t *box;
lenp = 0;
box = (opj_jp2_box_t *)opj_calloc( cstr_info.tw*cstr_info.th, sizeof(opj_jp2_box_t));
for ( i = 0; i < 2 ; i++ ){
if (i)
cio_seek( cio, lenp);
lenp = cio_tell( cio);
cio_skip( cio, 4); /* L [at the end] */
cio_write( cio, JPIP_THIX, 4); /* THIX */
write_manf( i, cstr_info.tw*cstr_info.th, box, cio);
for (tileno = 0; tileno < cstr_info.tw*cstr_info.th; tileno++){
box[tileno].length = write_tilemhix( coff, cstr_info, tileno, cio);
box[tileno].type = JPIP_MHIX;
}
len = cio_tell( cio)-lenp;
cio_seek( cio, lenp);
cio_write( cio, len, 4); /* L */
cio_seek( cio, lenp+len);
}
opj_free(box);
return len;
}
int write_tilemhix( int coff, opj_codestream_info_t cstr_info, int tileno, opj_cio_t *cio)
{
int i;
opj_tile_info_t tile;
opj_tp_info_t tp;
int len, lenp;
opj_marker_info_t *marker;
lenp = cio_tell( cio);
cio_skip( cio, 4); /* L [at the end] */
cio_write( cio, JPIP_MHIX, 4); /* MHIX */
tile = cstr_info.tile[tileno];
tp = tile.tp[0];
cio_write( cio, tp.tp_end_header-tp.tp_start_pos+1, 8); /* TLEN */
marker = cstr_info.tile[tileno].marker;
for( i=0; i<cstr_info.tile[tileno].marknum; i++){ /* Marker restricted to 1 apparition */
cio_write( cio, marker[i].type, 2);
cio_write( cio, 0, 2);
cio_write( cio, marker[i].pos-coff, 8);
cio_write( cio, marker[i].len, 2);
}
/* free( marker);*/
len = cio_tell( cio) - lenp;
cio_seek( cio, lenp);
cio_write( cio, len, 4); /* L */
cio_seek( cio, lenp+len);
return len;
}

View File

@@ -0,0 +1,153 @@
/*
* $Id: tpix_manager.c 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $
*
* Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
* Copyright (c) 2002-2011, Professor Benoit Macq
* Copyright (c) 2003-2004, Yannick Verschueren
* Copyright (c) 2010-2011, Kaori Hagihara
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*! \file
* \brief Modification of jpip.c from 2KAN indexer
*/
#include <math.h>
#include "opj_includes.h"
#define MAX(a,b) ((a)>(b)?(a):(b))
/*
* Write faix box of tpix
*
* @param[in] coff offset of j2k codestream
* @param[in] compno component number
* @param[in] cstr_info codestream information
* @param[in] j2klen length of j2k codestream
* @param[in] cio file output handle
* @return length of faix box
*/
int write_tpixfaix( int coff, int compno, opj_codestream_info_t cstr_info, int j2klen, opj_cio_t *cio);
int write_tpix( int coff, opj_codestream_info_t cstr_info, int j2klen, opj_cio_t *cio)
{
int len, lenp;
lenp = cio_tell( cio);
cio_skip( cio, 4); /* L [at the end] */
cio_write( cio, JPIP_TPIX, 4); /* TPIX */
write_tpixfaix( coff, 0, cstr_info, j2klen, cio);
len = cio_tell( cio)-lenp;
cio_seek( cio, lenp);
cio_write( cio, len, 4); /* L */
cio_seek( cio, lenp+len);
return len;
}
/*
* Get number of maximum tile parts per tile
*
* @param[in] cstr_info codestream information
* @return number of maximum tile parts per tile
*/
int get_num_max_tile_parts( opj_codestream_info_t cstr_info);
int write_tpixfaix( int coff, int compno, opj_codestream_info_t cstr_info, int j2klen, opj_cio_t *cio)
{
int len, lenp;
int i, j;
int Aux;
int num_max_tile_parts;
int size_of_coding; /* 4 or 8 */
opj_tp_info_t tp;
int version;
num_max_tile_parts = get_num_max_tile_parts( cstr_info);
if( j2klen > pow( 2.0, 32)){
size_of_coding = 8;
version = num_max_tile_parts == 1 ? 1:3;
}
else{
size_of_coding = 4;
version = num_max_tile_parts == 1 ? 0:2;
}
lenp = cio_tell( cio);
cio_skip( cio, 4); /* L [at the end] */
cio_write( cio, JPIP_FAIX, 4); /* FAIX */
cio_write( cio, version, 1); /* Version 0 = 4 bytes */
cio_write( cio, num_max_tile_parts, size_of_coding); /* NMAX */
cio_write( cio, cstr_info.tw*cstr_info.th, size_of_coding); /* M */
for (i = 0; i < cstr_info.tw*cstr_info.th; i++){
for (j = 0; j < cstr_info.tile[i].num_tps; j++){
tp = cstr_info.tile[i].tp[j];
cio_write( cio, tp.tp_start_pos-coff, size_of_coding); /* start position */
cio_write( cio, tp.tp_end_pos-tp.tp_start_pos+1, size_of_coding); /* length */
if (version & 0x02){
if( cstr_info.tile[i].num_tps == 1 && cstr_info.numdecompos[compno] > 1)
Aux = cstr_info.numdecompos[compno] + 1;
else
Aux = j + 1;
cio_write( cio, Aux,4);
/*cio_write(img.tile[i].tile_parts[j].num_reso_AUX,4);*/ /* Aux_i,j : Auxiliary value */
/* fprintf(stderr,"AUX value %d\n",Aux);*/
}
/*cio_write(0,4);*/
}
/* PADDING */
while (j < num_max_tile_parts){
cio_write( cio, 0, size_of_coding); /* start position */
cio_write( cio, 0, size_of_coding); /* length */
if (version & 0x02)
cio_write( cio, 0,4); /* Aux_i,j : Auxiliary value */
j++;
}
}
len = cio_tell( cio)-lenp;
cio_seek( cio, lenp);
cio_write( cio, len, 4); /* L */
cio_seek( cio, lenp+len);
return len;
}
int get_num_max_tile_parts( opj_codestream_info_t cstr_info)
{
int num_max_tp = 0, i;
for( i=0; i<cstr_info.tw*cstr_info.th; i++)
num_max_tp = MAX( cstr_info.tile[i].num_tps, num_max_tp);
return num_max_tp;
}

View File

@@ -50,8 +50,7 @@ LLMultiGesture::LLMultiGesture()
mSteps(),
mPlaying(FALSE),
mCurrentStep(0),
mDoneCallback(NULL),
mCallbackData(NULL)
mDoneCallback(NULL)
{
reset();
}

View File

@@ -100,8 +100,7 @@ public:
// Timer for waiting
LLFrameTimer mWaitTimer;
void (*mDoneCallback)(LLMultiGesture* gesture, void* data);
void* mCallbackData;
boost::function<void (LLMultiGesture*)> mDoneCallback;
// Animations that we requested to start
std::set<LLUUID> mRequestedAnimIDs;

View File

@@ -27,7 +27,7 @@
#include "linden_common.h"
#include "llallocator.h"
#if LL_USE_TCMALLOC
#if (LL_USE_TCMALLOC && LL_USE_HEAP_PROFILER)
#include "google/heap-profiler.h"
#include "google/commandlineflags_public.h"

View File

@@ -56,6 +56,7 @@ public:
};
LLDynamicArray(S32 size=0) : std::vector<Type>(size) { if (size < BlockSize) std::vector<Type>::reserve(BlockSize); }
LLDynamicArray(const std::vector<Type>& copy) : std::vector<Type>(copy) {}
void reset() { std::vector<Type>::clear(); }

View File

@@ -444,13 +444,13 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
{
// The new node isn't last. Place it between the previous node and
// the successor.
newNode = (myprev + mydmi->second)/2.0;
newNode = (myprev + mydmi->second)/2.f;
}
else
{
// The new node is last. Bump myprev up to the next integer, add
// 1.0 and use that.
newNode = std::ceil(myprev) + 1.0;
newNode = std::ceil(myprev) + 1.f;
}
// Now that newNode has a value that places it appropriately in mSignal,
// connect it.

View File

@@ -67,6 +67,17 @@ BOOL LLMemory::sEnableMemoryFailurePrevention = FALSE;
LLPrivateMemoryPoolManager::mem_allocation_info_t LLPrivateMemoryPoolManager::sMemAllocationTracker;
#endif
void ll_assert_aligned_func(uintptr_t ptr,U32 alignment)
{
#ifdef SHOW_ASSERT
// Redundant, place to set breakpoints.
if (ptr%alignment!=0)
{
llwarns << "alignment check failed" << llendl;
}
llassert(ptr%alignment==0);
#endif
}
//static
void LLMemory::initClass()
{
@@ -246,21 +257,6 @@ U32 LLMemory::getAllocatedMemKB()
return sAllocatedMemInKB ;
}
void* ll_allocate (size_t size)
{
if (size == 0)
{
llwarns << "Null allocation" << llendl;
}
void *p = malloc(size);
if (p == NULL)
{
LLMemory::freeReserve();
llerrs << "Out of memory Error" << llendl;
}
return p;
}
//----------------------------------------------------------------------------
#if defined(LL_WINDOWS)
@@ -1358,7 +1354,7 @@ char* LLPrivateMemoryPool::allocate(U32 size)
//if the asked size larger than MAX_BLOCK_SIZE, fetch from heap directly, the pool does not manage it
if(size >= CHUNK_SIZE)
{
return (char*)malloc(size) ;
return (char*)ll_aligned_malloc_16(size) ;
}
char* p = NULL ;
@@ -1415,7 +1411,7 @@ char* LLPrivateMemoryPool::allocate(U32 size)
to_log = false ;
}
return (char*)malloc(size) ;
return (char*)ll_aligned_malloc_16(size) ;
}
return p ;
@@ -1434,7 +1430,7 @@ void LLPrivateMemoryPool::freeMem(void* addr)
if(!chunk)
{
free(addr) ; //release from heap
ll_aligned_free_16(addr) ; //release from heap
}
else
{
@@ -1558,7 +1554,7 @@ LLPrivateMemoryPool::LLMemoryChunk* LLPrivateMemoryPool::addChunk(S32 chunk_inde
mReservedPoolSize += preferred_size + overhead ;
char* buffer = (char*)malloc(preferred_size + overhead) ;
char* buffer = (char*)ll_aligned_malloc_16(preferred_size + overhead) ;
if(!buffer)
{
return NULL ;
@@ -1626,7 +1622,7 @@ void LLPrivateMemoryPool::removeChunk(LLMemoryChunk* chunk)
mReservedPoolSize -= chunk->getBufferSize() ;
//release memory
free(chunk->getBuffer()) ;
ll_aligned_free_16(chunk->getBuffer()) ;
}
U16 LLPrivateMemoryPool::findHashKey(const char* addr)
@@ -1970,7 +1966,7 @@ char* LLPrivateMemoryPoolManager::allocate(LLPrivateMemoryPool* poolp, U32 size,
if(!poolp)
{
p = (char*)malloc(size) ;
p = (char*)ll_aligned_malloc_16(size) ;
}
else
{
@@ -1999,7 +1995,7 @@ char* LLPrivateMemoryPoolManager::allocate(LLPrivateMemoryPool* poolp, U32 size)
}
else
{
return (char*)malloc(size) ;
return (char*)ll_aligned_malloc_16(size) ;
}
}
#endif
@@ -2024,7 +2020,7 @@ void LLPrivateMemoryPoolManager::freeMem(LLPrivateMemoryPool* poolp, void* addr
{
if(!sPrivatePoolEnabled)
{
free(addr) ; //private pool is disabled.
ll_aligned_free_16(addr) ; //private pool is disabled.
}
else if(!sInstance) //the private memory manager is destroyed, try the dangling list
{

View File

@@ -39,9 +39,14 @@
#include <stdint.h> // uintptr_t
#endif
#include "llerror.h"
#include "llmemtype.h"
#if LL_DEBUG
#if LL_WINDOWS && LL_DEBUG
#define LL_CHECK_MEMORY llassert(_CrtCheckMemory());
#else
#define LL_CHECK_MEMORY
#endif
inline void* ll_aligned_malloc( size_t size, int align )
{
void* mem = malloc( size + (align - 1) + sizeof(void*) );
@@ -57,10 +62,11 @@ inline void ll_aligned_free( void* ptr )
free( ((void**)ptr)[-1] );
}
#if !LL_USE_TCMALLOC
inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed with ll_aligned_free_16().
{
#if defined(LL_WINDOWS)
return _mm_malloc(size, 16);
return _aligned_malloc(size, 16);
#elif defined(LL_DARWIN)
return malloc(size); // default osx malloc is 16 byte aligned.
#else
@@ -75,7 +81,7 @@ inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed wi
inline void ll_aligned_free_16(void *p)
{
#if defined(LL_WINDOWS)
_mm_free(p);
_aligned_free(p);
#elif defined(LL_DARWIN)
return free(p);
#else
@@ -83,10 +89,39 @@ inline void ll_aligned_free_16(void *p)
#endif
}
inline void* ll_aligned_realloc_16(void* ptr, size_t size, size_t old_size) // returned hunk MUST be freed with ll_aligned_free_16().
{
#if defined(LL_WINDOWS)
return _aligned_realloc(ptr, size, 16);
#elif defined(LL_DARWIN)
return realloc(ptr,size); // default osx malloc is 16 byte aligned.
#else
//FIXME: memcpy is SLOW
void* ret = ll_aligned_malloc_16(size);
if (ptr)
{
if (ret)
{
// Only copy the size of the smallest memory block to avoid memory corruption.
memcpy(ret, ptr, llmin(old_size, size));
}
ll_aligned_free_16(ptr);
}
return ret;
#endif
}
#else // USE_TCMALLOC
// ll_aligned_foo_16 are not needed with tcmalloc
#define ll_aligned_malloc_16 malloc
#define ll_aligned_realloc_16(a,b,c) realloc(a,b)
#define ll_aligned_free_16 free
#endif // USE_TCMALLOC
inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed with ll_aligned_free_32().
{
#if defined(LL_WINDOWS)
return _mm_malloc(size, 32);
return _aligned_malloc(size, 32);
#elif defined(LL_DARWIN)
return ll_aligned_malloc( size, 32 );
#else
@@ -101,22 +136,13 @@ inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed wi
inline void ll_aligned_free_32(void *p)
{
#if defined(LL_WINDOWS)
_mm_free(p);
_aligned_free(p);
#elif defined(LL_DARWIN)
ll_aligned_free( p );
#else
free(p); // posix_memalign() is compatible with heap deallocator
#endif
}
#else // LL_DEBUG
// ll_aligned_foo are noops now that we use tcmalloc everywhere (tcmalloc aligns automatically at appropriate intervals)
#define ll_aligned_malloc( size, align ) malloc(size)
#define ll_aligned_free( ptr ) free(ptr)
#define ll_aligned_malloc_16 malloc
#define ll_aligned_free_16 free
#define ll_aligned_malloc_32 malloc
#define ll_aligned_free_32 free
#endif // LL_DEBUG
#ifndef __DEBUG_PRIVATE_MEM__
#define __DEBUG_PRIVATE_MEM__ 0
@@ -521,6 +547,14 @@ void LLPrivateMemoryPoolTester::operator delete[](void* addr)
#endif
#endif
LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment);
#ifdef SHOW_ASSERT
#define ll_assert_aligned(ptr,alignment) ll_assert_aligned_func(reinterpret_cast<uintptr_t>(ptr),((U32)alignment))
#else
#define ll_assert_aligned(ptr,alignment)
#endif
//EVENTUALLY REMOVE THESE:
#include "llpointer.h"
#include "llsingleton.h"

View File

@@ -262,11 +262,6 @@ U64 totalTime()
// No wrapping, we're all okay.
gTotalTimeClockCount += current_clock_count - gLastTotalTimeClockCount;
}
else if((gLastTotalTimeClockCount - current_clock_count)<0xFFFF)
{
//clock is glitching and walking backwards - ignore it
gTotalTimeClockCount = gLastTotalTimeClockCount;
}
else
{
// We've wrapped. Compensate correctly

View File

@@ -206,6 +206,19 @@ U8* LLImageBase::allocateData(S32 size)
// virtual
U8* LLImageBase::reallocateData(S32 size)
{
if (size == -1)
{
size = mWidth * mHeight * mComponents;
if (size <= 0)
{
llerrs << llformat("LLImageBase::reallocateData called with bad dimensions: %dx%dx%d", mWidth, mHeight, (S32)mComponents) << llendl;
}
}
else if (size <= 0 || (size > 4096 * 4096 * 16 && !mAllowOverSize))
{
llerrs << "LLImageBase::reallocateData: bad size: " << size << llendl;
}
if(mData && (mDataSize == size))
return mData;
@@ -300,6 +313,32 @@ LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components)
++sRawImageCount;
}
LLImageRaw::LLImageRaw(LLImageRaw const* src, U16 width, U16 height, U16 crop_offset, bool crop_vertically) : mCacheEntries(0)
{
mMemType = LLMemType::MTYPE_IMAGERAW;
llassert_always(src);
S8 const components = src->getComponents();
U8 const* const data = src->getData();
if (allocateDataSize(width, height, components))
{
if (crop_vertically)
{
llassert_always(width == src->getWidth());
memcpy(getData(), data + width * crop_offset * components, width * height * components);
}
else
{
llassert_always(height == src->getHeight());
U16 const src_width = src->getWidth();
for (U16 row = 0; row < height; ++row)
{
memcpy(getData() + width * row * components, data + (src_width * row + crop_offset) * components, width * components);
}
}
}
++sRawImageCount;
}
/*LLImageRaw::LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only)
: LLImageBase(), mCacheEntries(0)
{
@@ -516,7 +555,7 @@ void LLImageRaw::contractToPowerOfTwo(S32 max_dim, BOOL scale_image)
scale( new_width, new_height, scale_image );
}
void LLImageRaw::biasedScaleToPowerOfTwo(S32 max_dim)
void LLImageRaw::biasedScaleToPowerOfTwo(S32 target_width, S32 target_height, S32 max_dim)
{
// Strong bias towards rounding down (to save bandwidth)
// No bias would mean THRESHOLD == 1.5f;
@@ -525,22 +564,22 @@ void LLImageRaw::biasedScaleToPowerOfTwo(S32 max_dim)
// Find new sizes
S32 larger_w = max_dim; // 2^n >= mWidth
S32 smaller_w = max_dim; // 2^(n-1) <= mWidth
while( (smaller_w > getWidth()) && (smaller_w > MIN_IMAGE_SIZE) )
while( (smaller_w > target_width) && (smaller_w > MIN_IMAGE_SIZE) )
{
larger_w = smaller_w;
smaller_w >>= 1;
}
S32 new_width = ( (F32)getWidth() / smaller_w > THRESHOLD ) ? larger_w : smaller_w;
S32 new_width = ( (F32)target_width / smaller_w > THRESHOLD ) ? larger_w : smaller_w;
S32 larger_h = max_dim; // 2^m >= mHeight
S32 smaller_h = max_dim; // 2^(m-1) <= mHeight
while( (smaller_h > getHeight()) && (smaller_h > MIN_IMAGE_SIZE) )
while( (smaller_h > target_height) && (smaller_h > MIN_IMAGE_SIZE) )
{
larger_h = smaller_h;
smaller_h >>= 1;
}
S32 new_height = ( (F32)getHeight() / smaller_h > THRESHOLD ) ? larger_h : smaller_h;
S32 new_height = ( (F32)target_height / smaller_h > THRESHOLD ) ? larger_h : smaller_h;
scale( new_width, new_height );
@@ -943,76 +982,66 @@ BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
return TRUE; // Nothing to do.
}
// Reallocate the data buffer.
U8* old_buffer = NULL;
U8* new_buffer;
S32 const old_width_bytes = old_width * getComponents();
S32 const new_width_bytes = new_width * getComponents();
S32 const min_height = llmin(old_height, new_height);
S32 const min_width_bytes = llmin(old_width_bytes, new_width_bytes);
if (scale_image_data)
{
// Vertical
S32 temp_data_size = old_width * new_height * getComponents();
llassert_always(temp_data_size > 0);
U8* temp_buffer = new (std::nothrow) U8[ temp_data_size ];
if (!temp_buffer )
if (new_height != old_height)
{
llerrs << "Out of memory in LLImageRaw::scale()" << llendl;
return FALSE;
// Resize vertically.
old_buffer = LLImageBase::release();
new_buffer = allocateDataSize(old_width, new_height, getComponents());
for (S32 col = 0; col < old_width; ++col)
{
copyLineScaled(old_buffer + getComponents() * col, new_buffer + getComponents() * col, old_height, new_height, old_width, old_width);
}
LLImageBase::deleteData(old_buffer);
}
for( S32 col = 0; col < old_width; col++ )
if (new_width != old_width)
{
copyLineScaled( getData() + (getComponents() * col), temp_buffer + (getComponents() * col), old_height, new_height, old_width, old_width );
// Resize horizontally.
old_buffer = LLImageBase::release();
new_buffer = allocateDataSize(new_width, new_height, getComponents());
for (S32 row = 0; row < new_height; ++row)
{
copyLineScaled(old_buffer + old_width_bytes * row, new_buffer + new_width_bytes * row, old_width, new_width, 1, 1);
}
LLImageBase::deleteData(old_buffer);
}
deleteData();
U8* new_buffer = allocateDataSize(new_width, new_height, getComponents());
// Horizontal
for( S32 row = 0; row < new_height; row++ )
{
copyLineScaled( temp_buffer + (getComponents() * old_width * row), new_buffer + (getComponents() * new_width * row), old_width, new_width, 1, 1 );
}
// Clean up
delete[] temp_buffer;
}
else
{
// copy out existing image data
S32 temp_data_size = old_width * old_height * getComponents();
U8* temp_buffer = new (std::nothrow) U8[ temp_data_size ];
if (!temp_buffer)
if (new_width == old_width)
{
llwarns << "Out of memory in LLImageRaw::scale: old (w, h, c) = (" << old_width << ", " << old_height << ", " << (S32)getComponents() <<
") ; new (w, h, c) = (" << new_width << ", " << new_height << ", " << (S32)getComponents() << ")" << llendl;
return FALSE ;
setSize(new_width, new_height, getComponents());
new_buffer = reallocateData();
}
memcpy(temp_buffer, getData(), temp_data_size); /* Flawfinder: ignore */
// allocate new image data, will delete old data
U8* new_buffer = allocateDataSize(new_width, new_height, getComponents());
for( S32 row = 0; row < new_height; row++ )
else
{
if (row < old_height)
old_buffer = LLImageBase::release();
new_buffer = allocateDataSize(new_width, new_height, getComponents());
for (S32 row = 0; row < min_height; ++row)
{
memcpy(new_buffer + (new_width * row * getComponents()), temp_buffer + (old_width * row * getComponents()), getComponents() * llmin(old_width, new_width)); /* Flawfinder: ignore */
if (old_width < new_width)
memcpy(new_buffer + row * new_width_bytes, old_buffer + row * old_width_bytes, min_width_bytes);
if (new_width_bytes > old_width_bytes)
{
// pad out rest of row with black
memset(new_buffer + (getComponents() * ((new_width * row) + old_width)), 0, getComponents() * (new_width - old_width));
// Pad out rest of row with black.
memset(new_buffer + new_width_bytes * row + old_width_bytes, 0, new_width_bytes - old_width_bytes);
}
}
else
{
// pad remaining rows with black
memset(new_buffer + (new_width * row * getComponents()), 0, new_width * getComponents());
}
LLImageBase::deleteData(old_buffer);
}
if (new_height > old_height)
{
// Pad remaining rows with black.
memset(new_buffer + new_width_bytes * min_height, 0, new_width_bytes * (new_height - old_height));
}
// Clean up
delete[] temp_buffer;
}
return TRUE ;
}
@@ -1690,6 +1719,12 @@ static void avg4_colors2(const U8* a, const U8* b, const U8* c, const U8* d, U8*
dst[1] = (U8)(((U32)(a[1]) + b[1] + c[1] + d[1])>>2);
}
void LLImageBase::setDataAndSize(U8 *data, S32 size)
{
ll_assert_aligned(data, 16);
mData = data; mDataSize = size;
}
//static
void LLImageBase::generateMip(const U8* indata, U8* mipdata, S32 width, S32 height, S32 nchannels)
{

View File

@@ -114,6 +114,8 @@ public:
virtual void deleteData();
virtual U8* allocateData(S32 size = -1);
virtual U8* reallocateData(S32 size = -1);
static void deleteData(U8* data) { FREE_MEM(sPrivatePoolp, data); }
U8* release() { U8* data = mData; mData = NULL; mDataSize = 0; return data; } // Same as deleteData(), but returns old data. Call deleteData(old_data) to free it.
virtual void dump();
virtual void sanityCheck();
@@ -134,7 +136,7 @@ public:
protected:
// special accessor to allow direct setting of mData and mDataSize by LLImageFormatted
void setDataAndSize(U8 *data, S32 size) { mData = data; mDataSize = size; }
void setDataAndSize(U8 *data, S32 size);
public:
static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels);
@@ -175,12 +177,13 @@ public:
LLImageRaw();
LLImageRaw(U16 width, U16 height, S8 components);
LLImageRaw(U8 *data, U16 width, U16 height, S8 components);
LLImageRaw(LLImageRaw const* src, U16 width, U16 height, U16 crop_offset, bool crop_vertically);
// Construct using createFromFile (used by tools)
//LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only = false);
/*virtual*/ void deleteData();
/*virtual*/ U8* allocateData(S32 size = -1);
/*virtual*/ U8* reallocateData(S32 size);
/*virtual*/ U8* reallocateData(S32 size = -1);
BOOL resize(U16 width, U16 height, S8 components);
@@ -194,7 +197,8 @@ public:
void expandToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
void contractToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE);
void biasedScaleToPowerOfTwo(S32 target_width, S32 target_height, S32 max_dim = MAX_IMAGE_SIZE);
void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE) { biasedScaleToPowerOfTwo(getWidth(), getHeight(), max_dim); }
BOOL scale( S32 new_width, S32 new_height, BOOL scale_image = TRUE );
//BOOL scaleDownWithoutBlending( S32 new_width, S32 new_height) ;
@@ -287,7 +291,7 @@ public:
// LLImageBase
/*virtual*/ void deleteData();
/*virtual*/ U8* allocateData(S32 size = -1);
/*virtual*/ U8* reallocateData(S32 size);
/*virtual*/ U8* reallocateData(S32 size = -1);
/*virtual*/ void dump();
/*virtual*/ void sanityCheck();

View File

@@ -1,4 +1,4 @@
/**
/**
* @file llimagej2coj.cpp
* @brief This is an implementation of JPEG2000 encode/decode using OpenJPEG.
*
@@ -35,9 +35,7 @@
const char* fallbackEngineInfoLLImageJ2CImpl()
{
static std::string version_string =
std::string("OpenJPEG: " OPENJPEG_VERSION ", Runtime: ")
+ opj_version();
static std::string version_string = std::string("OpenJPEG: ") + opj_version();
return version_string.c_str();
}
@@ -186,7 +184,15 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod
{
opj_image_destroy(image);
}
#if 0
std::stringstream filename;
filename << "err" << (int)base.getRawDiscardLevel() << "_" << rand() << ".jp2";
FILE* file = fopen(filename.str().c_str(), "wb");
if (file) {
fwrite(base.getData(), base.getDataSize(), 1, file);
fclose(file);
}
#endif
base.decodeFailed();
return TRUE; // done
}

View File

@@ -66,7 +66,7 @@ static const F32 MAX_FIELD_OF_VIEW = 175.f * DEG_TO_RAD;
// roll(), pitch(), yaw()
// etc...
LL_ALIGN_PREFIX(16)
class LLCamera
: public LLCoordFrame
{
@@ -114,7 +114,7 @@ public:
};
private:
LLPlane mAgentPlanes[7]; //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP
LL_ALIGN_16(LLPlane mAgentPlanes[7]); //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP
U8 mPlaneMask[8]; // 8 for alignment
F32 mView; // angle between top and bottom frustum planes in radians.
@@ -122,13 +122,13 @@ private:
S32 mViewHeightInPixels; // for ViewHeightInPixels() only
F32 mNearPlane;
F32 mFarPlane;
LLPlane mLocalPlanes[4];
LL_ALIGN_16(LLPlane mLocalPlanes[4]);
F32 mFixedDistance; // Always return this distance, unless < 0
LLVector3 mFrustCenter; // center of frustum and radius squared for ultra-quick exclusion test
F32 mFrustRadiusSquared;
LLPlane mWorldPlanes[PLANE_NUM];
LLPlane mHorizPlanes[HORIZ_PLANE_NUM];
LL_ALIGN_16(LLPlane mWorldPlanes[PLANE_NUM]);
LL_ALIGN_16(LLPlane mHorizPlanes[HORIZ_PLANE_NUM]);
U32 mPlaneCount; //defaults to 6, if setUserClipPlane is called, uses user supplied clip plane in
@@ -214,7 +214,7 @@ protected:
void calculateFrustumPlanes(F32 left, F32 right, F32 top, F32 bottom);
void calculateFrustumPlanesFromWindow(F32 x1, F32 y1, F32 x2, F32 y2);
void calculateWorldFrustumPlanes();
};
} LL_ALIGN_POSTFIX(16);
#endif

View File

@@ -111,7 +111,7 @@ public:
protected:
LLVector4a mColumns[3];
LL_ALIGN_16(LLVector4a mColumns[3]);
};

View File

@@ -34,7 +34,7 @@
class LLMatrix4a
{
public:
LLVector4a mMatrix[4];
LL_ALIGN_16(LLVector4a mMatrix[4]);
inline void clear()
{

View File

@@ -37,6 +37,7 @@
#include "v3math.h"
#include "llvector4a.h"
#include <vector>
#include <boost/pool/pool.hpp>
#if LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG
#define OCT_ERRS LL_ERRS("OctreeErrors")
@@ -46,6 +47,7 @@
#endif
extern U32 gOctreeMaxCapacity;
extern U32 gOctreeReserveCapacity;
#if LL_DEBUG
#define LL_OCTREE_PARANOIA_CHECK 0
#else
@@ -56,6 +58,106 @@ extern U32 gOctreeMaxCapacity;
template <class T> class LLOctreeNode;
#include "lltimer.h"
//#define LL_OCTREE_STATS
#define LL_OCTREE_POOLS
#ifdef LL_OCTREE_STATS
class OctreeStats : public LLSingleton<OctreeStats>
{
public:
OctreeStats() :
mPeriodNodesCreated(0),
mPeriodNodesDestroyed(0),
mPeriodAllocs(0),
mPeriodFrees(0),
mPeriodLargestSize(0),
mTotalNodes(0),
mTotalAllocs(0),
mTotalFrees(0),
mLargestSize(0),
mTotalSize(0)
{
mTotalTimer.reset();
mPeriodTimer.reset();
}
void addNode()
{
++mTotalNodes;
++mPeriodNodesCreated;
}
void removeNode()
{
--mTotalNodes;
++mPeriodNodesDestroyed;
}
void realloc(U32 old_count, U32 new_count)
{
if(new_count >= old_count)
mTotalSize+=new_count-old_count;
else
mTotalSize-=old_count-new_count;
if(mLargestSize < new_count)
mLargestSize = new_count;
if(mPeriodLargestSize < new_count)
mPeriodLargestSize = new_count;
++mTotalAllocs;
++mPeriodAllocs;
}
void free(U32 count)
{
mTotalSize-=count;
++mTotalFrees;
++mPeriodFrees;
}
void dump()
{
llinfos << llformat("Lifetime: Allocs:(+%u|-%u) Allocs/s: (+%lf|-%lf) Nodes: %u AccumSize: %llubytes Avg: %lf LargestSize: %u",
mTotalAllocs,
mTotalFrees,
F64(mTotalAllocs)/mTotalTimer.getElapsedTimeF64(),
F64(mTotalFrees)/mTotalTimer.getElapsedTimeF64(),
mTotalNodes,
mTotalSize*sizeof(LLPointer<LLRefCount>),
F64(mTotalSize)/F64(mTotalNodes),
mLargestSize
) << llendl;
llinfos << llformat("Timeslice: Allocs:(+%u|-%u) Allocs/s: (+%lf|-%lf) Nodes:(+%u|-%u) LargestSize: %u",
mPeriodAllocs,
mPeriodFrees,
F64(mPeriodAllocs)/mPeriodTimer.getElapsedTimeF64(),
F64(mPeriodFrees)/mPeriodTimer.getElapsedTimeF64(),
mPeriodNodesCreated,
mPeriodNodesDestroyed,
mPeriodLargestSize
) << llendl;
mPeriodNodesCreated=0;
mPeriodNodesDestroyed=0;
mPeriodAllocs=0;
mPeriodFrees=0;
mPeriodLargestSize=0;
mPeriodTimer.reset();
}
private:
//Accumulate per timer update
U32 mPeriodNodesCreated;
U32 mPeriodNodesDestroyed;
U32 mPeriodAllocs;
U32 mPeriodFrees;
U32 mPeriodLargestSize;
LLTimer mPeriodTimer;
//Accumulate through entire app lifetime:
U32 mTotalNodes;
U32 mTotalAllocs;
U32 mTotalFrees;
U32 mLargestSize;
U64 mTotalSize;
LLTimer mTotalTimer;
};
#endif //LL_OCTREE_STATS
template <class T>
class LLOctreeListener: public LLTreeListener<T>
{
@@ -129,25 +231,52 @@ public:
typedef LLOctreeTraveler<T> oct_traveler;
typedef LLTreeTraveler<T> tree_traveler;
typedef LLPointer<T>* element_list;
typedef LLPointer<T>* element_iter;
typedef const LLPointer<T>* const_element_iter;
typedef std::vector<LLPointer<T> > element_list;
typedef typename element_list::iterator element_iter;
typedef typename element_list::const_iterator const_element_iter;
typedef typename std::vector<LLTreeListener<T>*>::iterator tree_listener_iter;
typedef LLOctreeNode<T>** child_list;
typedef LLOctreeNode<T>** child_iter;
typedef LLTreeNode<T> BaseType;
typedef LLOctreeNode<T> oct_node;
typedef LLOctreeListener<T> oct_listener;
/*void* operator new(size_t size)
#ifdef LL_OCTREE_POOLS
struct octree_pool_alloc
{
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
static char * malloc(const std::size_t bytes)
{ return (char *)ll_aligned_malloc_16(bytes); }
static void free(char * const block)
{ ll_aligned_free_16(block); }
};
static boost::pool<octree_pool_alloc>& getPool(const std::size_t& size)
{
static boost::pool<octree_pool_alloc> sPool((std::size_t)LL_NEXT_ALIGNED_ADDRESS((char*)size),1200);
llassert_always((std::size_t)LL_NEXT_ALIGNED_ADDRESS((char*)size) == sPool.get_requested_size());
return sPool;
}
void* operator new(size_t size)
{
return getPool(size).malloc();
}
void operator delete(void* ptr)
{
getPool(sizeof(LLOctreeNode<T>)).free(ptr);
}
#else
void* operator new(size_t size)
{
return ll_aligned_malloc_16(size);
}
void operator delete(void* ptr)
{
ll_aligned_free_16(ptr);
}*/
}
#endif
LLOctreeNode( const LLVector4a& center,
const LLVector4a& size,
@@ -156,8 +285,16 @@ public:
: mParent((oct_node*)parent),
mOctant(octant)
{
mData = NULL;
mDataEnd = NULL;
#ifdef LL_OCTREE_STATS
OctreeStats::getInstance()->addNode();
#endif
if(gOctreeReserveCapacity)
mData.reserve(gOctreeReserveCapacity);
#ifdef LL_OCTREE_STATS
OctreeStats::getInstance()->realloc(0,mData.capacity());
#endif
//mData = NULL;
//mDataEnd = NULL;
mCenter = center;
mSize = size;
@@ -168,24 +305,31 @@ public:
mOctant = ((oct_node*) mParent)->getOctant(mCenter);
}
mElementCount = 0;
//mElementCount = 0;
clearChildren();
}
virtual ~LLOctreeNode()
{
{
#ifdef LL_OCTREE_STATS
OctreeStats::getInstance()->removeNode();
#endif
BaseType::destroyListeners();
for (U32 i = 0; i < mElementCount; ++i)
//for (U32 i = 0; i < mElementCount; ++i)
for (U32 i = 0; i < mData.size(); ++i)
{
mData[i]->setBinIndex(-1);
mData[i] = NULL;
}
free(mData);
mData = NULL;
mDataEnd = NULL;
#ifdef LL_OCTREE_STATS
OctreeStats::getInstance()->free(mData.capacity());
#endif
//free(mData);
//mData = NULL;
//mDataEnd = NULL;
for (U32 i = 0; i < getChildCount(); i++)
{
@@ -285,14 +429,14 @@ public:
void accept(oct_traveler* visitor) { visitor->visit(this); }
virtual bool isLeaf() const { return mChildCount == 0; }
U32 getElementCount() const { return mElementCount; }
bool isEmpty() const { return mElementCount == 0; }
U32 getElementCount() const { return mData.size(); }
bool isEmpty() const { return mData.size() == 0; }
//element_list& getData() { return mData; }
//const element_list& getData() const { return mData; }
element_iter getDataBegin() { return mData; }
element_iter getDataEnd() { return mDataEnd; }
const_element_iter getDataBegin() const { return mData; }
const_element_iter getDataEnd() const { return mDataEnd; }
element_iter getDataBegin() { return mData.begin(); }
element_iter getDataEnd() { return mData.end(); }
const_element_iter getDataBegin() const { return mData.begin(); }
const_element_iter getDataEnd() const { return mData.end(); }
U32 getChildCount() const { return mChildCount; }
oct_node* getChild(U32 index) { return mChild[index]; }
@@ -372,7 +516,10 @@ public:
if ((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius()) ||
(data->getBinRadius() > getSize()[0] && parent && parent->getElementCount() >= gOctreeMaxCapacity)))
{ //it belongs here
mElementCount++;
/*mElementCount++;
#ifdef LL_OCTREE_STATS
OctreeStats::getInstance()->realloc(mElementCount-1,mElementCount);
#endif
mData = (element_list) realloc(mData, sizeof(LLPointer<T>)*mElementCount);
//avoid unref on uninitialized memory
@@ -380,7 +527,18 @@ public:
mData[mElementCount-1] = data;
mDataEnd = mData + mElementCount;
data->setBinIndex(mElementCount-1);
data->setBinIndex(mElementCount-1);*/
#ifdef LL_OCTREE_STATS
U32 old_cap = mData.capacity();
#endif
data->setBinIndex(mData.size());
mData.push_back(data);
#ifdef LL_OCTREE_STATS
if(old_cap != mData.capacity())
OctreeStats::getInstance()->realloc(old_cap,mData.capacity());
#endif
BaseType::insert(data);
return true;
}
@@ -415,7 +573,10 @@ public:
if( lt == 0x7 )
{
mElementCount++;
/*mElementCount++;
#ifdef LL_OCTREE_STATS
OctreeStats::getInstance()->realloc(mElementCount-1,mElementCount);
#endif
mData = (element_list) realloc(mData, sizeof(LLPointer<T>)*mElementCount);
//avoid unref on uninitialized memory
@@ -423,7 +584,17 @@ public:
mData[mElementCount-1] = data;
mDataEnd = mData + mElementCount;
data->setBinIndex(mElementCount-1);
data->setBinIndex(mElementCount-1);*/
#ifdef LL_OCTREE_STATS
U32 old_cap = mData.capacity();
#endif
data->setBinIndex(mData.size());
mData.push_back(data);
#ifdef LL_OCTREE_STATS
if(old_cap != mData.capacity())
OctreeStats::getInstance()->realloc(old_cap,mData.capacity());
#endif
BaseType::insert(data);
return true;
}
@@ -476,10 +647,10 @@ public:
void _remove(T* data, S32 i)
{ //precondition -- mElementCount > 0, idx is in range [0, mElementCount)
OctreeGuard::checkGuarded(this);
mElementCount--;
//mElementCount--;
data->setBinIndex(-1);
if (mElementCount > 0)
/* if (mElementCount > 0)
{
if (mElementCount != i)
{
@@ -488,15 +659,51 @@ public:
}
mData[mElementCount] = NULL; //needed for unref
#ifdef LL_OCTREE_STATS
OctreeStats::getInstance()->realloc(mElementCount+1,mElementCount);
#endif
mData = (element_list) realloc(mData, sizeof(LLPointer<T>)*mElementCount);
mDataEnd = mData+mElementCount;
}
else
{
mData[0] = NULL; //needed for unref
#ifdef LL_OCTREE_STATS
OctreeStats::getInstance()->free(1);
#endif
free(mData);
mData = NULL;
mDataEnd = NULL;
}*/
if(mData.size())
{
if((mData.size()-1)!=i)
{
mData[i] = mData[mData.size()-1];
mData[i]->setBinIndex(i);
}
#ifdef LL_OCTREE_STATS
U32 old_cap = mData.capacity();
#endif
mData.pop_back();
if( mData.size() == gOctreeReserveCapacity ||
(mData.size() > gOctreeReserveCapacity && mData.capacity() > gOctreeReserveCapacity + mData.size() - 1 - (mData.size() - gOctreeReserveCapacity - 1) % 4))
{
//Shrink to lowest possible (reserve)+4*i size.. Say reserve is 5, here are [size,capacity] pairs. [10,13],[9,9],[8,9],[7,9],[6,9],[5,5],[4,5],[3,5],[2,5],[1,5],[0,5]
//For Windows: We always assume vs2010 or later, which support this c++11 feature with no configuration needed.
//For GCC: __cplusplus >= 201103L indicates C++11 support. __GXX_EXPERIMENTAL_CXX0X being set indicates experimental c++0x support. C++11 support replaces C++0x support.
// std::vector::shrink_to_fit was added to GCCs C++0x implementation in version 4.5.0.
#if defined(LL_WINDOWS) || __cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X) && __GNUC_MINOR__ >= 5)
mData.shrink_to_fit();
#else
std::vector<LLPointer<T> >(mData.begin(), mData.end()).swap(mData); //Need to confirm this works on OSX..
#endif
}
#ifdef LL_OCTREE_STATS
if(old_cap != mData.capacity())
OctreeStats::getInstance()->realloc(old_cap,mData.capacity());
#endif
}
this->notifyRemoval(data);
@@ -508,7 +715,8 @@ public:
OctreeGuard::checkGuarded(this);
S32 i = data->getBinIndex();
if (i >= 0 && i < (S32)mElementCount)
//if (i >= 0 && i < mElementCount)
if (i >= 0 && i < (S32)mData.size())
{
if (mData[i] == data)
{ //found it
@@ -552,7 +760,8 @@ public:
void removeByAddress(T* data)
{
OctreeGuard::checkGuarded(this);
for (U32 i = 0; i < mElementCount; ++i)
//for (U32 i = 0; i < mElementCount; ++i)
for (U32 i = 0; i < mData.size(); ++i)
{
if (mData[i] == data)
{ //we have data
@@ -660,8 +869,6 @@ public:
listener->handleChildRemoval(this, getChild(index));
}
if (destroy)
{
mChild[index]->destroy();
@@ -733,8 +940,8 @@ protected:
U32 mChildCount;
element_list mData;
element_iter mDataEnd;
U32 mElementCount;
//element_iter mDataEnd;
//U32 mElementCount;
};

View File

@@ -42,6 +42,8 @@
// The plane normal = [A, B, C]
// The closest approach = D / sqrt(A*A + B*B + C*C)
LL_ALIGN_PREFIX(16)
class LLPlane
{
public:
@@ -100,7 +102,7 @@ public:
private:
LLVector4a mV;
};
} LL_ALIGN_POSTFIX(16);

View File

@@ -124,8 +124,8 @@ public:
if (end_y < mBottom) clip_y = end_y - mBottom;
// clip_? and delta_? should have same sign, since starting point is in rect
// so ratios will be positive
F32 ratio_x = ((F32)clip_x / (F32)delta_x);
F32 ratio_y = ((F32)clip_y / (F32)delta_y);
F32 ratio_x = delta_x ? ((F32)clip_x / (F32)delta_x) : 0.f;
F32 ratio_y = delta_y ? ((F32)clip_y / (F32)delta_y) : 0.f;
if (ratio_x > ratio_y)
{
// clip along x direction

View File

@@ -67,11 +67,10 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)
#define LL_ALIGN_16(var) LL_ALIGN_PREFIX(16) var LL_ALIGN_POSTFIX(16)
#include <xmmintrin.h>
#include <emmintrin.h>
#include "llmemory.h"
#include "llsimdtypes.h"
#include "llsimdtypes.inl"

View File

@@ -62,6 +62,7 @@ inline LLSimdScalar operator/(const LLSimdScalar& a, const LLSimdScalar& b)
inline LLSimdScalar operator-(const LLSimdScalar& a)
{
static LL_ALIGN_16(const U32 signMask[4]) = {0x80000000, 0x80000000, 0x80000000, 0x80000000 };
ll_assert_aligned(signMask,16);
return _mm_xor_ps(*reinterpret_cast<const LLQuad*>(signMask), a);
}
@@ -146,6 +147,7 @@ inline LLSimdScalar& LLSimdScalar::operator/=(const LLSimdScalar& rhs)
inline LLSimdScalar LLSimdScalar::getAbs() const
{
static const LL_ALIGN_16(U32 F_ABS_MASK_4A[4]) = { 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF };
ll_assert_aligned(F_ABS_MASK_4A,16);
return _mm_and_ps( mQ, *reinterpret_cast<const LLQuad*>(F_ABS_MASK_4A));
}

View File

@@ -24,6 +24,7 @@
* $/LicenseInfo$
*/
#include "llmemory.h"
#include "llmath.h"
#include "llquantize.h"
@@ -44,7 +45,10 @@ extern const LLVector4a LL_V4A_EPSILON = reinterpret_cast<const LLVector4a&> ( F
assert(dst != NULL);
assert(bytes > 0);
assert((bytes % sizeof(F32))== 0);
ll_assert_aligned(src,16);
ll_assert_aligned(dst,16);
assert(bytes%16==0);
F32* end = dst + (bytes / sizeof(F32) );
if (bytes > 64)
@@ -189,6 +193,8 @@ void LLVector4a::quantize16( const LLVector4a& low, const LLVector4a& high )
LLVector4a oneOverDelta;
{
static LL_ALIGN_16( const F32 F_TWO_4A[4] ) = { 2.f, 2.f, 2.f, 2.f };
ll_assert_aligned(F_TWO_4A,16);
LLVector4a two; two.load4a( F_TWO_4A );
// Here we use _mm_rcp_ps plus one round of newton-raphson

View File

@@ -32,6 +32,7 @@ class LLRotation;
#include <assert.h>
#include "llpreprocessor.h"
#include "llmemory.h"
///////////////////////////////////
// FIRST TIME USERS PLEASE READ
@@ -46,6 +47,7 @@ class LLRotation;
// LLVector3/LLVector4.
/////////////////////////////////
LL_ALIGN_PREFIX(16)
class LLVector4a
{
public:
@@ -90,6 +92,7 @@ public:
LLVector4a()
{ //DO NOT INITIALIZE -- The overhead is completely unnecessary
ll_assert_aligned(this,16);
}
LLVector4a(F32 x, F32 y, F32 z, F32 w = 0.f)
@@ -313,7 +316,7 @@ public:
private:
LLQuad mQ;
};
} LL_ALIGN_POSTFIX(16);
inline void update_min_max(LLVector4a& min, LLVector4a& max, const LLVector4a& p)
{

View File

@@ -27,6 +27,7 @@
#ifndef LL_VECTOR4LOGICAL_H
#define LL_VECTOR4LOGICAL_H
#include "llmemory.h"
////////////////////////////
// LLVector4Logical
@@ -77,6 +78,7 @@ public:
inline LLVector4Logical& invert()
{
static const LL_ALIGN_16(U32 allOnes[4]) = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
ll_assert_aligned(allOnes,16);
mQ = _mm_andnot_ps( mQ, *(LLQuad*)(allOnes) );
return *this;
}

View File

@@ -29,6 +29,10 @@
#include "llmath.h"
#include <set>
#if !LL_WINDOWS
#include <stdint.h>
#endif
#include <cmath>
#include "llerror.h"
#include "llmemtype.h"
@@ -91,17 +95,6 @@ const S32 SCULPT_MIN_AREA_DETAIL = 1;
extern BOOL gDebugGL;
void assert_aligned(void* ptr, uintptr_t alignment)
{
#if 0
uintptr_t t = (uintptr_t) ptr;
if (t%alignment != 0)
{
llerrs << "Alignment check failed." << llendl;
}
#endif
}
BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, const LLVector3& norm)
{
LLVector3 test = (pt2-pt1)%(pt3-pt2);
@@ -6963,14 +6956,14 @@ void LLVolumeFace::resizeVertices(S32 num_verts)
if (num_verts)
{
mPositions = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
assert_aligned(mPositions, 16);
ll_assert_aligned(mPositions, 16);
mNormals = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
assert_aligned(mNormals, 16);
ll_assert_aligned(mNormals, 16);
//pad texture coordinate block end to allow for QWORD reads
S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF;
mTexCoords = (LLVector2*) ll_aligned_malloc_16(size);
assert_aligned(mTexCoords, 16);
ll_assert_aligned(mTexCoords, 16);
}
else
{
@@ -6991,17 +6984,21 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con
{
S32 new_verts = mNumVertices+1;
S32 new_size = new_verts*16;
// S32 old_size = mNumVertices*16;
S32 old_size = mNumVertices*16;
//positions
mPositions = (LLVector4a*) realloc(mPositions, new_size);
mPositions = (LLVector4a*) ll_aligned_realloc_16(mPositions, new_size, old_size);
ll_assert_aligned(mPositions,16);
//normals
mNormals = (LLVector4a*) realloc(mNormals, new_size);
mNormals = (LLVector4a*) ll_aligned_realloc_16(mNormals, new_size, old_size);
ll_assert_aligned(mNormals,16);
//tex coords
new_size = ((new_verts*8)+0xF) & ~0xF;
mTexCoords = (LLVector2*) realloc(mTexCoords, new_size);
old_size = ((mNumVertices*8)+0xF) & ~0xF;
mTexCoords = (LLVector2*) ll_aligned_realloc_16(mTexCoords, new_size, old_size);
ll_assert_aligned(mTexCoords,16);
//just clear binormals
@@ -7054,7 +7051,8 @@ void LLVolumeFace::pushIndex(const U16& idx)
S32 old_size = ((mNumIndices*2)+0xF) & ~0xF;
if (new_size != old_size)
{
mIndices = (U16*) realloc(mIndices, new_size);
mIndices = (U16*) ll_aligned_realloc_16(mIndices, new_size, old_size);
ll_assert_aligned(mIndices,16);
}
mIndices[mNumIndices++] = idx;
@@ -7095,12 +7093,12 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat
}
//allocate new buffer space
mPositions = (LLVector4a*) realloc(mPositions, new_count*sizeof(LLVector4a));
assert_aligned(mPositions, 16);
mNormals = (LLVector4a*) realloc(mNormals, new_count*sizeof(LLVector4a));
assert_aligned(mNormals, 16);
mTexCoords = (LLVector2*) realloc(mTexCoords, (new_count*sizeof(LLVector2)+0xF) & ~0xF);
assert_aligned(mTexCoords, 16);
mPositions = (LLVector4a*) ll_aligned_realloc_16(mPositions, new_count*sizeof(LLVector4a), mNumVertices*sizeof(LLVector4a));
ll_assert_aligned(mPositions, 16);
mNormals = (LLVector4a*) ll_aligned_realloc_16(mNormals, new_count*sizeof(LLVector4a), mNumVertices*sizeof(LLVector4a));
ll_assert_aligned(mNormals, 16);
mTexCoords = (LLVector2*) ll_aligned_realloc_16(mTexCoords, (new_count*sizeof(LLVector2)+0xF) & ~0xF, (mNumVertices*sizeof(LLVector2)+0xF) & ~0xF);
ll_assert_aligned(mTexCoords, 16);
mNumVertices = new_count;
@@ -7146,7 +7144,7 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat
new_count = mNumIndices + face.mNumIndices;
//allocate new index buffer
mIndices = (U16*) realloc(mIndices, (new_count*sizeof(U16)+0xF) & ~0xF);
mIndices = (U16*) ll_aligned_realloc_16(mIndices, (new_count*sizeof(U16)+0xF) & ~0xF, (mNumIndices*sizeof(U16)+0xF) & ~0xF);
//get destination address into new index buffer
U16* dst_idx = mIndices+mNumIndices;

View File

@@ -37,6 +37,15 @@
class LLVolumeTriangle : public LLRefCount
{
public:
void* operator new(size_t size)
{
return ll_aligned_malloc_16(size);
}
void operator delete(void* ptr)
{
ll_aligned_free_16(ptr);
}
LLVolumeTriangle()
{
mBinIndex = -1;
@@ -58,7 +67,7 @@ public:
}
LLVector4a mPositionGroup;
LL_ALIGN_16(LLVector4a mPositionGroup);
const LLVector4a* mV[3];
U16 mIndex[3];
@@ -78,6 +87,16 @@ class LLVolumeOctreeListener : public LLOctreeListener<LLVolumeTriangle>
{
public:
void* operator new(size_t size)
{
return ll_aligned_malloc_16(size);
}
void operator delete(void* ptr)
{
ll_aligned_free_16(ptr);
}
LLVolumeOctreeListener(LLOctreeNode<LLVolumeTriangle>* node);
~LLVolumeOctreeListener();
@@ -104,8 +123,8 @@ public:
public:
LLVector4a mBounds[2]; // bounding box (center, size) of this node and all its children (tight fit to objects)
LLVector4a mExtents[2]; // extents (min, max) of this node and all its children
LL_ALIGN_16(LLVector4a mBounds[2]); // bounding box (center, size) of this node and all its children (tight fit to objects)
LL_ALIGN_16(LLVector4a mExtents[2]); // extents (min, max) of this node and all its children
};
class LLOctreeTriangleRayIntersect : public LLOctreeTraveler<LLVolumeTriangle>

View File

@@ -308,9 +308,10 @@ LLAtomicU32 Stats::llsd_body_count;
LLAtomicU32 Stats::llsd_body_parse_error;
LLAtomicU32 Stats::raw_body_count;
// Called from BufferedCurlEasyRequest::setStatusAndReason.
// The only allowed values for 'status' are S <= status < S+20, where S={100,200,300,400,500}.
U32 Stats::status2index(U32 status)
{
llassert_always(status >= 100 && status < 600 && (status % 100) < 20); // Max value 519.
return (status - 100) / 100 * 20 + status % 100; // Returns 0..99 (for status 100..519).
}
@@ -418,6 +419,7 @@ void cleanupCurl(void)
if (CurlMultiHandle::getTotalMultiHandles() != 0)
llwarns << "Not all CurlMultiHandle objects were destroyed!" << llendl;
AIStateMachine::flush();
clearCommandQueue();
Stats::print();
ssl_cleanup();
@@ -491,12 +493,10 @@ void Stats::print(void)
// Even more strict, BufferedCurlEasyRequest may not be created directly either, only as
// base class of ThreadSafeBufferedCurlEasyRequest.
llassert(BufferedCurlEasyRequest_count == ThreadSafeBufferedCurlEasyRequest_count);
// Each AICurlEasyRequestStateMachine is responsible for exactly one easy handle.
llassert(easy_handles >= AICurlEasyRequest_count);
// Each AICurlEasyRequestStateMachine has one AICurlEasyRequest member.
llassert(AICurlEasyRequest_count >= AICurlEasyRequestStateMachine_count);
// AIFIXME: is this really always the case? And why?
llassert(easy_handles <= ResponderBase_count);
llassert(easy_handles <= S32(ResponderBase_count));
}
} // namespace AICurlInterface
@@ -546,6 +546,9 @@ void CurlEasyHandle::handle_easy_error(CURLcode code)
// Throws AICurlNoEasyHandle.
CurlEasyHandle::CurlEasyHandle(void) : mActiveMultiHandle(NULL), mErrorBuffer(NULL), mQueuedForRemoval(false)
#ifdef DEBUG_CURLIO
, mDebug(false)
#endif
#ifdef SHOW_ASSERT
, mRemovedPerCommand(true)
#endif
@@ -589,6 +592,12 @@ CurlEasyHandle::~CurlEasyHandle()
llassert(!mActiveMultiHandle);
curl_easy_cleanup(mEasyHandle);
Stats::easy_cleanup_calls++;
#ifdef DEBUG_CURLIO
if (mDebug)
{
debug_curl_remove_easy(mEasyHandle);
}
#endif
}
//static
@@ -761,17 +770,17 @@ void CurlEasyRequest::setoptString(CURLoption option, std::string const& value)
setopt(option, value.c_str());
}
void CurlEasyRequest::setPost(AIPostFieldPtr const& postdata, U32 size)
void CurlEasyRequest::setPost(AIPostFieldPtr const& postdata, U32 size, bool keepalive)
{
llassert_always(postdata->data());
DoutCurl("POST size is " << size << " bytes: \"" << libcwd::buf2str(postdata->data(), size) << "\".");
setPostField(postdata); // Make sure the data stays around until we don't need it anymore.
setPost_raw(size, postdata->data());
setPost_raw(size, postdata->data(), keepalive);
}
void CurlEasyRequest::setPost_raw(U32 size, char const* data)
void CurlEasyRequest::setPost_raw(U32 size, char const* data, bool keepalive)
{
if (!data)
{
@@ -781,7 +790,7 @@ void CurlEasyRequest::setPost_raw(U32 size, char const* data)
// The server never replies with 100-continue, so suppress the "Expect: 100-continue" header that libcurl adds by default.
addHeader("Expect:");
if (size > 0)
if (size > 0 && keepalive)
{
addHeader("Connection: keep-alive");
addHeader("Keep-alive: 300");
@@ -1006,6 +1015,8 @@ CURLcode CurlEasyRequest::curlCtxCallback(CURL* curl, void* sslctx, void* parm)
options |= SSL_OP_NO_TLSv1_1;
}
#else
// This is expected when you compile against the headers of a version < 1.0.1 and then link at runtime with version >= 1.0.1.
// Don't do that.
llassert_always(!need_renegotiation_hack);
#endif
SSL_CTX_set_options(ctx, options);
@@ -1226,6 +1237,20 @@ void CurlEasyRequest::removed_from_multi_handle(AICurlEasyRequest_wat& curl_easy
mHandleEventsTarget->removed_from_multi_handle(curl_easy_request_w);
}
void CurlEasyRequest::bad_file_descriptor(AICurlEasyRequest_wat& curl_easy_request_w)
{
if (mHandleEventsTarget)
mHandleEventsTarget->bad_file_descriptor(curl_easy_request_w);
}
#ifdef SHOW_ASSERT
void CurlEasyRequest::queued_for_removal(AICurlEasyRequest_wat& curl_easy_request_w)
{
if (mHandleEventsTarget)
mHandleEventsTarget->queued_for_removal(curl_easy_request_w);
}
#endif
PerHostRequestQueuePtr CurlEasyRequest::getPerHostPtr(void)
{
if (!mPerHostPtr)
@@ -1289,7 +1314,17 @@ void BufferedCurlEasyRequest::timed_out(void)
mResponder->finished(CURLE_OK, HTTP_INTERNAL_ERROR, "Request timeout, aborted.", sChannels, mOutput);
if (mResponder->needsHeaders())
{
send_buffer_events_to(NULL); // Revoke buffer events: we sent them to the responder.
send_buffer_events_to(NULL); // Revoke buffer events: we send them to the responder.
}
mResponder = NULL;
}
void BufferedCurlEasyRequest::bad_socket(void)
{
mResponder->finished(CURLE_OK, HTTP_INTERNAL_ERROR, "File descriptor went bad! Aborted.", sChannels, mOutput);
if (mResponder->needsHeaders())
{
send_buffer_events_to(NULL); // Revoke buffer events: we send them to the responder.
}
mResponder = NULL;
}
@@ -1348,11 +1383,22 @@ void BufferedCurlEasyRequest::prepRequest(AICurlEasyRequest_wat& curl_easy_reque
curl_easy_request_w->setReadCallback(&curlReadCallback, lockobj);
curl_easy_request_w->setHeaderCallback(&curlHeaderCallback, lockobj);
bool allow_cookies = headers.hasHeader("Cookie");
// Allow up to ten redirects.
if (responder->followRedir())
{
curl_easy_request_w->setopt(CURLOPT_FOLLOWLOCATION, 1);
curl_easy_request_w->setopt(CURLOPT_MAXREDIRS, HTTP_REDIRECTS_DEFAULT);
// This is needed (at least) for authentication after temporary redirection
// to id.secondlife.com for marketplace.secondlife.com.
allow_cookies = true;
}
if (allow_cookies)
{
// Given an empty or non-existing file or by passing the empty string (""),
// this option will enable cookies for this curl handle, making it understand
// and parse received cookies and then use matching cookies in future requests.
curl_easy_request_w->setopt(CURLOPT_COOKIEFILE, "");
}
// Keep responder alive.
@@ -1398,3 +1444,18 @@ CurlMultiHandle::~CurlMultiHandle()
}
} // namespace AICurlPrivate
#if LL_LINUX
extern "C" {
// Keep linker happy.
const SSL_METHOD *SSLv2_client_method(void)
{
// Never used.
llassert_always(false);
return NULL;
}
}
#endif

View File

@@ -208,6 +208,10 @@ struct AICurlEasyHandleEvents {
virtual void added_to_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w) = 0;
virtual void finished(AICurlEasyRequest_wat& curl_easy_request_w) = 0;
virtual void removed_from_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w) = 0;
virtual void bad_file_descriptor(AICurlEasyRequest_wat& curl_easy_request_w) = 0;
#ifdef SHOW_ASSERT
virtual void queued_for_removal(AICurlEasyRequest_wat& curl_easy_request_w) = 0;
#endif
// Avoid compiler warning.
virtual ~AICurlEasyHandleEvents() { }
};
@@ -271,6 +275,11 @@ class AICurlEasyRequest {
// Queue a command to remove this request from the multi session (or cancel a queued command to add it).
void removeRequest(void);
#ifdef DEBUG_CURLIO
// Turn on/off debug output.
void debug(bool debug) { AICurlEasyRequest_wat(*mBufferedCurlEasyRequest)->debug(debug); }
#endif
private:
// The actual pointer to the ThreadSafeBufferedCurlEasyRequest instance.
AICurlPrivate::BufferedCurlEasyRequestPtr mBufferedCurlEasyRequest;

View File

@@ -40,7 +40,8 @@ enum curleasyrequeststatemachine_state_type {
AICurlEasyRequestStateMachine_timedOut, // This must be smaller than the rest, so they always overrule.
AICurlEasyRequestStateMachine_finished,
AICurlEasyRequestStateMachine_removed, // The removed states must be largest two, so they are never ignored.
AICurlEasyRequestStateMachine_removed_after_finished
AICurlEasyRequestStateMachine_removed_after_finished,
AICurlEasyRequestStateMachine_bad_file_descriptor
};
char const* AICurlEasyRequestStateMachine::state_str_impl(state_type run_state) const
@@ -54,6 +55,7 @@ char const* AICurlEasyRequestStateMachine::state_str_impl(state_type run_state)
AI_CASE_RETURN(AICurlEasyRequestStateMachine_finished);
AI_CASE_RETURN(AICurlEasyRequestStateMachine_removed);
AI_CASE_RETURN(AICurlEasyRequestStateMachine_removed_after_finished);
AI_CASE_RETURN(AICurlEasyRequestStateMachine_bad_file_descriptor);
}
return "UNKNOWN STATE";
}
@@ -94,6 +96,24 @@ void AICurlEasyRequestStateMachine::removed_from_multi_handle(AICurlEasyRequest_
set_state(mFinished ? AICurlEasyRequestStateMachine_removed_after_finished : AICurlEasyRequestStateMachine_removed);
}
// CURL-THREAD
void AICurlEasyRequestStateMachine::bad_file_descriptor(AICurlEasyRequest_wat&)
{
if (!mFinished)
{
mFinished = true;
set_state(AICurlEasyRequestStateMachine_bad_file_descriptor);
}
}
#ifdef SHOW_ASSERT
// CURL-THREAD
void AICurlEasyRequestStateMachine::queued_for_removal(AICurlEasyRequest_wat&)
{
llassert(mFinished || mTimedOut); // See AICurlEasyRequestStateMachine::removed_from_multi_handle
}
#endif
void AICurlEasyRequestStateMachine::multiplex_impl(void)
{
mSetStateLock.lock();
@@ -207,6 +227,11 @@ void AICurlEasyRequestStateMachine::multiplex_impl(void)
break;
}
case AICurlEasyRequestStateMachine_bad_file_descriptor:
{
AICurlEasyRequest_wat(*mCurlEasyRequest)->bad_socket();
abort();
}
}
}

View File

@@ -81,6 +81,14 @@ class AICurlEasyRequestStateMachine : public AIStateMachine, public AICurlEasyHa
// Called after this curl easy handle was removed from a multi handle.
/*virtual*/ void removed_from_multi_handle(AICurlEasyRequest_wat&);
// Called when the curl thread detected that the socket of this handle has become unusable.
/*virtual*/ void bad_file_descriptor(AICurlEasyRequest_wat&);
#ifdef SHOW_ASSERT
// Called when a command was added to remove this easy handle.
/*virtual*/ void queued_for_removal(AICurlEasyRequest_wat&);
#endif
protected:
// AIStateMachine implementations.

View File

@@ -56,12 +56,17 @@ PerHostRequestQueuePtr PerHostRequestQueue::instance(std::string const& hostname
//static
void PerHostRequestQueue::release(PerHostRequestQueuePtr& instance)
{
if (instance->lastone())
if (instance->exactly_two_left()) // Being 'instance' and the one in sInstanceMap.
{
// The viewer can be have left main() we can't access the global sInstanceMap anymore.
if (LLApp::isStopped())
{
return;
}
instance_map_wat instance_map_w(sInstanceMap);
// It is possible that 'lastone' is not up to date anymore.
// It is possible that 'exactly_two_left' is not up to date anymore.
// Therefore, recheck the condition now that we have locked sInstanceMap.
if (!instance->lastone())
if (!instance->exactly_two_left())
{
// Some other thread added this host in the meantime.
return;
@@ -87,13 +92,13 @@ void PerHostRequestQueue::release(PerHostRequestQueuePtr& instance)
bool PerHostRequestQueue::throttled() const
{
llassert(mAdded <= curl_concurrent_connections_per_host);
return mAdded == curl_concurrent_connections_per_host;
llassert(mAdded <= int(curl_concurrent_connections_per_host));
return mAdded == int(curl_concurrent_connections_per_host);
}
void PerHostRequestQueue::added_to_multi_handle(void)
{
llassert(mAdded < curl_concurrent_connections_per_host);
llassert(mAdded < int(curl_concurrent_connections_per_host));
++mAdded;
}

View File

@@ -118,7 +118,7 @@ class PerHostRequestQueue {
class RefCountedThreadSafePerHostRequestQueue : public threadsafe_PerHostRequestQueue {
public:
RefCountedThreadSafePerHostRequestQueue(void) : mReferenceCount(0) { }
bool lastone(void) const { llassert(mReferenceCount >= 2); return mReferenceCount == 2; }
bool exactly_two_left(void) const { return mReferenceCount == 2; }
private:
// Used by PerHostRequestQueuePtr. Object is deleted when reference count reaches zero.

View File

@@ -119,6 +119,7 @@ inline CURLMcode check_multi_code(CURLMcode code) { AICurlInterface::Stats::mult
bool curlThreadIsRunning(void);
void wakeUpCurlThread(void);
void stopCurlThread(void);
void clearCommandQueue(void);
#define DECLARE_SETOPT(param_type) \
CURLcode setopt(CURLoption option, param_type parameter)
@@ -200,12 +201,19 @@ class CurlEasyHandle : public boost::noncopyable, protected AICurlEasyHandleEven
// In case it's added after being removed.
void add_queued(void) { mQueuedForRemoval = false; }
#ifdef DEBUG_CURLIO
void debug(bool debug) { if (mDebug) debug_curl_remove_easy(mEasyHandle); if (debug) debug_curl_add_easy(mEasyHandle); mDebug = debug; }
#endif
private:
CURL* mEasyHandle;
CURLM* mActiveMultiHandle;
mutable char* mErrorBuffer;
AIPostFieldPtr mPostField; // This keeps the POSTFIELD data alive for as long as the easy handle exists.
bool mQueuedForRemoval; // Set if the easy handle is (probably) added to the multi handle, but is queued for removal.
#ifdef DEBUG_CURLIO
bool mDebug;
#endif
#ifdef SHOW_ASSERT
public:
bool mRemovedPerCommand; // Set if mActiveMultiHandle was reset as per command from the main thread.
@@ -269,11 +277,11 @@ class CurlEasyHandle : public boost::noncopyable, protected AICurlEasyHandleEven
// and the CurlEasyRequest destructed.
class CurlEasyRequest : public CurlEasyHandle {
private:
void setPost_raw(U32 size, char const* data);
void setPost_raw(U32 size, char const* data, bool keepalive);
public:
void setPost(U32 size) { setPost_raw(size, NULL); }
void setPost(AIPostFieldPtr const& postdata, U32 size);
void setPost(char const* data, U32 size) { setPost(new AIPostField(data), size); }
void setPost(U32 size, bool keepalive = true) { setPost_raw(size, NULL, keepalive); }
void setPost(AIPostFieldPtr const& postdata, U32 size, bool keepalive = true);
void setPost(char const* data, U32 size, bool keepalive = true) { setPost(new AIPostField(data), size, keepalive); }
void setoptString(CURLoption option, std::string const& value);
void addHeader(char const* str);
void addHeaders(AIHTTPHeaders const& headers);
@@ -412,6 +420,11 @@ class CurlEasyRequest : public CurlEasyHandle {
/*virtual*/ void added_to_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w);
/*virtual*/ void finished(AICurlEasyRequest_wat& curl_easy_request_w);
/*virtual*/ void removed_from_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w);
public:
/*virtual*/ void bad_file_descriptor(AICurlEasyRequest_wat& curl_easy_request_w);
#ifdef SHOW_ASSERT
/*virtual*/ void queued_for_removal(AICurlEasyRequest_wat& curl_easy_request_w);
#endif
};
// This class adds input/output buffers to the request and hooks up the libcurl callbacks to use those buffers.
@@ -430,6 +443,9 @@ class BufferedCurlEasyRequest : public CurlEasyRequest {
// Called if libcurl doesn't deliver within AIHTTPTimeoutPolicy::mMaximumTotalDelay seconds.
void timed_out(void);
// Called if the underlaying socket went bad (ie, when accidently closed by a buggy library).
void bad_socket(void);
// Called after removed_from_multi_handle was called.
void processOutput(void);

View File

@@ -286,14 +286,36 @@ enum refresh_t {
empty_and_complete = complete|empty
};
// A class with info for each socket that is in use by curl.
class CurlSocketInfo
{
public:
CurlSocketInfo(MultiHandle& multi_handle, CURL* easy, curl_socket_t s, int action, ThreadSafeBufferedCurlEasyRequest* lockobj);
~CurlSocketInfo();
void set_action(int action);
void mark_dead(void) { set_action(CURL_POLL_NONE); mDead = true; }
curl_socket_t getSocketFd(void) const { return mSocketFd; }
AICurlEasyRequest& getEasyRequest(void) { return mEasyRequest; }
private:
MultiHandle& mMultiHandle;
CURL const* mEasy;
curl_socket_t mSocketFd;
int mAction;
bool mDead;
AICurlEasyRequest mEasyRequest;
LLPointer<HTTPTimeout> mTimeout;
};
class PollSet
{
public:
PollSet(void);
// Add/remove a filedescriptor to/from mFileDescriptors.
void add(curl_socket_t s);
void remove(curl_socket_t s);
void add(CurlSocketInfo* sp);
void remove(CurlSocketInfo* sp);
// Copy mFileDescriptors to an internal fd_set that is returned by access().
// Returns if all fds could be copied (complete) and/or if the resulting fd_set is empty.
@@ -307,8 +329,8 @@ class PollSet
curl_socket_t get_max_fd(void) const { return mMaxFdSet; }
#endif
// Return true if a filedescriptor is set in mFileDescriptors (used for debugging).
bool contains(curl_socket_t s) const;
// Return a pointer to the corresponding CurlSocketInfo if a filedescriptor is set in mFileDescriptors, or NULL if s is not set.
CurlSocketInfo* contains(curl_socket_t s) const;
// Return true if a filedescriptor is set in mFdSet.
bool is_set(curl_socket_t s) const;
@@ -323,7 +345,7 @@ class PollSet
void next(void); // Advance to next filedescriptor.
private:
curl_socket_t* mFileDescriptors;
CurlSocketInfo** mFileDescriptors;
int mNrFds; // The number of filedescriptors in the array.
int mNext; // The index of the first file descriptor to start copying, the next call to refresh().
@@ -332,8 +354,8 @@ class PollSet
#if !WINDOWS_CODE
curl_socket_t mMaxFd; // The largest filedescriptor in the array, or CURL_SOCKET_BAD when it is empty.
curl_socket_t mMaxFdSet; // The largest filedescriptor set in mFdSet by refresh(), or CURL_SOCKET_BAD when it was empty.
std::vector<curl_socket_t> mCopiedFileDescriptors; // Filedescriptors copied by refresh to mFdSet.
std::vector<curl_socket_t>::iterator mIter; // Index into mCopiedFileDescriptors for next(); loop variable.
std::vector<CurlSocketInfo*> mCopiedFileDescriptors; // Filedescriptors copied by refresh to mFdSet.
std::vector<CurlSocketInfo*>::iterator mIter; // Index into mCopiedFileDescriptors for next(); loop variable.
#else
unsigned int mIter; // Index into fd_set::fd_array.
#endif
@@ -359,7 +381,7 @@ class PollSet
static size_t const MAXSIZE = llmax(1024, FD_SETSIZE);
// Create an empty PollSet.
PollSet::PollSet(void) : mFileDescriptors(new curl_socket_t [MAXSIZE]),
PollSet::PollSet(void) : mFileDescriptors(new CurlSocketInfo* [MAXSIZE]),
mNrFds(0), mNext(0)
#if !WINDOWS_CODE
, mMaxFd(-1), mMaxFdSet(-1)
@@ -369,17 +391,17 @@ PollSet::PollSet(void) : mFileDescriptors(new curl_socket_t [MAXSIZE]),
}
// Add filedescriptor s to the PollSet.
void PollSet::add(curl_socket_t s)
void PollSet::add(CurlSocketInfo* sp)
{
llassert_always(mNrFds < (int)MAXSIZE);
mFileDescriptors[mNrFds++] = s;
mFileDescriptors[mNrFds++] = sp;
#if !WINDOWS_CODE
mMaxFd = llmax(mMaxFd, s);
mMaxFd = llmax(mMaxFd, sp->getSocketFd());
#endif
}
// Remove filedescriptor s from the PollSet.
void PollSet::remove(curl_socket_t s)
void PollSet::remove(CurlSocketInfo* sp)
{
// The number of open filedescriptors is relatively small,
// and on top of that we rather do something CPU intensive
@@ -391,15 +413,15 @@ void PollSet::remove(curl_socket_t s)
// back, keeping it compact and keeping the filedescriptors
// in the same order (which is supposedly their priority).
//
// The general case is where mFileDescriptors contains s at an index
// The general case is where mFileDescriptors contains sp at an index
// between 0 and mNrFds:
// mNrFds = 6
// v
// index: 0 1 2 3 4 5
// a b c s d e
// This function should never be called unless s is actually in mFileDescriptors,
// as a result of a previous call to PollSet::add().
// This function should never be called unless sp is actually in mFileDescriptors,
// as a result of a previous call to PollSet::add(sp).
llassert(mNrFds > 0);
// Correct mNrFds for when the descriptor is removed.
@@ -409,17 +431,18 @@ void PollSet::remove(curl_socket_t s)
// v
// index: 0 1 2 3 4 5
// a b c s d e
curl_socket_t cur = mFileDescriptors[i]; // cur = 'e'
curl_socket_t const s = sp->getSocketFd();
CurlSocketInfo* cur = mFileDescriptors[i]; // cur = 'e'
#if !WINDOWS_CODE
curl_socket_t max = -1;
#endif
while (cur != s)
while (cur != sp)
{
llassert(i > 0);
curl_socket_t next = mFileDescriptors[--i]; // next = 'd'
CurlSocketInfo* next = mFileDescriptors[--i]; // next = 'd'
mFileDescriptors[i] = cur; // Overwrite 'd' with 'e'.
#if !WINDOWS_CODE
max = llmax(max, cur); // max is the maximum value in 'i' or higher.
max = llmax(max, cur->getSocketFd()); // max is the maximum value in 'i' or higher.
#endif
cur = next; // cur = 'd'
// i NrFds = 5
@@ -427,21 +450,21 @@ void PollSet::remove(curl_socket_t s)
// index: 0 1 2 3 4
// a b c s e // cur = 'd'
//
// Next loop iteration: next = 's', overwrite 's' with 'd', cur = 's'; loop terminates.
// Next loop iteration: next = 'sp', overwrite 'sp' with 'd', cur = 'sp'; loop terminates.
// i NrFds = 5
// v v
// index: 0 1 2 3 4
// a b c d e // cur = 's'
// a b c d e // cur = 'sp'
}
llassert(cur == s);
llassert(cur == sp);
// At this point i was decremented once more and points to the element before the old s.
// i NrFds = 5
// v v
// index: 0 1 2 3 4
// a b c d e // max = llmax('d', 'e')
// If mNext pointed to an element before s, it should be left alone. Otherwise, if mNext pointed
// to s it must now point to 'd', or if it pointed beyond 's' it must be decremented by 1.
// If mNext pointed to an element before sp, it should be left alone. Otherwise, if mNext pointed
// to sp it must now point to 'd', or if it pointed beyond 'sp' it must be decremented by 1.
if (mNext > i) // i is where s was.
--mNext;
@@ -451,8 +474,8 @@ void PollSet::remove(curl_socket_t s)
{
while (i > 0)
{
curl_socket_t next = mFileDescriptors[--i];
max = llmax(max, next);
CurlSocketInfo* next = mFileDescriptors[--i];
max = llmax(max, next->getSocketFd());
}
mMaxFd = max;
llassert(mMaxFd < s);
@@ -487,12 +510,12 @@ void PollSet::remove(curl_socket_t s)
#endif
}
bool PollSet::contains(curl_socket_t fd) const
CurlSocketInfo* PollSet::contains(curl_socket_t fd) const
{
for (int i = 0; i < mNrFds; ++i)
if (mFileDescriptors[i] == fd)
return true;
return false;
if (mFileDescriptors[i]->getSocketFd() == fd)
return mFileDescriptors[i];
return NULL;
}
inline bool PollSet::is_set(curl_socket_t fd) const
@@ -536,7 +559,7 @@ refresh_t PollSet::refresh(void)
// Calculate mMaxFdSet.
// Run over FD_SETSIZE - 1 elements, starting at mNext, wrapping to 0 when we reach the end.
int max = -1, i = mNext, count = 0;
while (++count < FD_SETSIZE) { max = llmax(max, mFileDescriptors[i]); if (++i == mNrFds) i = 0; }
while (++count < FD_SETSIZE) { max = llmax(max, mFileDescriptors[i]->getSocketFd()); if (++i == mNrFds) i = 0; }
mMaxFdSet = max;
#endif
}
@@ -556,7 +579,7 @@ refresh_t PollSet::refresh(void)
mNext = i;
return not_complete_not_empty;
}
FD_SET(mFileDescriptors[i], &mFdSet);
FD_SET(mFileDescriptors[i]->getSocketFd(), &mFdSet);
#if !WINDOWS_CODE
mCopiedFileDescriptors.push_back(mFileDescriptors[i]);
#endif
@@ -603,7 +626,7 @@ void PollSet::reset(void)
else
{
mIter = mCopiedFileDescriptors.begin();
if (!FD_ISSET(*mIter, &mFdSet))
if (!FD_ISSET((*mIter)->getSocketFd(), &mFdSet))
next();
}
#endif
@@ -614,7 +637,7 @@ inline curl_socket_t PollSet::get(void) const
#if WINDOWS_CODE
return (mIter >= mFdSet.fd_count) ? CURL_SOCKET_BAD : mFdSet.fd_array[mIter];
#else
return (mIter == mCopiedFileDescriptors.end()) ? CURL_SOCKET_BAD : *mIter;
return (mIter == mCopiedFileDescriptors.end()) ? CURL_SOCKET_BAD : (*mIter)->getSocketFd();
#endif
}
@@ -625,7 +648,7 @@ void PollSet::next(void)
++mIter;
#else
llassert(mIter != mCopiedFileDescriptors.end()); // Only call next() if the last call to get() didn't return -1.
while (++mIter != mCopiedFileDescriptors.end() && !FD_ISSET(*mIter, &mFdSet));
while (++mIter != mCopiedFileDescriptors.end() && !FD_ISSET((*mIter)->getSocketFd(), &mFdSet));
#endif
}
@@ -743,26 +766,8 @@ std::ostream& operator<<(std::ostream& os, DebugFdSet const& s)
}
#endif
// A class with info for each socket that is in use by curl.
class CurlSocketInfo
{
public:
CurlSocketInfo(MultiHandle& multi_handle, CURL* easy, curl_socket_t s, int action, ThreadSafeBufferedCurlEasyRequest* lockobj);
~CurlSocketInfo();
void set_action(int action);
private:
MultiHandle& mMultiHandle;
CURL const* mEasy;
curl_socket_t mSocketFd;
int mAction;
AICurlEasyRequest mEasyRequest;
LLPointer<HTTPTimeout> mTimeout;
};
CurlSocketInfo::CurlSocketInfo(MultiHandle& multi_handle, CURL* easy, curl_socket_t s, int action, ThreadSafeBufferedCurlEasyRequest* lockobj) :
mMultiHandle(multi_handle), mEasy(easy), mSocketFd(s), mAction(CURL_POLL_NONE), mEasyRequest(lockobj)
mMultiHandle(multi_handle), mEasy(easy), mSocketFd(s), mAction(CURL_POLL_NONE), mDead(false), mEasyRequest(lockobj)
{
llassert(*AICurlEasyRequest_wat(*mEasyRequest) == easy);
mMultiHandle.assign(s, this);
@@ -785,23 +790,28 @@ CurlSocketInfo::~CurlSocketInfo()
void CurlSocketInfo::set_action(int action)
{
if (mDead)
{
return;
}
Dout(dc::curl, "CurlSocketInfo::set_action(" << action_str(mAction) << " --> " << action_str(action) << ") [" << (void*)mEasyRequest.get_ptr().get() << "]");
int toggle_action = mAction ^ action;
mAction = action;
if ((toggle_action & CURL_POLL_IN))
{
if ((action & CURL_POLL_IN))
mMultiHandle.mReadPollSet->add(mSocketFd);
mMultiHandle.mReadPollSet->add(this);
else
mMultiHandle.mReadPollSet->remove(mSocketFd);
mMultiHandle.mReadPollSet->remove(this);
}
if ((toggle_action & CURL_POLL_OUT))
{
if ((action & CURL_POLL_OUT))
mMultiHandle.mWritePollSet->add(mSocketFd);
mMultiHandle.mWritePollSet->add(this);
else
{
mMultiHandle.mWritePollSet->remove(mSocketFd);
mMultiHandle.mWritePollSet->remove(this);
// The following is a bit of a hack, needed because of the lack of proper timeout callbacks in libcurl.
// The removal of CURL_POLL_OUT could be part of the SSL handshake, therefore check if we're already connected:
@@ -838,6 +848,9 @@ class AICurlThread : public LLThread
// MAIN-THREAD
void stop_thread(void) { mRunning = false; wakeup_thread(); }
// MAIN-THREAD
apr_status_t join_thread(void);
protected:
virtual void run(void);
void wakeup(AICurlMultiHandle_wat const& multi_handle_w);
@@ -1065,6 +1078,10 @@ void AICurlThread::wakeup_thread(void)
DoutEntering(dc::curl, "AICurlThread::wakeup_thread");
llassert(is_main_thread());
// If we are already exiting the viewer then return immediately.
if (!mRunning)
return;
// Try if curl thread is still awake and if so, pass the new commands directly.
if (mWakeUpMutex.tryLock())
{
@@ -1106,6 +1123,17 @@ void AICurlThread::wakeup_thread(void)
#endif
}
apr_status_t AICurlThread::join_thread(void)
{
apr_status_t retval = APR_SUCCESS;
if (sInstance)
{
apr_thread_join(&retval, sInstance->mAPRThreadp);
delete sInstance;
}
return retval;
}
void AICurlThread::wakeup(AICurlMultiHandle_wat const& multi_handle_w)
{
DoutEntering(dc::curl, "AICurlThread::wakeup");
@@ -1251,6 +1279,26 @@ void AICurlThread::process_commands(AICurlMultiHandle_wat const& multi_handle_w)
}
}
// Return true if fd is a 'bad' socket.
static bool is_bad(curl_socket_t fd, bool for_writing)
{
fd_set tmp;
FD_ZERO(&tmp);
FD_SET(fd, &tmp);
fd_set* readfds = for_writing ? NULL : &tmp;
fd_set* writefds = for_writing ? &tmp : NULL;
#if !WINDOWS_CODE
int nfds = fd + 1;
#else
int nfds = 64;
#endif
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 10;
int ret = select(nfds, readfds, writefds, NULL, &timeout);
return ret == -1;
}
// The main loop of the curl thread.
void AICurlThread::run(void)
{
@@ -1262,7 +1310,7 @@ void AICurlThread::run(void)
{
// If mRunning is true then we can only get here if mWakeUpFd != CURL_SOCKET_BAD.
llassert(mWakeUpFd != CURL_SOCKET_BAD);
// Copy the next batch of file descriptors from the PollSets mFiledescriptors into their mFdSet.
// Copy the next batch of file descriptors from the PollSets mFileDescriptors into their mFdSet.
multi_handle_w->mReadPollSet->refresh();
refresh_t wres = multi_handle_w->mWritePollSet->refresh();
// Add wake up fd if any, and pass NULL to select() if a set is empty.
@@ -1379,6 +1427,51 @@ void AICurlThread::run(void)
if (ready == -1)
{
llwarns << "select() failed: " << errno << ", " << strerror(errno) << llendl;
if (errno == EBADF)
{
// Somewhere (fmodex?) one of our file descriptors was closed. Try to recover by finding out which.
llassert_always(!is_bad(mWakeUpFd, false)); // We can't recover from this.
PollSet* found = NULL;
// Run over all read file descriptors.
multi_handle_w->mReadPollSet->refresh();
multi_handle_w->mReadPollSet->reset();
curl_socket_t fd;
while ((fd = multi_handle_w->mReadPollSet->get()) != CURL_SOCKET_BAD)
{
if (is_bad(fd, false))
{
found = multi_handle_w->mReadPollSet;
break;
}
multi_handle_w->mReadPollSet->next();
}
if (!found)
{
// Try all write file descriptors.
refresh_t wres = multi_handle_w->mWritePollSet->refresh();
if (!(wres & empty))
{
multi_handle_w->mWritePollSet->reset();
while ((fd = multi_handle_w->mWritePollSet->get()) != CURL_SOCKET_BAD)
{
if (is_bad(fd, true))
{
found = multi_handle_w->mWritePollSet;
break;
}
multi_handle_w->mWritePollSet->next();
}
}
}
llassert_always(found); // It makes no sense to continue if we can't recover.
// Find the corresponding CurlSocketInfo
CurlSocketInfo* sp = found->contains(fd);
llassert_always(sp); // fd was just *read* from this sp.
sp->mark_dead(); // Make sure it's never used again.
AICurlEasyRequest_wat curl_easy_request_w(*sp->getEasyRequest());
curl_easy_request_w->pause(CURLPAUSE_ALL); // Keep libcurl at bay.
curl_easy_request_w->bad_file_descriptor(curl_easy_request_w); // Make the main thread cleanly terminate this transaction.
}
continue;
}
// Clock count used for timeouts.
@@ -1609,7 +1702,9 @@ CURLMcode MultiHandle::remove_easy_request(addedEasyRequests_type::iterator cons
ThreadSafeBufferedCurlEasyRequest* lockobj = iter->get_ptr().get();
#endif
mAddedEasyRequests.erase(iter);
#if CWDEBUG
Dout(dc::curl, "MultiHandle::remove_easy_request: Removed AICurlEasyRequest " << (void*)lockobj << "; now processing " << mAddedEasyRequests.size() << " easy handles.");
#endif
// Attempt to add a queued request, if any.
PerHostRequestQueue_wat(*per_host)->add_queued_to(this);
@@ -1816,7 +1911,7 @@ bool HTTPTimeout::data_received(size_t n)
// | | | | | | | | | | | | | |
bool HTTPTimeout::lowspeed(size_t bytes)
{
DoutCurlEntering("HTTPTimeout::lowspeed(" << bytes << ")");
//DoutCurlEntering("HTTPTimeout::lowspeed(" << bytes << ")"); commented out... too spammy for normal use.
// The algorithm to determine if we timed out if different from how libcurls CURLOPT_LOW_SPEED_TIME works.
//
@@ -1994,12 +2089,11 @@ void HTTPTimeout::print_diagnostics(CurlEasyRequest const* curl_easy_request, ch
#if LOWRESTIMER
llinfos << "Hostname seems to have been still in the DNS cache." << llendl;
#else
llwarns << "Huh? Curl returned CURLE_OPERATION_TIMEDOUT, but DNS lookup did not occur according to timings. Expected CURLE_COULDNT_RESOLVE_PROXY or CURLE_COULDNT_RESOLVE_HOST!" << llendl;
llwarns << "Curl returned CURLE_OPERATION_TIMEDOUT and DNS lookup did not occur according to timings. Apparently the resolve attempt timed out (bad network?)" << llendl;
llassert(connect_time == 0);
llassert(appconnect_time == 0);
llassert(pretransfer_time == 0);
llassert(starttransfer_time == 0);
// Fatal error for diagnostics.
return;
#endif
}
@@ -2022,11 +2116,10 @@ void HTTPTimeout::print_diagnostics(CurlEasyRequest const* curl_easy_request, ch
#endif
)
{
llwarns << "Huh? Curl returned CURLE_OPERATION_TIMEDOUT, but connection did not occur according to timings. Expected CURLE_COULDNT_CONNECT!" << llendl;
llwarns << "Curl returned CURLE_OPERATION_TIMEDOUT and connection did not occur according to timings: apparently the connect attempt timed out (bad network?)" << llendl;
llassert(appconnect_time == 0);
llassert(pretransfer_time == 0);
llassert(starttransfer_time == 0);
// Fatal error for diagnostics.
return;
}
// If connect_time is almost equal to namelookup_time, then it was just set because it was already connected.
@@ -2142,16 +2235,30 @@ void stopCurlThread(void)
if (AICurlThread::sInstance)
{
AICurlThread::sInstance->stop_thread();
int count = 101;
int count = 401;
while(--count && !AICurlThread::sInstance->isStopped())
{
ms_sleep(10);
}
Dout(dc::curl, "Curl thread" << (curlThreadIsRunning() ? " not" : "") << " stopped after " << ((100 - count) * 10) << "ms.");
// Clear the command queue, for a cleaner cleanup.
if (AICurlThread::sInstance->isStopped())
{
// isStopped() returns true somewhere at the end of run(),
// but that doesn't mean the thread really stopped: it still
// needs to destroy it's static variables.
// If we don't join here, then there is a chance that the
// curl thread will crash when using globals that we (the
// main thread) will have destroyed before it REALLY finished.
AICurlThread::sInstance->join_thread(); // Wait till it is REALLY done.
}
llinfos << "Curl thread" << (curlThreadIsRunning() ? " not" : "") << " stopped after " << ((400 - count) * 10) << "ms." << llendl;
}
}
void clearCommandQueue(void)
{
// Clear the command queue now in order to avoid the global deinitialization order fiasco.
command_queue_wat command_queue_w(command_queue);
command_queue_w->clear();
}
}
//-----------------------------------------------------------------------------
@@ -2161,7 +2268,17 @@ void BufferedCurlEasyRequest::setStatusAndReason(U32 status, std::string const&
{
mStatus = status;
mReason = reason;
AICurlInterface::Stats::status_count[AICurlInterface::Stats::status2index(mStatus)]++;
if (status >= 100 && status < 600 && (status % 100) < 20)
{
// Only count statistic for sane values.
AICurlInterface::Stats::status_count[AICurlInterface::Stats::status2index(mStatus)]++;
}
// Sanity check. If the server replies with a redirect status then we better have that option turned on!
if ((status >= 300 && status < 400) && mResponder && !mResponder->redirect_status_ok())
{
llerrs << "Received " << status << " (" << reason << ") for responder \"" << mTimeoutPolicy->name() << "\" which has no followRedir()!" << llendl;
}
}
void BufferedCurlEasyRequest::processOutput(void)
@@ -2172,7 +2289,7 @@ void BufferedCurlEasyRequest::processOutput(void)
CURLcode code;
AITransferInfo info;
getResult(&code, &info);
if (code == CURLE_OK)
if (code == CURLE_OK && mStatus != HTTP_INTERNAL_ERROR)
{
getinfo(CURLINFO_RESPONSE_CODE, &responseCode);
// If getResult code is CURLE_OK then we should have decoded the first header line ourselves.
@@ -2185,7 +2302,7 @@ void BufferedCurlEasyRequest::processOutput(void)
else
{
responseCode = HTTP_INTERNAL_ERROR;
responseReason = curl_easy_strerror(code);
responseReason = (code == CURLE_OK) ? mReason : std::string(curl_easy_strerror(code));
setopt(CURLOPT_FRESH_CONNECT, TRUE);
}
@@ -2306,23 +2423,31 @@ size_t BufferedCurlEasyRequest::curlHeaderCallback(char* data, size_t size, size
std::string::iterator pos2 = std::find(pos1, end, ' ');
if (pos2 != end) ++pos2;
std::string::iterator pos3 = std::find(pos2, end, '\r');
U32 status;
U32 status = 0;
std::string reason;
if (pos3 != end && std::isdigit(*pos1))
{
status = atoi(&header_line[pos1 - begin]);
reason.assign(pos2, pos3);
}
else
if (!(status >= 100 && status < 600 && (status % 100) < 20)) // Sanity check on the decoded status.
{
if (status == 0)
{
reason = "Header parse error.";
llwarns << "Received broken header line from server: \"" << header << "\"" << llendl;
}
else
{
reason = "Unexpected HTTP status.";
llwarns << "Received unexpected status value from server (" << status << "): \"" << header << "\"" << llendl;
}
// Either way, this status value is not understood (or taken into account).
// Set it to internal error so that the rest of code treats it as an error.
status = HTTP_INTERNAL_ERROR;
reason = "Header parse error.";
llwarns << "Received broken header line from server: \"" << header << "\"" << llendl;
}
{
self_w->received_HTTP_header();
self_w->setStatusAndReason(status, reason);
}
self_w->received_HTTP_header();
self_w->setStatusAndReason(status, reason);
return header_len;
}
@@ -2351,14 +2476,25 @@ size_t BufferedCurlEasyRequest::curlHeaderCallback(char* data, size_t size, size
}
#if defined(CWDEBUG) || defined(DEBUG_CURLIO)
int debug_callback(CURL*, curl_infotype infotype, char* buf, size_t size, void* user_ptr)
int debug_callback(CURL* handle, curl_infotype infotype, char* buf, size_t size, void* user_ptr)
{
BufferedCurlEasyRequest* request = (BufferedCurlEasyRequest*)user_ptr;
if (infotype == CURLINFO_HEADER_OUT && size >= 5 && (strncmp(buf, "GET ", 4) == 0 || strncmp(buf, "HEAD ", 5) == 0))
{
request->mDebugIsHeadOrGetMethod = true;
}
#ifdef DEBUG_CURLIO
if (!debug_curl_print_debug(handle))
{
return 0;
}
#endif
#ifdef CWDEBUG
using namespace ::libcwd;
BufferedCurlEasyRequest* request = (BufferedCurlEasyRequest*)user_ptr;
std::ostringstream marker;
marker << (void*)request->get_lockobj();
marker << (void*)request->get_lockobj() << ' ';
libcw_do.push_marker();
libcw_do.marker().assign(marker.str().data(), marker.str().size());
if (!debug::channels::dc::curlio.is_on())
@@ -2382,8 +2518,6 @@ int debug_callback(CURL*, curl_infotype infotype, char* buf, size_t size, void*
break;
case CURLINFO_HEADER_OUT:
LibcwDoutStream << "H< ";
if (size >= 5 && (strncmp(buf, "GET ", 4) == 0 || strncmp(buf, "HEAD ", 5) == 0))
request->mDebugIsHeadOrGetMethod = true;
break;
case CURLINFO_DATA_IN:
LibcwDoutStream << "D> ";
@@ -2557,6 +2691,14 @@ void AICurlEasyRequest::removeRequest(void)
}
}
}
{
AICurlEasyRequest_wat curl_easy_request_w(*get());
// As soon as the lock on the command queue is released, it could be picked up by
// the curl thread and executed. At that point it (already) demands that the easy
// request either timed out or is finished. So, to avoid race conditions that already
// has to be true right now. The call to queued_for_removal() checks this.
curl_easy_request_w->queued_for_removal(curl_easy_request_w);
}
#endif
// Add a command to remove this request from the multi session to the command queue.
command_queue_w->push_back(Command(*this, cmd_remove));

View File

@@ -107,6 +107,20 @@ void AIHTTPReceivedHeaders::addHeader(std::string const& key, std::string const&
{
mContainer = new Container;
}
else if (equal(key, "set-cookie"))
{
// If a cookie with this name already exists, replace it.
std::string const name = value.substr(0, value.find('='));
container_t::iterator const end = mContainer->mKeyValuePairs.end();
for (container_t::iterator header = mContainer->mKeyValuePairs.begin(); header != end; ++header)
{
if (equal(header->first, "set-cookie") && header->second.substr(0, header->second.find('=')) == name)
{
header->second = value;
return;
}
}
}
mContainer->mKeyValuePairs.insert(container_t::value_type(key, value));
}
@@ -151,3 +165,20 @@ std::ostream& operator<<(std::ostream& os, AIHTTPReceivedHeaders const& headers)
return os;
}
//static
bool AIHTTPReceivedHeaders::equal(std::string const& key1, std::string const& key2)
{
if (key1.length() != key2.length())
{
return false;
}
for (std::string::const_iterator i1 = key1.begin(), i2 = key2.begin(); i1 != key1.end(); ++i1, ++i2)
{
if ((*i1 ^ *i2) & 0xdf != 0)
{
return false;
}
}
return true;
}

View File

@@ -132,6 +132,9 @@ class AIHTTPReceivedHeaders {
// Add a header.
void addHeader(std::string const& key, std::string const& value);
// Swap headers with another container.
void swap(AIHTTPReceivedHeaders& headers) { LLPointer<Container>::swap(mContainer, headers.mContainer); }
// Return true if there are no headers associated with this object.
bool empty(void) const { return !mContainer || mContainer->mKeyValuePairs.empty(); }
@@ -147,6 +150,9 @@ class AIHTTPReceivedHeaders {
// For debug purposes.
friend std::ostream& operator<<(std::ostream& os, AIHTTPReceivedHeaders const& headers);
// Returns true if the two keys compare equal (ie, "Set-Cookie" == "set-cookie").
static bool equal(std::string const& key1, std::string const& key2);
private:
struct Container : public LLThreadSafeRefCount {
container_t mKeyValuePairs;

View File

@@ -646,6 +646,12 @@ AIHTTPTimeoutPolicyBase transfer_18s(AIHTTPTimeoutPolicyBase::getDebugSettingsCu
transactionOp18s
);
// This used to be '30 seconds'.
Transaction transactionOp30s(30);
AIHTTPTimeoutPolicyBase transfer_30s(AIHTTPTimeoutPolicyBase::getDebugSettingsCurlTimeout(),
transactionOp30s
);
// This used to be '300 seconds'. We derive this from the hardcoded result so users can't mess with it.
Transaction transactionOp300s(300);
AIHTTPTimeoutPolicyBase transfer_300s(HTTPTimeoutPolicy_default,
@@ -820,6 +826,7 @@ P(accountingCostResponder);
P(agentStateResponder);
P(assetUploadResponder);
P(asyncConsoleResponder);
P(avatarPickerResponder);
P(authHandler);
P(avatarNameResponder);
P2(baseCapabilitiesComplete, transfer_18s);
@@ -838,6 +845,7 @@ P(estateChangeInfoResponder);
P(eventPollResponder);
P(fetchInventoryResponder);
P(fnPtrResponder);
P2(groupMemberDataResponder, transfer_300s);
P2(groupProposalBallotResponder, transfer_300s);
P(homeLocationResponder);
P(HTTPGetResponder);
@@ -850,6 +858,7 @@ P(lcl_responder);
P(MPImportGetResponder);
P(MPImportPostResponder);
P(mapLayerResponder);
P2(maturityPreferences, transfer_30s);
P(mediaTypeResponder);
P(meshDecompositionResponder);
P(meshHeaderResponder);
@@ -889,6 +898,7 @@ P(viewerStatsResponder);
P(viewerVoiceAccountProvisionResponder);
P(voiceCallCapResponder);
P(voiceClientCapResponder);
P(webProfileResponders);
P(wholeModelFeeResponder);
P(wholeModelUploadResponder);
P2(XMLRPCResponder, connect_40s);

View File

@@ -6,6 +6,7 @@
#include <cstdlib>
#include <stdarg.h>
#include <cstring>
#include <algorithm>
#include "llpreprocessor.h"
#include <curl/curl.h>
#define COMPILING_DEBUG_LIBCURL_CC
@@ -528,19 +529,66 @@ std::ostream& operator<<(std::ostream& os, EvBitmask const& bitmask)
return os;
}
// Set this to limit the curl debug output to specific easy handles.
bool gDebugCurlTerse = false;
namespace {
std::vector<CURL*> handles;
inline bool print_debug(CURL* handle)
{
if (!gDebugCurlTerse)
return true;
return std::find(handles.begin(), handles.end(), handle) != handles.end();
}
} // namespace
void debug_curl_add_easy(CURL* handle)
{
std::vector<CURL*>::iterator iter = std::find(handles.begin(), handles.end(), handle);
if (iter == handles.end())
{
handles.push_back(handle);
Dout(dc::warning, "debug_curl_add_easy(" << (void*)handle << "): added");
}
llassert(print_debug(handle));
}
void debug_curl_remove_easy(CURL* handle)
{
std::vector<CURL*>::iterator iter = std::find(handles.begin(), handles.end(), handle);
if (iter != handles.end())
{
handles.erase(iter);
Dout(dc::warning, "debug_curl_remove_easy(" << (void*)handle << "): removed");
}
llassert(!print_debug(handle));
}
bool debug_curl_print_debug(CURL* handle)
{
return print_debug(handle);
}
extern "C" {
void debug_curl_easy_cleanup(CURL* handle)
{
curl_easy_cleanup(handle);
Dout(dc::curl, "curl_easy_cleanup(" << (AICURL*)handle << ")");
if (print_debug(handle))
{
Dout(dc::curltr, "curl_easy_cleanup(" << (AICURL*)handle << ")");
}
}
CURL* debug_curl_easy_duphandle(CURL* handle)
{
CURL* ret;
ret = curl_easy_duphandle(handle);
Dout(dc::curl, "curl_easy_duphandle(" << (AICURL*)handle << ") = " << (AICURL*)ret);
if (!print_debug(handle)) return ret;
Dout(dc::curltr, "curl_easy_duphandle(" << (AICURL*)handle << ") = " << (AICURL*)ret);
return ret;
}
@@ -548,11 +596,12 @@ char* debug_curl_easy_escape(CURL* curl, char* url, int length)
{
char* ret;
ret = curl_easy_escape(curl, url, length);
Dout(dc::curl, "curl_easy_escape(" << (AICURL*)curl << ", \"" << url << "\", " << length << ") = \"" << ret << '"');
if (!print_debug(curl)) return ret;
Dout(dc::curltr, "curl_easy_escape(" << (AICURL*)curl << ", \"" << url << "\", " << length << ") = \"" << ret << '"');
return ret;
}
CURLcode debug_curl_easy_getinfo(CURL* curl, CURLINFO info, ...)
CURLcode debug_curl_easy_getinfo(CURL* handle, CURLINFO info, ...)
{
CURLcode ret;
va_list ap;
@@ -566,26 +615,27 @@ CURLcode debug_curl_easy_getinfo(CURL* curl, CURLINFO info, ...)
va_start(ap, info);
param.some_ptr = va_arg(ap, void*);
va_end(ap);
ret = curl_easy_getinfo(curl, info, param.some_ptr);
ret = curl_easy_getinfo(handle, info, param.some_ptr);
if (!print_debug(handle)) return ret;
if (info == CURLINFO_PRIVATE)
{
Dout(dc::curl, "curl_easy_getinfo(" << (AICURL*)curl << ", " << info << ", 0x" << std::hex << (size_t)param.some_ptr << std::dec << ") = " << ret);
Dout(dc::curltr, "curl_easy_getinfo(" << (AICURL*)handle << ", " << info << ", 0x" << std::hex << (size_t)param.some_ptr << std::dec << ") = " << ret);
}
else
{
switch((info & CURLINFO_TYPEMASK))
{
case CURLINFO_STRING:
Dout(dc::curl, "curl_easy_getinfo(" << (AICURL*)curl << ", " << info << ", (char**){ \"" << (ret == CURLE_OK ? *param.char_ptr : " <unchanged> ") << "\" }) = " << ret);
Dout(dc::curltr, "curl_easy_getinfo(" << (AICURL*)handle << ", " << info << ", (char**){ \"" << (ret == CURLE_OK ? *param.char_ptr : " <unchanged> ") << "\" }) = " << ret);
break;
case CURLINFO_LONG:
Dout(dc::curl, "curl_easy_getinfo(" << (AICURL*)curl << ", " << info << ", (long*){ " << (ret == CURLE_OK ? *param.long_ptr : 0L) << "L }) = " << ret);
Dout(dc::curltr, "curl_easy_getinfo(" << (AICURL*)handle << ", " << info << ", (long*){ " << (ret == CURLE_OK ? *param.long_ptr : 0L) << "L }) = " << ret);
break;
case CURLINFO_DOUBLE:
Dout(dc::curl, "curl_easy_getinfo(" << (AICURL*)curl << ", " << info << ", (double*){" << (ret == CURLE_OK ? *param.double_ptr : 0.) << "}) = " << ret);
Dout(dc::curltr, "curl_easy_getinfo(" << (AICURL*)handle << ", " << info << ", (double*){" << (ret == CURLE_OK ? *param.double_ptr : 0.) << "}) = " << ret);
break;
case CURLINFO_SLIST:
Dout(dc::curl, "curl_easy_getinfo(" << (AICURL*)curl << ", " << info << ", (curl_slist**){ " << (ret == CURLE_OK ? **param.curl_slist_ptr : unchanged_slist) << " }) = " << ret);
Dout(dc::curltr, "curl_easy_getinfo(" << (AICURL*)handle << ", " << info << ", (curl_slist**){ " << (ret == CURLE_OK ? **param.curl_slist_ptr : unchanged_slist) << " }) = " << ret);
break;
}
}
@@ -596,7 +646,8 @@ CURL* debug_curl_easy_init(void)
{
CURL* ret;
ret = curl_easy_init();
Dout(dc::curl, "curl_easy_init() = " << (AICURL*)ret);
if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_easy_init() = " << (AICURL*)ret);
return ret;
}
@@ -604,7 +655,8 @@ CURLcode debug_curl_easy_pause(CURL* handle, int bitmask)
{
CURLcode ret;
ret = curl_easy_pause(handle, bitmask);
Dout(dc::curl, "curl_easy_pause(" << (AICURL*)handle << ", 0x" << std::hex << bitmask << std::dec << ") = " << ret);
if (!print_debug(handle)) return ret;
Dout(dc::curltr, "curl_easy_pause(" << (AICURL*)handle << ", 0x" << std::hex << bitmask << std::dec << ") = " << ret);
return ret;
}
@@ -612,19 +664,21 @@ CURLcode debug_curl_easy_perform(CURL* handle)
{
CURLcode ret;
ret = curl_easy_perform(handle);
Dout(dc::curl, "curl_easy_perform(" << (AICURL*)handle << ") = " << ret);
if (!print_debug(handle)) return ret;
Dout(dc::curltr, "curl_easy_perform(" << (AICURL*)handle << ") = " << ret);
return ret;
}
void debug_curl_easy_reset(CURL* handle)
{
curl_easy_reset(handle);
Dout(dc::curl, "curl_easy_reset(" << (AICURL*)handle << ")");
if (!print_debug(handle)) return;
Dout(dc::curltr, "curl_easy_reset(" << (AICURL*)handle << ")");
}
CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...)
{
CURLcode ret;
CURLcode ret = CURLE_OBSOLETE50; // Suppress compiler warning.
va_list ap;
union param_type {
long along;
@@ -656,7 +710,10 @@ CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...)
case CURLOPTTYPE_LONG:
{
ret = curl_easy_setopt(handle, option, param.along);
Dout(dc::curl, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", " << param.along << "L) = " << ret);
if (print_debug(handle))
{
Dout(dc::curltr, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", " << param.along << "L) = " << ret);
}
if (option == CURLOPT_POSTFIELDSIZE)
{
postfieldsize = param.along;
@@ -666,7 +723,8 @@ CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...)
case CURLOPTTYPE_OBJECTPOINT:
{
ret = curl_easy_setopt(handle, option, param.ptr);
LibcwDoutScopeBegin(LIBCWD_DEBUGCHANNELS, libcwd::libcw_do, dc::curl)
if (!print_debug(handle)) break;
LibcwDoutScopeBegin(LIBCWD_DEBUGCHANNELS, libcwd::libcw_do, dc::curltr)
LibcwDoutStream << "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", ";
// For a subset of all options that take a char*, print the string passed.
if (option == CURLOPT_PROXY || // Set HTTP proxy to use. The parameter should be a char* to a zero terminated string holding the host name or dotted IP address.
@@ -717,11 +775,11 @@ CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...)
if (option == CURLOPT_HTTPHEADER && param.ptr)
{
debug::Indent indent(2);
Dout(dc::curl, "HTTP Headers:");
Dout(dc::curltr, "HTTP Headers:");
struct curl_slist* list = (struct curl_slist*)param.ptr;
while (list)
{
Dout(dc::curl, '"' << list->data << '"');
Dout(dc::curltr, '"' << list->data << '"');
list = list->next;
}
}
@@ -729,12 +787,18 @@ CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...)
}
case CURLOPTTYPE_FUNCTIONPOINT:
ret = curl_easy_setopt(handle, option, param.ptr);
Dout(dc::curl, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", (function*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret);
if (print_debug(handle))
{
Dout(dc::curltr, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", (function*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret);
}
break;
case CURLOPTTYPE_OFF_T:
{
ret = curl_easy_setopt(handle, option, param.offset);
Dout(dc::curl, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", (curl_off_t)" << param.offset << ") = " << ret);
if (print_debug(handle))
{
Dout(dc::curltr, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", (curl_off_t)" << param.offset << ") = " << ret);
}
if (option == CURLOPT_POSTFIELDSIZE_LARGE)
{
postfieldsize = (long)param.offset;
@@ -751,7 +815,8 @@ char const* debug_curl_easy_strerror(CURLcode errornum)
{
char const* ret;
ret = curl_easy_strerror(errornum);
Dout(dc::curl, "curl_easy_strerror(" << errornum << ") = \"" << ret << '"');
if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_easy_strerror(" << errornum << ") = \"" << ret << '"');
return ret;
}
@@ -759,35 +824,38 @@ char* debug_curl_easy_unescape(CURL* curl, char* url, int inlength, int* outleng
{
char* ret;
ret = curl_easy_unescape(curl, url, inlength, outlength);
Dout(dc::curl, "curl_easy_unescape(" << (AICURL*)curl << ", \"" << url << "\", " << inlength << ", " << ((ret && outlength) ? *outlength : 1) << ") = \"" << ret << '"');
if (!print_debug(curl)) return ret;
Dout(dc::curltr, "curl_easy_unescape(" << (AICURL*)curl << ", \"" << url << "\", " << inlength << ", " << ((ret && outlength) ? *outlength : 1) << ") = \"" << ret << '"');
return ret;
}
void debug_curl_free(char* ptr)
{
curl_free(ptr);
Dout(dc::curl, "curl_free(0x" << std::hex << (size_t)ptr << std::dec << ")");
if (gDebugCurlTerse) return;
Dout(dc::curltr, "curl_free(0x" << std::hex << (size_t)ptr << std::dec << ")");
}
time_t debug_curl_getdate(char const* datestring, time_t* now)
{
time_t ret;
ret = curl_getdate(datestring, now);
Dout(dc::curl, "curl_getdate(\"" << datestring << "\", " << (now == NULL ? "NULL" : "<erroneous non-NULL value for 'now'>") << ") = " << ret);
if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_getdate(\"" << datestring << "\", " << (now == NULL ? "NULL" : "<erroneous non-NULL value for 'now'>") << ") = " << ret);
return ret;
}
void debug_curl_global_cleanup(void)
{
curl_global_cleanup();
Dout(dc::curl, "curl_global_cleanup()");
Dout(dc::curltr, "curl_global_cleanup()");
}
CURLcode debug_curl_global_init(long flags)
{
CURLcode ret;
ret = curl_global_init(flags);
Dout(dc::curl, "curl_global_init(0x" << std::hex << flags << std::dec << ") = " << ret);
Dout(dc::curltr, "curl_global_init(0x" << std::hex << flags << std::dec << ") = " << ret);
return ret;
}
@@ -795,7 +863,8 @@ CURLMcode debug_curl_multi_add_handle(CURLM* multi_handle, CURL* easy_handle)
{
CURLMcode ret;
ret = curl_multi_add_handle(multi_handle, easy_handle);
Dout(dc::curl, "curl_multi_add_handle(" << (AICURLM*)multi_handle << ", " << (AICURL*)easy_handle << ") = " << ret);
if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_multi_add_handle(" << (AICURLM*)multi_handle << ", " << (AICURL*)easy_handle << ") = " << ret);
return ret;
}
@@ -803,7 +872,8 @@ CURLMcode debug_curl_multi_assign(CURLM* multi_handle, curl_socket_t sockfd, voi
{
CURLMcode ret;
ret = curl_multi_assign(multi_handle, sockfd, sockptr);
Dout(dc::curl, "curl_multi_assign(" << (AICURLM*)multi_handle << ", " << Socket(sockfd) << ", " << sockptr << ") = " << ret);
if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_multi_assign(" << (AICURLM*)multi_handle << ", " << Socket(sockfd) << ", " << sockptr << ") = " << ret);
return ret;
}
@@ -811,7 +881,8 @@ CURLMcode debug_curl_multi_cleanup(CURLM* multi_handle)
{
CURLMcode ret;
ret = curl_multi_cleanup(multi_handle);
Dout(dc::curl, "curl_multi_cleanup(" << (AICURLM*)multi_handle << ") = " << ret);
if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_multi_cleanup(" << (AICURLM*)multi_handle << ") = " << ret);
return ret;
}
@@ -819,7 +890,8 @@ CURLMsg* debug_curl_multi_info_read(CURLM* multi_handle, int* msgs_in_queue)
{
CURLMsg* ret;
ret = curl_multi_info_read(multi_handle, msgs_in_queue);
Dout(dc::curl, "curl_multi_info_read(" << (AICURLM*)multi_handle << ", {" << *msgs_in_queue << "}) = " << ret);
if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_multi_info_read(" << (AICURLM*)multi_handle << ", {" << *msgs_in_queue << "}) = " << ret);
return ret;
}
@@ -827,7 +899,8 @@ CURLM* debug_curl_multi_init(void)
{
CURLM* ret;
ret = curl_multi_init();
Dout(dc::curl, "curl_multi_init() = " << (AICURLM*)ret);
if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_multi_init() = " << (AICURLM*)ret);
return ret;
}
@@ -835,13 +908,14 @@ CURLMcode debug_curl_multi_remove_handle(CURLM* multi_handle, CURL* easy_handle)
{
CURLMcode ret;
ret = curl_multi_remove_handle(multi_handle, easy_handle);
Dout(dc::curl, "curl_multi_remove_handle(" << (AICURLM*)multi_handle << ", " << (AICURL*)easy_handle << ") = " << ret);
if (!print_debug(easy_handle)) return ret;
Dout(dc::curltr, "curl_multi_remove_handle(" << (AICURLM*)multi_handle << ", " << (AICURL*)easy_handle << ") = " << ret);
return ret;
}
CURLMcode debug_curl_multi_setopt(CURLM* multi_handle, CURLMoption option, ...)
{
CURLMcode ret;
CURLMcode ret = CURLM_UNKNOWN_OPTION; // Suppress compiler warning.
va_list ap;
union param_type {
long along;
@@ -871,19 +945,23 @@ CURLMcode debug_curl_multi_setopt(CURLM* multi_handle, CURLMoption option, ...)
{
case CURLOPTTYPE_LONG:
ret = curl_multi_setopt(multi_handle, option, param.along);
Dout(dc::curl, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", " << param.along << "L) = " << ret);
if (gDebugCurlTerse) break;
Dout(dc::curltr, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", " << param.along << "L) = " << ret);
break;
case CURLOPTTYPE_OBJECTPOINT:
ret = curl_multi_setopt(multi_handle, option, param.ptr);
Dout(dc::curl, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (object*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret);
if (gDebugCurlTerse) break;
Dout(dc::curltr, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (object*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret);
break;
case CURLOPTTYPE_FUNCTIONPOINT:
ret = curl_multi_setopt(multi_handle, option, param.ptr);
Dout(dc::curl, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (function*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret);
if (gDebugCurlTerse) break;
Dout(dc::curltr, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (function*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret);
break;
case CURLOPTTYPE_OFF_T:
ret = curl_multi_setopt(multi_handle, option, param.offset);
Dout(dc::curl, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (curl_off_t)" << param.offset << ") = " << ret);
if (gDebugCurlTerse) break;
Dout(dc::curltr, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (curl_off_t)" << param.offset << ") = " << ret);
break;
default: // Stop compiler complaining about no default.
break;
@@ -895,7 +973,8 @@ CURLMcode debug_curl_multi_socket_action(CURLM* multi_handle, curl_socket_t sock
{
CURLMcode ret;
ret = curl_multi_socket_action(multi_handle, sockfd, ev_bitmask, running_handles);
Dout(dc::curl, "curl_multi_socket_action(" << (AICURLM*)multi_handle << ", " << Socket(sockfd) <<
if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_multi_socket_action(" << (AICURLM*)multi_handle << ", " << Socket(sockfd) <<
", " << EvBitmask(ev_bitmask) << ", {" << (ret == CURLM_OK ? *running_handles : 0) << "}) = " << ret);
return ret;
}
@@ -904,7 +983,8 @@ char const* debug_curl_multi_strerror(CURLMcode errornum)
{
char const* ret;
ret = curl_multi_strerror(errornum);
Dout(dc::curl, "curl_multi_strerror(" << errornum << ") = \"" << ret << '"');
if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_multi_strerror(" << errornum << ") = \"" << ret << '"');
return ret;
}
@@ -912,21 +992,24 @@ struct curl_slist* debug_curl_slist_append(struct curl_slist* list, char const*
{
struct curl_slist* ret;
ret = curl_slist_append(list, string);
Dout(dc::curl, "curl_slist_append((curl_slist)@0x" << std::hex << (size_t)list << std::dec << ", \"" << string << "\") = " << *ret);
if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_slist_append((curl_slist)@0x" << std::hex << (size_t)list << std::dec << ", \"" << string << "\") = " << *ret);
return ret;
}
void debug_curl_slist_free_all(struct curl_slist* list)
{
curl_slist_free_all(list);
Dout(dc::curl, "curl_slist_free_all((curl_slist)@0x" << std::hex << (size_t)list << std::dec << ")");
if (gDebugCurlTerse) return;
Dout(dc::curltr, "curl_slist_free_all((curl_slist)@0x" << std::hex << (size_t)list << std::dec << ")");
}
char* debug_curl_unescape(char const* url, int length)
{
char* ret;
ret = curl_unescape(url, length);
Dout(dc::curl, "curl_unescape(\"" << url << "\", " << length << ") = \"" << ret << '"');
if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_unescape(\"" << url << "\", " << length << ") = \"" << ret << '"');
return ret;
}
@@ -934,7 +1017,8 @@ char* debug_curl_version(void)
{
char* ret;
ret = curl_version();
Dout(dc::curl, "curl_version() = \"" << ret << '"');
if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_version() = \"" << ret << '"');
return ret;
}

View File

@@ -86,4 +86,9 @@ extern char* debug_curl_version(void);
#endif // !COMPILING_DEBUG_LIBCURL_CC
extern bool gDebugCurlTerse; // With this set,
void debug_curl_add_easy(CURL* handle); // only output debug output for easy handles added with this function.
void debug_curl_remove_easy(CURL* handle);
bool debug_curl_print_debug(CURL* handle);
#endif // DEBUG_LIBCURL

View File

@@ -24,12 +24,12 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llavatarnamecache.h"
#include "llcachename.h" // we wrap this system
#include "llcontrol.h" // For LLCachedControl
#include "llframetimer.h"
#include "llhttpclient.h"
#include "llsd.h"
@@ -93,6 +93,9 @@ namespace LLAvatarNameCache
/// Time when unrefreshed cached names were checked last
static F64 sLastExpireCheck;
/// Time-to-live for a temp cache entry.
const F64 TEMP_CACHE_ENTRY_LIFETIME = 60.0;
//-----------------------------------------------------------------------
// Internal methods
//-----------------------------------------------------------------------
@@ -291,13 +294,14 @@ void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id)
// Clear this agent from the pending list
LLAvatarNameCache::sPendingQueue.erase(agent_id);
const LLAvatarName& av_name = existing->second;
LLAvatarName& av_name = existing->second;
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache use cache for agent "
<< agent_id
<< "user '" << av_name.mUsername << "' "
<< "display '" << av_name.mDisplayName << "' "
<< "expires in " << av_name.mExpires - LLFrameTimer::getTotalSeconds() << " seconds"
<< LL_ENDL;
av_name.mExpires = LLFrameTimer::getTotalSeconds() + TEMP_CACHE_ENTRY_LIFETIME; // reset expiry time so we don't constantly rerequest.
}
}
@@ -342,19 +346,23 @@ void LLAvatarNameCache::requestNamesViaCapability()
// http://pdp60.lindenlab.com:8000/agents/?ids=3941037e-78ab-45f0-b421-bd6e77c1804d&ids=0012809d-7d2d-4c24-9609-af1230a37715&ids=0019aaba-24af-4f0a-aa72-6457953cf7f0
//
// Apache can handle URLs of 4096 chars, but let's be conservative
const U32 NAME_URL_MAX = 4096;
const U32 NAME_URL_SEND_THRESHOLD = 3000;
static const U32 NAME_URL_MAX = 4096;
static const U32 NAME_URL_SEND_THRESHOLD = 3500;
std::string url;
url.reserve(NAME_URL_MAX);
std::vector<LLUUID> agent_ids;
agent_ids.reserve(128);
U32 id_total = sAskQueue.size();
U32 ids = 0;
ask_queue_t::const_iterator it = sAskQueue.begin();
for ( ; it != sAskQueue.end(); ++it)
ask_queue_t::const_iterator it;
while(!sAskQueue.empty())
{
it = sAskQueue.begin();
const LLUUID& agent_id = *it;
sAskQueue.erase(it);
if (url.empty())
{
@@ -377,27 +385,17 @@ void LLAvatarNameCache::requestNamesViaCapability()
if (url.size() > NAME_URL_SEND_THRESHOLD)
{
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::requestNamesViaCapability first "
<< ids << " ids"
<< LL_ENDL;
LLHTTPClient::get(url, new LLAvatarNameResponder(agent_ids));
url.clear();
agent_ids.clear();
break;
}
}
if (!url.empty())
{
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::requestNamesViaCapability all "
<< ids << " ids"
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::requestNamesViaCapability requested "
<< ids << "/" << id_total << "ids "
<< LL_ENDL;
LLHTTPClient::get(url, new LLAvatarNameResponder(agent_ids));
url.clear();
agent_ids.clear();
}
// We've moved all asks to the pending request queue
sAskQueue.clear();
}
void LLAvatarNameCache::legacyNameCallback(const LLUUID& agent_id,
@@ -414,20 +412,25 @@ void LLAvatarNameCache::legacyNameCallback(const LLUUID& agent_id,
<< LL_ENDL;
buildLegacyName(full_name, &av_name);
// Don't add to cache, the data already exists in the legacy name system
// cache and we don't want or need duplicate storage, because keeping the
// two copies in sync is complex.
processName(agent_id, av_name, false);
// Add to cache, because if we don't we'll keep rerequesting the
// same record forever. buildLegacyName should always guarantee
// that these records expire reasonably soon
// (in TEMP_CACHE_ENTRY_LIFETIME seconds), so if the failure was due
// to something temporary we will eventually request and get the right data.
processName(agent_id, av_name, true);
}
void LLAvatarNameCache::requestNamesViaLegacy()
{
static const S32 MAX_REQUESTS = 100;
F64 now = LLFrameTimer::getTotalSeconds();
std::string full_name;
ask_queue_t::const_iterator it = sAskQueue.begin();
for (; it != sAskQueue.end(); ++it)
ask_queue_t::const_iterator it;
for (S32 requests = 0; !sAskQueue.empty() && requests < MAX_REQUESTS; ++requests)
{
it = sAskQueue.begin();
const LLUUID& agent_id = *it;
sAskQueue.erase(it);
// Mark as pending first, just in case the callback is immediately
// invoked below. This should never happen in practice.
@@ -439,10 +442,6 @@ void LLAvatarNameCache::requestNamesViaLegacy()
boost::bind(&LLAvatarNameCache::legacyNameCallback,
_1, _2, _3));
}
// We've either answered immediately or moved all asks to the
// pending queue
sAskQueue.clear();
}
void LLAvatarNameCache::initClass(bool running)
@@ -519,11 +518,11 @@ void LLAvatarNameCache::idle()
// *TODO: Possibly re-enabled this based on People API load measurements
// 100 ms is the threshold for "user speed" operations, so we can
// stall for about that long to batch up requests.
//const F32 SECS_BETWEEN_REQUESTS = 0.1f;
//if (!sRequestTimer.checkExpirationAndReset(SECS_BETWEEN_REQUESTS))
//{
// return;
//}
const F32 SECS_BETWEEN_REQUESTS = 0.1f;
if (!sRequestTimer.hasExpired())
{
return;
}
if (!sAskQueue.empty())
{
@@ -538,6 +537,12 @@ void LLAvatarNameCache::idle()
}
}
if (sAskQueue.empty())
{
// cleared the list, reset the request timer.
sRequestTimer.reset(SECS_BETWEEN_REQUESTS);
}
// erase anything that has not been refreshed for more than MAX_UNREFRESHED_TIME
eraseUnrefreshed();
}
@@ -595,7 +600,7 @@ void LLAvatarNameCache::buildLegacyName(const std::string& full_name,
av_name->mDisplayName = full_name;
av_name->mIsDisplayNameDefault = true;
av_name->mIsTemporaryName = true;
av_name->mExpires = F64_MAX; // not used because these are not cached
av_name->mExpires = LLFrameTimer::getTotalSeconds() + TEMP_CACHE_ENTRY_LIFETIME;
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::buildLegacyName "
<< full_name
<< LL_ENDL;
@@ -619,7 +624,6 @@ bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name)
// ...only do immediate lookups when cache is running
if (useDisplayNames())
{
// ...use display names cache
std::map<LLUUID,LLAvatarName>::iterator it = sCache.find(agent_id);
if (it != sCache.end())
@@ -664,6 +668,29 @@ bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name)
return false;
}
// Return true when name has been set to Phoenix Name System Name, if not return false.
bool LLAvatarNameCache::getPNSName(const LLUUID& agent_id, std::string& name)
{
LLAvatarName avatar_name;
if (get(agent_id, &avatar_name))
getPNSName(avatar_name, name);
else return false;
return true;
}
// get() with callback compatible version of getPNSName
void LLAvatarNameCache::getPNSName(const LLAvatarName& avatar_name, std::string& name)
{
static LLCachedControl<S32> phoenix_name_system("PhoenixNameSystem", 0);
switch (phoenix_name_system)
{
case 0 : name = avatar_name.getLegacyName(); break;
case 1 : name = avatar_name.getCompleteName(); break;
case 2 : name = avatar_name.mDisplayName; break;
default : name = avatar_name.getLegacyName(); break;
}
}
void LLAvatarNameCache::fireSignal(const LLUUID& agent_id,
const callback_slot_t& slot,
const LLAvatarName& av_name)
@@ -673,8 +700,10 @@ void LLAvatarNameCache::fireSignal(const LLUUID& agent_id,
signal(agent_id, av_name);
}
void LLAvatarNameCache::get(const LLUUID& agent_id, callback_slot_t slot)
LLAvatarNameCache::callback_connection_t LLAvatarNameCache::get(const LLUUID& agent_id, callback_slot_t slot)
{
callback_connection_t connection;
if (sRunning)
{
// ...only do immediate lookups when cache is running
@@ -690,7 +719,7 @@ void LLAvatarNameCache::get(const LLUUID& agent_id, callback_slot_t slot)
{
// ...name already exists in cache, fire callback now
fireSignal(agent_id, slot, av_name);
return;
return connection;
}
}
}
@@ -703,7 +732,7 @@ void LLAvatarNameCache::get(const LLUUID& agent_id, callback_slot_t slot)
LLAvatarName av_name;
buildLegacyName(full_name, &av_name);
fireSignal(agent_id, slot, av_name);
return;
return connection;
}
}
}
@@ -720,15 +749,17 @@ void LLAvatarNameCache::get(const LLUUID& agent_id, callback_slot_t slot)
{
// ...new callback for this id
callback_signal_t* signal = new callback_signal_t();
signal->connect(slot);
connection = signal->connect(slot);
sSignalMap[agent_id] = signal;
}
else
{
// ...existing callback, bind additional slot
callback_signal_t* signal = sig_it->second;
signal->connect(slot);
connection = signal->connect(slot);
}
return connection;
}
// [RLVa:KB] - Checked: 2010-12-08 (RLVa-1.4.0a) | Added: RLVa-1.2.2c
@@ -774,12 +805,6 @@ void LLAvatarNameCache::erase(const LLUUID& agent_id)
sCache.erase(agent_id);
}
void LLAvatarNameCache::fetch(const LLUUID& agent_id)
{
// re-request, even if request is already pending
sAskQueue.insert(agent_id);
}
void LLAvatarNameCache::insert(const LLUUID& agent_id, const LLAvatarName& av_name)
{
// *TODO: update timestamp if zero?
@@ -788,26 +813,35 @@ void LLAvatarNameCache::insert(const LLUUID& agent_id, const LLAvatarName& av_na
F64 LLAvatarNameCache::nameExpirationFromHeaders(AIHTTPReceivedHeaders const& headers)
{
F64 expires;
expirationFromCacheControl(headers, &expires);
return expires;
F64 expires = 0.0;
if (expirationFromCacheControl(headers, &expires))
{
return expires;
}
else
{
// With no expiration info, default to an hour
const F64 DEFAULT_EXPIRES = 60.0 * 60.0;
F64 now = LLFrameTimer::getTotalSeconds();
return now + DEFAULT_EXPIRES;
}
}
bool LLAvatarNameCache::expirationFromCacheControl(AIHTTPReceivedHeaders const& headers, F64* expires)
{
bool fromCacheControl = false;
S32 max_age = 3600; // With no expiration info, default to an hour.
F64 now = LLFrameTimer::getTotalSeconds();
// Allow the header to override the default
std::string cache_control;
if (headers.getFirstValue("cache-control", cache_control))
{
S32 max_age = 0;
if (max_age_from_cache_control(cache_control, &max_age))
{
*expires = now + (F64)max_age;
fromCacheControl = true;
}
}
*expires = now + (F64)max_age;
LL_DEBUGS("AvNameCache")
<< ( fromCacheControl ? "expires based on cache control " : "default expiration " )
<< "in " << *expires - now << " seconds"

View File

@@ -65,16 +65,23 @@ namespace LLAvatarNameCache
// If name is in cache, returns true and fills in provided LLAvatarName
// otherwise returns false
bool get(const LLUUID& agent_id, LLAvatarName *av_name);
// If get() succeeds, returns true and fills in name string
// via void function below, otherwise returns false
bool getPNSName(const LLUUID& agent_id, std::string& name);
// Perform a filling of name string according to Phoenix Name System,
// when we have an LLAvatarName already.
void getPNSName(const LLAvatarName& avatar_name, std::string& name);
// Callback types for get() below
typedef boost::signals2::signal<
void (const LLUUID& agent_id, const LLAvatarName& av_name)>
callback_signal_t;
typedef callback_signal_t::slot_type callback_slot_t;
typedef boost::signals2::connection callback_connection_t;
// Fetches name information and calls callback.
// If name information is in cache, callback will be called immediately.
void get(const LLUUID& agent_id, callback_slot_t slot);
callback_connection_t get(const LLUUID& agent_id, callback_slot_t slot);
// Allow display names to be explicitly disabled for testing.
void setUseDisplayNames(bool use);
@@ -90,10 +97,6 @@ namespace LLAvatarNameCache
/// Provide some fallback for agents that return errors
void handleAgentError(const LLUUID& agent_id);
// Force a re-fetch of the most recent data, but keep the current
// data in cache
void fetch(const LLUUID& agent_id);
void insert(const LLUUID& agent_id, const LLAvatarName& av_name);
// Compute name expiration time from HTTP Cache-Control header,

View File

@@ -200,7 +200,9 @@ static void request(
LLURLRequest::ERequestAction method,
Injector* body_injector,
LLHTTPClient::ResponderPtr responder,
AIHTTPHeaders& headers,
AIHTTPHeaders& headers/*,*/
DEBUG_CURLIO_PARAM(EDebugCurl debug),
EKeepAlive keepalive = keep_alive,
bool is_auth = false,
bool no_compression = false)
{
@@ -213,7 +215,10 @@ static void request(
LLURLRequest* req;
try
{
req = new LLURLRequest(method, url, body_injector, responder, headers, is_auth, no_compression);
req = new LLURLRequest(method, url, body_injector, responder, headers, keepalive, is_auth, no_compression);
#ifdef DEBUG_CURLIO
req->mCurlEasyRequest.debug(debug);
#endif
}
catch(AICurlNoEasyHandle& error)
{
@@ -225,36 +230,36 @@ static void request(
req->run();
}
void LLHTTPClient::getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder, AIHTTPHeaders& headers)
void LLHTTPClient::getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{
if(offset > 0 || bytes > 0)
{
headers.addHeader("Range", llformat("bytes=%d-%d", offset, offset + bytes - 1));
}
request(url, LLURLRequest::HTTP_GET, NULL, responder, headers);
request(url, LLURLRequest::HTTP_GET, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
}
void LLHTTPClient::head(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers)
void LLHTTPClient::head(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{
request(url, LLURLRequest::HTTP_HEAD, NULL, responder, headers);
request(url, LLURLRequest::HTTP_HEAD, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
}
void LLHTTPClient::get(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers)
void LLHTTPClient::get(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{
request(url, LLURLRequest::HTTP_GET, NULL, responder, headers);
request(url, LLURLRequest::HTTP_GET, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
}
void LLHTTPClient::getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers)
void LLHTTPClient::getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{
request(url, LLURLRequest::HTTP_HEAD, NULL, responder, headers);
request(url, LLURLRequest::HTTP_HEAD, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
}
void LLHTTPClient::get(std::string const& url, LLSD const& query, ResponderPtr responder, AIHTTPHeaders& headers)
void LLHTTPClient::get(std::string const& url, LLSD const& query, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{
LLURI uri;
uri = LLURI::buildHTTP(url, LLSD::emptyArray(), query);
get(uri.asString(), responder, headers);
get(uri.asString(), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
}
//=============================================================================
@@ -362,6 +367,22 @@ void LLHTTPClient::ResponderBase::decode_raw_body(U32 status, std::string const&
}
}
std::string const& LLHTTPClient::ResponderBase::get_cookie(std::string const& key)
{
AIHTTPReceivedHeaders::range_type cookies;
mReceivedHeaders.getValues("set-cookie", cookies);
for (AIHTTPReceivedHeaders::iterator_type cookie = cookies.first; cookie != cookies.second; ++cookie)
{
if (key == cookie->second.substr(0, cookie->second.find('=')))
{
return cookie->second;
}
}
// Not found.
static std::string empty_dummy;
return empty_dummy;
}
// Called with HTML body.
// virtual
void LLHTTPClient::ResponderWithCompleted::completedRaw(U32 status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer)
@@ -554,7 +575,8 @@ enum EBlockingRequestAction {
static LLSD blocking_request(
std::string const& url,
EBlockingRequestAction method,
LLSD const& body) // Only used for HTTP_LLSD_POST
LLSD const& body/*,*/ // Only used for HTTP_LLSD_POST
DEBUG_CURLIO_PARAM(EDebugCurl debug))
{
lldebugs << "blockingRequest of " << url << llendl;
@@ -563,17 +585,17 @@ static LLSD blocking_request(
if (method == HTTP_LLSD_POST)
{
responder = new BlockingLLSDPostResponder;
LLHTTPClient::post(url, body, responder, headers);
LLHTTPClient::post(url, body, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
}
else if (method == HTTP_LLSD_GET)
{
responder = new BlockingLLSDGetResponder;
LLHTTPClient::get(url, responder, headers);
LLHTTPClient::get(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
}
else // method == HTTP_RAW_GET
{
responder = new BlockingRawGetResponder;
LLHTTPClient::get(url, responder, headers);
LLHTTPClient::get(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
}
responder->wait();
@@ -635,39 +657,39 @@ static LLSD blocking_request(
return response;
}
LLSD LLHTTPClient::blockingPost(const std::string& url, const LLSD& body)
LLSD LLHTTPClient::blockingPost(const std::string& url, const LLSD& body/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{
return blocking_request(url, HTTP_LLSD_POST, body);
return blocking_request(url, HTTP_LLSD_POST, body/*,*/ DEBUG_CURLIO_PARAM(debug));
}
LLSD LLHTTPClient::blockingGet(const std::string& url)
LLSD LLHTTPClient::blockingGet(const std::string& url/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{
return blocking_request(url, HTTP_LLSD_GET, LLSD());
return blocking_request(url, HTTP_LLSD_GET, LLSD()/*,*/ DEBUG_CURLIO_PARAM(debug));
}
U32 LLHTTPClient::blockingGetRaw(const std::string& url, std::string& body)
U32 LLHTTPClient::blockingGetRaw(const std::string& url, std::string& body/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{
LLSD result = blocking_request(url, HTTP_RAW_GET, LLSD());
LLSD result = blocking_request(url, HTTP_RAW_GET, LLSD()/*,*/ DEBUG_CURLIO_PARAM(debug));
body = result["body"].asString();
return result["status"].asInteger();
}
void LLHTTPClient::put(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers)
void LLHTTPClient::put(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{
request(url, LLURLRequest::HTTP_PUT, new LLSDInjector(body), responder, headers);
request(url, LLURLRequest::HTTP_PUT, new LLSDInjector(body), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
}
void LLHTTPClient::post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers)
void LLHTTPClient::post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive)
{
request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder, headers);
request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive);
}
void LLHTTPClient::postXMLRPC(std::string const& url, XMLRPC_REQUEST xmlrpc_request, ResponderPtr responder, AIHTTPHeaders& headers)
void LLHTTPClient::postXMLRPC(std::string const& url, XMLRPC_REQUEST xmlrpc_request, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive)
{
request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers, true, false); // Does use compression.
request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive, true, false); // Does use compression.
}
void LLHTTPClient::postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers)
void LLHTTPClient::postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive)
{
XMLRPC_REQUEST xmlrpc_request = XMLRPC_RequestNew();
XMLRPC_RequestSetMethodName(xmlrpc_request, method);
@@ -675,33 +697,33 @@ void LLHTTPClient::postXMLRPC(std::string const& url, char const* method, XMLRPC
XMLRPC_RequestSetData(xmlrpc_request, value);
// XMLRPCInjector takes ownership of xmlrpc_request and will free it when done.
// LLURLRequest takes ownership of the XMLRPCInjector object and will free it when done.
request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers, true, true); // Does not use compression.
request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive, true, true); // Does not use compression.
}
void LLHTTPClient::postRaw(std::string const& url, char const* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers)
void LLHTTPClient::postRaw(std::string const& url, char const* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive)
{
request(url, LLURLRequest::HTTP_POST, new RawInjector(data, size), responder, headers);
request(url, LLURLRequest::HTTP_POST, new RawInjector(data, size), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive);
}
void LLHTTPClient::postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers)
void LLHTTPClient::postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive)
{
request(url, LLURLRequest::HTTP_POST, new FileInjector(filename), responder, headers);
request(url, LLURLRequest::HTTP_POST, new FileInjector(filename), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive);
}
void LLHTTPClient::postFile(std::string const& url, LLUUID const& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers)
void LLHTTPClient::postFile(std::string const& url, LLUUID const& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive)
{
request(url, LLURLRequest::HTTP_POST, new VFileInjector(uuid, asset_type), responder, headers);
request(url, LLURLRequest::HTTP_POST, new VFileInjector(uuid, asset_type), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive);
}
// static
void LLHTTPClient::del(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers)
void LLHTTPClient::del(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{
request(url, LLURLRequest::HTTP_DELETE, NULL, responder, headers);
request(url, LLURLRequest::HTTP_DELETE, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
}
// static
void LLHTTPClient::move(std::string const& url, std::string const& destination, ResponderPtr responder, AIHTTPHeaders& headers)
void LLHTTPClient::move(std::string const& url, std::string const& destination, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{
headers.addHeader("Destination", destination);
request(url, LLURLRequest::HTTP_MOVE, NULL, responder, headers);
request(url, LLURLRequest::HTTP_MOVE, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
}

View File

@@ -66,6 +66,21 @@ struct AIBufferedCurlEasyRequestEvents {
virtual void completed_headers(U32 status, std::string const& reason, AITransferInfo* info) = 0; // Transaction completed.
};
enum EKeepAlive {
no_keep_alive = 0,
keep_alive
};
#ifdef DEBUG_CURLIO
enum EDebugCurl {
debug_off = 0,
debug_on
};
#define DEBUG_CURLIO_PARAM(p) ,p
#else
#define DEBUG_CURLIO_PARAM(p)
#endif
class LLHTTPClient {
public:
@@ -140,7 +155,16 @@ public:
{
// It's possible that this page was moved (302), so we already saw headers
// from the 302 page and are starting over on the new page now.
mReceivedHeaders.clear();
// Erase all headers EXCEPT the cookies.
AIHTTPReceivedHeaders set_cookie_headers;
AIHTTPReceivedHeaders::range_type cookies;
mReceivedHeaders.getValues("set-cookie", cookies);
for (AIHTTPReceivedHeaders::iterator_type cookie = cookies.first; cookie != cookies.second; ++cookie)
{
set_cookie_headers.addHeader(cookie->first, cookie->second);
}
// Replace headers with just the cookie headers.
mReceivedHeaders.swap(set_cookie_headers);
}
// Called for all remaining headers.
@@ -155,13 +179,19 @@ public:
completedHeaders(status, reason, mReceivedHeaders);
}
// Extract cookie 'key' from mReceivedHeaders and return the string 'key=value', or an empty string if key does not exists.
std::string const& get_cookie(std::string const& key);
public:
// Derived classes that implement completed_headers()/completedHeaders() should return true here.
virtual bool needsHeaders(void) const { return false; }
// A derived class should return true if curl should follow redirections.
// The default is not to follow redirections.
virtual bool followRedir(void) { return false; }
virtual bool followRedir(void) const { return false; }
// If this function returns false then we generate an error when a redirect status (300..399) is received.
virtual bool redirect_status_ok(void) const { return followRedir(); }
// Timeout policy to use.
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const = 0;
@@ -188,6 +218,7 @@ public:
class ResponderHeadersOnly : public ResponderBase {
private:
/*virtual*/ bool needsHeaders(void) const { return true; }
/*virtual*/ bool followRedir(void) const { return true; }
protected:
// ResponderBase event
@@ -357,59 +388,59 @@ public:
/** @name non-blocking API */
//@{
static void head(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers);
static void head(std::string const& url, ResponderHeadersOnly* responder)
{ AIHTTPHeaders headers; head(url, responder, headers); }
static void head(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
static void head(std::string const& url, ResponderHeadersOnly* responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
{ AIHTTPHeaders headers; head(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
static void getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder, AIHTTPHeaders& headers);
static void getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder)
{ AIHTTPHeaders headers; getByteRange(url, offset, bytes, responder, headers); }
static void getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
static void getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
{ AIHTTPHeaders headers; getByteRange(url, offset, bytes, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
static void get(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers);
static void get(std::string const& url, ResponderPtr responder)
{ AIHTTPHeaders headers; get(url, responder, headers); }
static void get(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
static void get(std::string const& url, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
{ AIHTTPHeaders headers; get(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
static void get(std::string const& url, LLSD const& query, ResponderPtr responder, AIHTTPHeaders& headers);
static void get(std::string const& url, LLSD const& query, ResponderPtr responder)
{ AIHTTPHeaders headers; get(url, query, responder, headers); }
static void get(std::string const& url, LLSD const& query, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
static void get(std::string const& url, LLSD const& query, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
{ AIHTTPHeaders headers; get(url, query, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
static void put(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers);
static void put(std::string const& url, LLSD const& body, ResponderPtr responder)
{ AIHTTPHeaders headers; put(url, body, responder, headers); }
static void put(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
static void put(std::string const& url, LLSD const& body, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
{ AIHTTPHeaders headers; put(url, body, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
static void getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers);
static void getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder)
{ AIHTTPHeaders headers; getHeaderOnly(url, responder, headers); }
static void getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
static void getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
{ AIHTTPHeaders headers; getHeaderOnly(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
static void post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers);
static void post(std::string const& url, LLSD const& body, ResponderPtr responder)
{ AIHTTPHeaders headers; post(url, body, responder, headers); }
static void post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive);
static void post(std::string const& url, LLSD const& body, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive)
{ AIHTTPHeaders headers; post(url, body, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); }
/** Takes ownership of request and deletes it when sent */
static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder, AIHTTPHeaders& headers);
static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder)
{ AIHTTPHeaders headers; postXMLRPC(url, request, responder, headers); }
static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive);
static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive)
{ AIHTTPHeaders headers; postXMLRPC(url, request, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); }
static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers);
static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder)
{ AIHTTPHeaders headers; postXMLRPC(url, method, value, responder, headers); }
static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive);
static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive)
{ AIHTTPHeaders headers; postXMLRPC(url, method, value, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); }
/** Takes ownership of data and deletes it when sent */
static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers);
static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder)
{ AIHTTPHeaders headers; postRaw(url, data, size, responder, headers); }
static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive);
static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive)
{ AIHTTPHeaders headers; postRaw(url, data, size, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); }
static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers);
static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder)
{ AIHTTPHeaders headers; postFile(url, filename, responder, headers); }
static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive);
static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive)
{ AIHTTPHeaders headers; postFile(url, filename, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); }
static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers);
static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder)
{ AIHTTPHeaders headers; postFile(url, uuid, asset_type, responder, headers); }
static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive);
static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive)
{ AIHTTPHeaders headers; postFile(url, uuid, asset_type, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); }
static void del(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers);
static void del(std::string const& url, ResponderPtr responder)
{ AIHTTPHeaders headers; del(url, responder, headers); }
static void del(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
static void del(std::string const& url, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
{ AIHTTPHeaders headers; del(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
///< sends a DELETE method, but we can't call it delete in c++
@@ -422,9 +453,9 @@ public:
* @param headers A map of key:value headers to pass to the request
* @param timeout The number of seconds to give the server to respond.
*/
static void move(std::string const& url, std::string const& destination, ResponderPtr responder, AIHTTPHeaders& headers);
static void move(std::string const& url, std::string const& destination, ResponderPtr responder)
{ AIHTTPHeaders headers; move(url, destination, responder, headers); }
static void move(std::string const& url, std::string const& destination, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
static void move(std::string const& url, std::string const& destination, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
{ AIHTTPHeaders headers; move(url, destination, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
//@}
@@ -434,7 +465,7 @@ public:
* @param url the complete serialized (and escaped) url to get
* @return An LLSD of { 'status':status, 'body':payload }
*/
static LLSD blockingGet(std::string const& url);
static LLSD blockingGet(std::string const& url/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
/**
* @brief Blocking HTTP GET that returns the raw body.
@@ -443,7 +474,7 @@ public:
* @param result the target string to write the body to
* @return HTTP status
*/
static U32 blockingGetRaw(const std::string& url, std::string& result);
static U32 blockingGetRaw(const std::string& url, std::string& result/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
/**
* @brief Blocking HTTP POST that returns an LLSD map of status and body.
@@ -452,7 +483,7 @@ public:
* @param body the LLSD post body
* @return An LLSD of { 'status':status (an int), 'body':payload (an LLSD) }
*/
static LLSD blockingPost(std::string const& url, LLSD const& body);
static LLSD blockingPost(std::string const& url, LLSD const& body/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
};
#endif // LL_LLHTTPCLIENT_H

View File

@@ -77,19 +77,14 @@ std::string LLURLRequest::actionAsVerb(LLURLRequest::ERequestAction action)
// This might throw AICurlNoEasyHandle.
LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action, std::string const& url, Injector* body,
LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool is_auth, bool no_compression) :
mAction(action), mURL(url), mIsAuth(is_auth), mNoCompression(no_compression),
LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool keepalive, bool is_auth, bool no_compression) :
mAction(action), mURL(url), mKeepAlive(keepalive), mIsAuth(is_auth), mNoCompression(no_compression),
mBody(body), mResponder(responder), mHeaders(headers)
{
}
void LLURLRequest::initialize_impl(void)
{
if (mHeaders.hasHeader("Cookie"))
{
allowCookies();
}
// If the header is "Pragma" with no value, the caller intends to
// force libcurl to drop the Pragma header it so gratuitously inserts.
// Before inserting the header, force libcurl to not use the proxy.
@@ -105,7 +100,7 @@ void LLURLRequest::initialize_impl(void)
// but if they did not specify a Content-Type, then ask the injector.
mHeaders.addHeader("Content-Type", mBody->contentType(), AIHTTPHeaders::keep_existing_header);
}
else
else if (mAction != HTTP_HEAD)
{
// Check to see if we have already set Accept or not. If no one
// set it, set it to application/llsd+xml since that's what we
@@ -199,12 +194,6 @@ void LLURLRequest::useProxy(const std::string &proxy)
}
#endif
void LLURLRequest::allowCookies()
{
AICurlEasyRequest_wat curlEasyRequest_w(*mCurlEasyRequest);
curlEasyRequest_w->setoptString(CURLOPT_COOKIEFILE, "");
}
bool LLURLRequest::configure(AICurlEasyRequest_wat const& curlEasyRequest_w)
{
bool rv = false;
@@ -213,13 +202,11 @@ bool LLURLRequest::configure(AICurlEasyRequest_wat const& curlEasyRequest_w)
{
case HTTP_HEAD:
curlEasyRequest_w->setopt(CURLOPT_NOBODY, 1);
curlEasyRequest_w->setopt(CURLOPT_FOLLOWLOCATION, 1);
rv = true;
break;
case HTTP_GET:
curlEasyRequest_w->setopt(CURLOPT_HTTPGET, 1);
curlEasyRequest_w->setopt(CURLOPT_FOLLOWLOCATION, 1);
// Set Accept-Encoding to allow response compression
curlEasyRequest_w->setoptString(CURLOPT_ENCODING, mNoCompression ? "identity" : "");
@@ -239,7 +226,7 @@ bool LLURLRequest::configure(AICurlEasyRequest_wat const& curlEasyRequest_w)
case HTTP_POST:
{
// Set the handle for an http post
curlEasyRequest_w->setPost(mBodySize);
curlEasyRequest_w->setPost(mBodySize, mKeepAlive);
// Set Accept-Encoding to allow response compression
curlEasyRequest_w->setoptString(CURLOPT_ENCODING, mNoCompression ? "identity" : "");

View File

@@ -77,18 +77,13 @@ class LLURLRequest : public AICurlEasyRequestStateMachine {
* @param action One of the ERequestAction enumerations.
* @param url The url of the request. It should already be encoded.
*/
LLURLRequest(ERequestAction action, std::string const& url, Injector* body, LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool is_auth, bool no_compression);
LLURLRequest(ERequestAction action, std::string const& url, Injector* body, LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool keepalive, bool is_auth, bool no_compression);
protected:
// Call abort(), not delete.
/*virtual*/ ~LLURLRequest() { }
public:
/**
* @brief Turn on cookie handling for this request with CURLOPT_COOKIEFILE.
*/
void allowCookies(void);
/**
* @ brief Turn off (or on) the CURLOPT_PROXY header.
*/
@@ -116,6 +111,7 @@ class LLURLRequest : public AICurlEasyRequestStateMachine {
private:
ERequestAction mAction;
std::string mURL;
bool mKeepAlive; // Set to false only when explicitely requested.
bool mIsAuth; // Set for authentication messages (login, buy land, buy currency).
bool mNoCompression; // Set to disable using gzip.
Injector* mBody; // Non-zero iff the action is HTTP_POST and HTTP_PUT.

View File

@@ -1027,7 +1027,8 @@ void LLModel::setVolumeFaceData(
if (tc.get())
{
LLVector4a::memcpyNonAliased16((F32*) face.mTexCoords, (F32*) tc.get(), num_verts*2*sizeof(F32));
U32 tex_size = (num_verts*2*sizeof(F32)+0xF)&~0xF;
LLVector4a::memcpyNonAliased16((F32*) face.mTexCoords, (F32*) tc.get(), tex_size);
}
else
{

View File

@@ -71,7 +71,7 @@ void LLStyle::drawControl(ControlElement element, const QStyleOption *option, QP
QPlastiqueStyle::drawControl(element, &localOption, painter, widget);
return;
}
default:
break;
}

View File

@@ -935,7 +935,7 @@ void LLGLManager::initExtensions()
mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts);
mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts);
mHasDebugOutput = ExtensionExists("GL_ARB_debug_output", gGLHExts.mSysExts);
mHasTransformFeedback = mGLVersion >= 4.f ? TRUE : FALSE;
mHasTransformFeedback = mGLVersion >= 4.f || ExtensionExists("GL_EXT_transform_feedback", gGLHExts.mSysExts);
#if !LL_DARWIN
mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts);
#endif

View File

@@ -1329,6 +1329,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
llassert(mCurrentDiscardLevel >= 0);
discard_level = mCurrentDiscardLevel;
}
discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel);
if (mTexName != 0 && discard_level == mCurrentDiscardLevel)
{
@@ -1586,7 +1587,18 @@ void LLImageGL::destroyGLTexture()
}
}
//force to invalidate the gl texture, most likely a sculpty texture
void LLImageGL::forceToInvalidateGLTexture()
{
if (mTexName != 0)
{
destroyGLTexture();
}
else
{
mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel.
}
}
//----------------------------------------------------------------------------

View File

@@ -119,6 +119,7 @@ public:
// Read back a raw image for this discard level, if it exists
BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok);
void destroyGLTexture();
void forceToInvalidateGLTexture();
void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE);
void setComponents(S8 ncomponents) { mComponents = ncomponents; }

View File

@@ -49,12 +49,63 @@ extern LLGLSLShader gPostNightVisionProgram;
extern LLGLSLShader gPostGaussianBlurProgram;
extern LLGLSLShader gPostPosterizeProgram;
extern LLGLSLShader gPostMotionBlurProgram;
extern LLGLSLShader gPostVignetteProgram;
static const unsigned int NOISE_SIZE = 512;
static const char * const XML_FILENAME = "postprocesseffects.xml";
template<> LLSD LLPostProcessShader::LLShaderSetting<LLVector4>::getDefaultValue()
class LLPostProcessShader : public IPostProcessShader, public LLRefCount
{
public:
LLPostProcessShader(const std::string& enable_name, LLGLSLShader& shader, bool enabled = false) :
mShader(shader), mEnabled(enable_name,enabled)
{
addSetting(mEnabled);
}
/*virtual*/ bool isEnabled() const {return mShader.mProgramObject && mEnabled;}
/*virtual*/ void bindShader() {mShader.bind();}
/*virtual*/ void unbindShader() {mShader.unbind();}
/*virtual*/ LLGLSLShader& getShader() {return mShader;}
/*virtual*/ LLSD getDefaults(); //See IPostProcessShader::getDefaults
/*virtual*/ void loadSettings(const LLSD& settings); //See IPostProcessShader::loadSettings
/*virtual*/ void addSetting(IShaderSettingBase& setting) { mSettings.push_back(&setting); }
protected:
template<typename T>
struct LLShaderSetting : public IShaderSettingBase
{
LLShaderSetting(const std::string& name, T def) :
mValue(def), mDefault(def), mSettingName(name) {}
operator T() const { return mValue; }
T get() const { return mValue; }
/*virtual*/ const std::string& getName() const { return mSettingName; } //See LLShaderSettingBase::getName
/*virtual*/ LLSD getDefaultValue() const { return mDefault; } //See LLShaderSettingBase::getDefaultValue
/*virtual*/ void setValue(const LLSD& value) { mValue = value; } //See LLShaderSettingBase::setValue
private:
const std::string mSettingName; //LLSD key names as found in postprocesseffects.xml. eg 'contrast_base'
T mValue; //The member variable mentioned above.
T mDefault; //Set via ctor. Value is inserted into the defaults LLSD list if absent from postprocesseffects.xml
};
private:
std::vector<IShaderSettingBase*> mSettings; //Contains a list of all the 'settings' this shader uses. Manually add via push_back in ctor.
LLGLSLShader& mShader;
LLShaderSetting<bool> mEnabled;
};
//helpers
class LLPostProcessSinglePassColorShader : public LLPostProcessShader
{
public:
LLPostProcessSinglePassColorShader(const std::string& enable_name, LLGLSLShader& shader, bool enabled = false) :
LLPostProcessShader(enable_name, shader, enabled) {}
/*virtual*/ S32 getColorChannel() const {return 0;}
/*virtual*/ S32 getDepthChannel() const {return -1;}
/*virtual*/ bool draw(U32 pass) {return pass == 1;}
/*virtual*/ void postDraw() {}
};
template<> LLSD LLPostProcessShader::LLShaderSetting<LLVector4>::getDefaultValue() const
{
return mDefault.getValue();
}
@@ -66,223 +117,175 @@ template<> void LLPostProcessShader::LLShaderSetting<LLVector4>::setValue(const
LLSD LLPostProcessShader::getDefaults()
{
LLSD defaults;
for(std::vector<LLShaderSettingBase*>::iterator it=mSettings.begin();it!=mSettings.end();++it)
for(std::vector<IShaderSettingBase*>::iterator it=mSettings.begin();it!=mSettings.end();++it)
{
defaults[(*it)->mSettingName]=(*it)->getDefaultValue();
defaults[(*it)->getName()]=(*it)->getDefaultValue();
}
return defaults;
}
void LLPostProcessShader::loadSettings(const LLSD& settings)
{
for(std::vector<LLShaderSettingBase*>::iterator it=mSettings.begin();it!=mSettings.end();++it)
for(std::vector<IShaderSettingBase*>::iterator it=mSettings.begin();it!=mSettings.end();++it)
{
LLSD value = settings[(*it)->mSettingName];
LLSD value = settings[(*it)->getName()];
(*it)->setValue(value);
}
}
class LLColorFilterShader : public LLPostProcessShader
class LLColorFilterShader : public LLPostProcessSinglePassColorShader
{
private:
LLShaderSetting<bool> mEnabled;
LLShaderSetting<F32> mGamma, mBrightness, mContrast, mSaturation;
LLShaderSetting<LLVector4> mContrastBase;
public:
LLColorFilterShader() :
mEnabled("enable_color_filter",false),
LLColorFilterShader() :
LLPostProcessSinglePassColorShader("enable_color_filter",gPostColorFilterProgram),
mGamma("gamma",1.f),
mBrightness("brightness",1.f),
mContrast("contrast",1.f),
mSaturation("saturation",1.f),
mContrastBase("contrast_base",LLVector4(1.f,1.f,1.f,0.5f))
{
mSettings.push_back(&mEnabled);
mSettings.push_back(&mGamma);
mSettings.push_back(&mBrightness);
mSettings.push_back(&mContrast);
mSettings.push_back(&mSaturation);
mSettings.push_back(&mContrastBase);
addSetting(mGamma);
addSetting(mBrightness);
addSetting(mContrast);
addSetting(mSaturation);
addSetting(mContrastBase);
}
bool isEnabled() { return mEnabled && gPostColorFilterProgram.mProgramObject; }
S32 getColorChannel() { return 0; }
S32 getDepthChannel() { return -1; }
QuadType bind()
/*virtual*/ QuadType preDraw()
{
if(!isEnabled())
return QUAD_NONE;
getShader().uniform1f("gamma", mGamma);
getShader().uniform1f("brightness", mBrightness);
getShader().uniform1f("contrast", mContrast);
float baseI = (mContrastBase.get()[VX] + mContrastBase.get()[VY] + mContrastBase.get()[VZ]) / 3.0f;
baseI = mContrastBase.get()[VW] / llmax(baseI,0.001f);
float baseR = mContrastBase.get()[VX] * baseI;
float baseG = mContrastBase.get()[VY] * baseI;
float baseB = mContrastBase.get()[VZ] * baseI;
getShader().uniform3fv("contrastBase", 1, LLVector3(baseR, baseG, baseB).mV);
getShader().uniform1f("saturation", mSaturation);
/// CALCULATING LUMINANCE (Using NTSC lum weights)
/// http://en.wikipedia.org/wiki/Luma_%28video%29
static const float LUMINANCE_R = 0.299f;
static const float LUMINANCE_G = 0.587f;
static const float LUMINANCE_B = 0.114f;
gPostColorFilterProgram.bind();
gPostColorFilterProgram.uniform1f("gamma", mGamma);
gPostColorFilterProgram.uniform1f("brightness", mBrightness);
gPostColorFilterProgram.uniform1f("contrast", mContrast);
float baseI = (mContrastBase.mValue[VX] + mContrastBase.mValue[VY] + mContrastBase.mValue[VZ]) / 3.0f;
baseI = mContrastBase.mValue[VW] / ((baseI < 0.001f) ? 0.001f : baseI);
float baseR = mContrastBase.mValue[VX] * baseI;
float baseG = mContrastBase.mValue[VY] * baseI;
float baseB = mContrastBase.mValue[VZ] * baseI;
gPostColorFilterProgram.uniform3fv("contrastBase", 1, LLVector3(baseR, baseG, baseB).mV);
gPostColorFilterProgram.uniform1f("saturation", mSaturation);
gPostColorFilterProgram.uniform3fv("lumWeights", 1, LLVector3(LUMINANCE_R, LUMINANCE_G, LUMINANCE_B).mV);
return QUAD_NORMAL;
}
bool draw(U32 pass) {return pass == 1;}
void unbind()
{
gPostColorFilterProgram.unbind();
}
};
class LLNightVisionShader : public LLPostProcessShader
class LLNightVisionShader : public LLPostProcessSinglePassColorShader
{
private:
LLShaderSetting<bool> mEnabled;
LLShaderSetting<F32> mBrightnessMult, mNoiseStrength;
public:
LLNightVisionShader() :
mEnabled("enable_night_vision",false),
LLPostProcessSinglePassColorShader("enable_night_vision",gPostNightVisionProgram),
mBrightnessMult("brightness_multiplier",3.f),
mNoiseStrength("noise_strength",.4f)
{
mSettings.push_back(&mEnabled);
mSettings.push_back(&mBrightnessMult);
mSettings.push_back(&mNoiseStrength);
addSetting(mBrightnessMult);
addSetting(mNoiseStrength);
}
bool isEnabled() { return mEnabled && gPostNightVisionProgram.mProgramObject; }
S32 getColorChannel() { return 0; }
S32 getDepthChannel() { return -1; }
QuadType bind()
/*virtual*/ QuadType preDraw()
{
if(!isEnabled())
return QUAD_NONE;
gPostNightVisionProgram.bind();
LLPostProcess::getInstance()->bindNoise(1);
gPostNightVisionProgram.uniform1f("brightMult", mBrightnessMult);
gPostNightVisionProgram.uniform1f("noiseStrength", mNoiseStrength);
getShader().uniform1f("brightMult", mBrightnessMult);
getShader().uniform1f("noiseStrength", mNoiseStrength);
return QUAD_NOISE;
}
bool draw(U32 pass) {return pass == 1;}
void unbind()
};
class LLPosterizeShader : public LLPostProcessSinglePassColorShader
{
private:
LLShaderSetting<S32> mNumLayers;
public:
LLPosterizeShader() : LLPostProcessSinglePassColorShader("enable_posterize",gPostPosterizeProgram),
mNumLayers("posterize_layers",2)
{
gPostNightVisionProgram.unbind();
addSetting(mNumLayers);
}
/*virtual*/ QuadType preDraw()
{
getShader().uniform1i("layerCount", mNumLayers);
return QUAD_NORMAL;
}
};
class LLVignetteShader : public LLPostProcessSinglePassColorShader
{
private:
LLShaderSetting<F32> mStrength, mRadius, mDarkness, mDesaturation, mChromaticAberration;
public:
LLVignetteShader() : LLPostProcessSinglePassColorShader("enable_vignette",gPostVignetteProgram),
mStrength("vignette_strength",.85f),
mRadius("vignette_radius",.7f),
mDarkness("vignette_darkness",1.f),
mDesaturation("vignette_desaturation",1.5f),
mChromaticAberration("vignette_chromatic_aberration",.05f)
{
addSetting(mStrength);
addSetting(mRadius);
addSetting(mDarkness);
addSetting(mDesaturation);
addSetting(mChromaticAberration);
}
/*virtual*/ QuadType preDraw()
{
LLVector2 screen_rect = LLPostProcess::getInstance()->getDimensions();
getShader().uniform1f("vignette_strength", mStrength);
getShader().uniform1f("vignette_radius", mRadius);
getShader().uniform1f("vignette_darkness", mDarkness);
getShader().uniform1f("vignette_desaturation", mDesaturation);
getShader().uniform1f("vignette_chromatic_aberration", mChromaticAberration);
getShader().uniform2fv("screen_res", 1, screen_rect.mV);
return QUAD_NORMAL;
}
};
class LLGaussBlurShader : public LLPostProcessShader
{
private:
LLShaderSetting<bool> mEnabled;
LLShaderSetting<S32> mNumPasses;
GLint mPassLoc;
public:
LLGaussBlurShader() :
mEnabled("enable_gauss_blur",false),
LLGaussBlurShader() : LLPostProcessShader("enable_gauss_blur",gPostGaussianBlurProgram),
mNumPasses("gauss_blur_passes",2),
mPassLoc(0)
{
mSettings.push_back(&mEnabled);
mSettings.push_back(&mNumPasses);
addSetting(mNumPasses);
}
bool isEnabled() { return mEnabled && mNumPasses && gPostGaussianBlurProgram.mProgramObject; }
S32 getColorChannel() { return 0; }
S32 getDepthChannel() { return -1; }
QuadType bind()
/*virtual*/ bool isEnabled() const { return LLPostProcessShader::isEnabled() && mNumPasses.get(); }
/*virtual*/ S32 getColorChannel() const { return 0; }
/*virtual*/ S32 getDepthChannel() const { return -1; }
/*virtual*/ QuadType preDraw()
{
if(!isEnabled())
return QUAD_NONE;
gPostGaussianBlurProgram.bind();
mPassLoc = gPostGaussianBlurProgram.getUniformLocation("horizontalPass");
mPassLoc = getShader().getUniformLocation("horizontalPass");
return QUAD_NORMAL;
}
bool draw(U32 pass)
/*virtual*/ bool draw(U32 pass)
{
if((S32)pass > mNumPasses*2)
return false;
glUniform1iARB(mPassLoc, (pass-1) % 2);
return true;
}
void unbind()
{
gPostGaussianBlurProgram.unbind();
}
};
class LLPosterizeShader : public LLPostProcessShader
{
private:
LLShaderSetting<bool> mEnabled;
LLShaderSetting<S32> mNumLayers;
public:
LLPosterizeShader() :
mEnabled("enable_posterize",false),
mNumLayers("posterize_layers",2)
{
mSettings.push_back(&mEnabled);
mSettings.push_back(&mNumLayers);
}
bool isEnabled() { return mEnabled && gPostPosterizeProgram.mProgramObject; }
S32 getColorChannel() { return 0; }
S32 getDepthChannel() { return -1; }
QuadType bind()
{
if(!isEnabled())
return QUAD_NONE;
gPostPosterizeProgram.bind();
gPostPosterizeProgram.uniform1i("layerCount", mNumLayers);
return QUAD_NORMAL;
}
bool draw(U32 pass)
{
return pass == 1;
}
void unbind()
{
gPostPosterizeProgram.unbind();
}
/*virtual*/ void postDraw() {}
};
class LLMotionShader : public LLPostProcessShader
{
private:
LLShaderSetting<bool> mEnabled;
LLShaderSetting<S32> mStrength;
public:
LLMotionShader() :
mEnabled("enable_motionblur",false),
mStrength("blur_strength",false)
LLMotionShader() : LLPostProcessShader("enable_motionblur",gPostMotionBlurProgram),
mStrength("blur_strength",1)
{
mSettings.push_back(&mEnabled);
mSettings.push_back(&mStrength);
addSetting(mStrength);
}
bool isEnabled() { return mEnabled && gPostMotionBlurProgram.mProgramObject; }
S32 getColorChannel() { return 0; }
S32 getDepthChannel() { return 1; }
QuadType bind()
/*virtual*/ S32 getColorChannel() const { return 0; }
/*virtual*/ S32 getDepthChannel() const { return 1; }
/*virtual*/ QuadType preDraw()
{
if(!isEnabled())
{
return QUAD_NONE;
}
glh::matrix4f inv_proj(gGLModelView);
inv_proj.mult_left(gGLProjection);
inv_proj = inv_proj.inverse();
@@ -291,22 +294,18 @@ public:
LLVector2 screen_rect = LLPostProcess::getInstance()->getDimensions();
gPostMotionBlurProgram.bind();
gPostMotionBlurProgram.uniformMatrix4fv("prev_proj", 1, GL_FALSE, prev_proj.m);
gPostMotionBlurProgram.uniformMatrix4fv("inv_proj", 1, GL_FALSE, inv_proj.m);
gPostMotionBlurProgram.uniform2fv("screen_res", 1, screen_rect.mV);
gPostMotionBlurProgram.uniform1i("blur_strength", mStrength);
getShader().uniformMatrix4fv("prev_proj", 1, GL_FALSE, prev_proj.m);
getShader().uniformMatrix4fv("inv_proj", 1, GL_FALSE, inv_proj.m);
getShader().uniform2fv("screen_res", 1, screen_rect.mV);
getShader().uniform1i("blur_strength", mStrength);
return QUAD_NORMAL;
}
bool draw(U32 pass)
/*virtual*/ bool draw(U32 pass)
{
return pass == 1;
}
void unbind()
{
gPostMotionBlurProgram.unbind();
}
/*virtual*/ void postDraw() {}
};
LLPostProcess::LLPostProcess(void) :
@@ -320,12 +319,12 @@ LLPostProcess::LLPostProcess(void) :
mAllEffectInfo(LLSD::emptyMap())
{
mShaders.push_back(new LLMotionShader());
mShaders.push_back(new LLVignetteShader());
mShaders.push_back(new LLColorFilterShader());
mShaders.push_back(new LLNightVisionShader());
mShaders.push_back(new LLGaussBlurShader());
mShaders.push_back(new LLPosterizeShader());
/* Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender.*/
std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME));
LL_DEBUGS2("AppInit", "Shaders") << "Loading PostProcess Effects settings from " << pathName << LL_ENDL;
@@ -547,20 +546,19 @@ void LLPostProcess::doEffects(void)
void LLPostProcess::applyShaders(void)
{
QuadType quad;
bool primary_rendertarget = 1;
for(std::list<LLPointer<LLPostProcessShader> >::iterator it=mShaders.begin();it!=mShaders.end();++it)
{
if((quad = (*it)->bind()) != QUAD_NONE)
if((*it)->isEnabled())
{
S32 color_channel = (*it)->getColorChannel();
S32 depth_channel = (*it)->getDepthChannel();
if(depth_channel >= 0)
gGL.getTexUnit(depth_channel)->bindManual(LLTexUnit::TT_RECT_TEXTURE, mDepthTexture);
U32 pass = 1;
(*it)->bindShader();
QuadType quad = (*it)->preDraw();
while((*it)->draw(pass++))
{
mRenderTarget[!primary_rendertarget].bindTarget();
@@ -573,7 +571,8 @@ void LLPostProcess::applyShaders(void)
if(mRenderTarget[0].getFBO())
primary_rendertarget = !primary_rendertarget;
}
(*it)->unbind();
(*it)->postDraw();
(*it)->unbindShader();
}
}
//Only need to copy to framebuffer if FBOs are supported, else we've already been drawing to the framebuffer to begin with.

View File

@@ -38,57 +38,48 @@
#include "llrendertarget.h"
class LLSD;
class LLGLSLShader;
typedef enum _QuadType {
QUAD_NONE,
QUAD_NORMAL,
QUAD_NOISE
} QuadType;
//LLPostProcessShader is an attempt to encapsulate the shaders a little better.
class LLPostProcessShader : public LLRefCount //Abstract. PostProcess shaders derive off of this common base.
class IPostProcessShader //Abstract. PostProcess shaders derive off of this common base.
{
protected:
//LLShaderSetting is used to associate key names to member variables to avoid LLSD lookups when drawing.
//It also facilitates automating the assigning of defaults to, as well as parsing from, the effects LLSD list.
//This replaces the entire old PostProcessTweaks structure. More will be done in the future to move into a more
//xml-driven configuration.
struct LLShaderSettingBase
struct IShaderSettingBase
{
LLShaderSettingBase(const char* name) : mSettingName(name) {}
const char* mSettingName; //LLSD key names as found in postprocesseffects.xml. eg 'contrast_base'
virtual LLSD getDefaultValue() = 0; //Converts the member variable as an LLSD. Used to set defaults absent in postprocesseffects.xml
virtual ~IShaderSettingBase() {} //virtual dtor.
virtual const std::string& getName() const = 0; //Returns the name of this setting
virtual LLSD getDefaultValue() const = 0; //Converts the member variable as an LLSD. Used to set defaults absent in postprocesseffects.xml
virtual void setValue(const LLSD& value) = 0; //Connects the LLSD element to the member variable. Used when loading effects (such as default)
};
template<typename T>
struct LLShaderSetting : public LLShaderSettingBase
{
LLShaderSetting(const char* setting_name, T def) : LLShaderSettingBase(setting_name), mValue(def), mDefault(def) {}
T mValue; //The member variable mentioned above.
T mDefault; //Set via ctor. Value is inserted into the defaults LLSD list if absent from postprocesseffects.xml
LLSD getDefaultValue() { return mDefault; } //See LLShaderSettingBase::getDefaultValue
void setValue(const LLSD& value) { mValue = value; } //See LLShaderSettingBase::setValue
operator T() { return mValue; } //Typecast operator overload so this object can be handled as if it was whatever T represents.
};
std::vector<LLShaderSettingBase*> mSettings; //Contains a list of all the 'settings' this shader uses. Manually add via push_back in ctor.
public:
virtual ~LLPostProcessShader() {};
virtual bool isEnabled() = 0; //Returning false avoids bind/draw/unbind calls. If no shaders are enabled, framebuffer copying is skipped.
virtual S32 getColorChannel() = 0; //If color buffer is used in this shader returns > -1 to cue LLPostProcess on copying it from the framebuffer.
virtual S32 getDepthChannel() = 0; //If depth buffer is used in this shader returns > -1 to cue LLPostProcess on copying it from the framebuffer.
virtual QuadType bind() = 0; //Bind shader and textures, set up attribs. Returns the 'type' of quad to be drawn.
virtual ~IPostProcessShader() {} //virtual dtor.
virtual bool isEnabled() const = 0; //Returning false avoids bind/draw/unbind calls. If no shaders are enabled, framebuffer copying is skipped.
virtual S32 getColorChannel() const = 0; //If color buffer is used in this shader returns > -1 to cue LLPostProcess on copying it from the framebuffer.
virtual S32 getDepthChannel() const = 0; //If depth buffer is used in this shader returns > -1 to cue LLPostProcess on copying it from the framebuffer.
virtual void bindShader() = 0;
virtual void unbindShader() = 0;
virtual LLGLSLShader& getShader() = 0;
virtual QuadType preDraw() = 0; //Bind shader and textures, set up attribs. Returns the 'type' of quad to be drawn.
virtual bool draw(U32 pass) = 0; //returning false means finished. Used to update per-pass attributes and such. LLPostProcess will call
//drawOrthoQuad when this returns true, increment pass, then call this again, and keep repeating this until false is returned.
virtual void unbind() = 0; //Unbind shader and textures.
virtual void postDraw() = 0; //Done drawing..
LLSD getDefaults(); //Returns a full LLSD kvp list filled with default values.
void loadSettings(const LLSD& settings); //Parses the effects LLSD list and sets the member variables linked to them (via LLShaderSetting::setValue())
virtual LLSD getDefaults() = 0; //Returns a full LLSD kvp list filled with default values.
virtual void loadSettings(const LLSD& settings) = 0; //Parses the effects LLSD list and sets the member variables linked to them (via LLShaderSetting::setValue())
virtual void addSetting(IShaderSettingBase& setting) = 0;
};
//LLVector4 does not implicitly convert to and from LLSD, so template specilizations are necessary.
template<> LLSD LLPostProcessShader::LLShaderSetting<LLVector4>::getDefaultValue();
template<> void LLPostProcessShader::LLShaderSetting<LLVector4>::setValue(const LLSD& value);
class LLPostProcessShader;
class LLPostProcess : public LLSingleton<LLPostProcess>
{
private:

View File

@@ -229,8 +229,6 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)
stop_glerror();
if (mIndex < 0) return false;
gGL.flush();
LLImageGL* gl_tex = NULL ;
if (texture == NULL || !(gl_tex = texture->getGLTexture()))
{
@@ -258,6 +256,7 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)
}
if ((mCurrTexture != gl_tex->getTexName()) || forceBind)
{
gGL.flush();
activate();
enable(gl_tex->getTarget());
mCurrTexture = gl_tex->getTexName();
@@ -1120,6 +1119,9 @@ void LLRender::refreshState(void)
setAlphaRejectSettings(mCurrAlphaFunc, mCurrAlphaFuncVal);
//Singu note: Also reset glBlendFunc
blendFunc(mCurrBlendColorSFactor,mCurrBlendColorDFactor,mCurrBlendAlphaSFactor,mCurrBlendAlphaDFactor);
mDirty = false;
}
@@ -1510,20 +1512,26 @@ void LLRender::pushUIMatrix()
{
if (mUIOffset.empty())
{
mUIOffset.push_back(new LLVector4a(0.f));
mUIOffset.push_back(static_cast<LLVector4a*>(ll_aligned_malloc_16(sizeof(LLVector4a))));
mUIOffset.back()->splat(0.f);
}
else
{
mUIOffset.push_back(new LLVector4a(*mUIOffset.back()));
const LLVector4a* last_entry = mUIOffset.back();
mUIOffset.push_back(static_cast<LLVector4a*>(ll_aligned_malloc_16(sizeof(LLVector4a))));
*mUIOffset.back() = *last_entry;
}
if (mUIScale.empty())
{
mUIScale.push_back(new LLVector4a(1.f));
mUIScale.push_back(static_cast<LLVector4a*>(ll_aligned_malloc_16(sizeof(LLVector4a))));
mUIScale.back()->splat(1.f);
}
else
{
mUIScale.push_back(new LLVector4a(*mUIScale.back()));
const LLVector4a* last_entry = mUIScale.back();
mUIScale.push_back(static_cast<LLVector4a*>(ll_aligned_malloc_16(sizeof(LLVector4a))));
*mUIScale.back() = *last_entry;
}
}
@@ -1533,9 +1541,9 @@ void LLRender::popUIMatrix()
{
llerrs << "UI offset stack blown." << llendl;
}
delete mUIOffset.back();
ll_aligned_free_16(mUIOffset.back());
mUIOffset.pop_back();
delete mUIScale.back();
ll_aligned_free_16(mUIScale.back());
mUIScale.pop_back();
}
@@ -1580,7 +1588,7 @@ void LLRender::setColorMask(bool writeColorR, bool writeColorG, bool writeColorB
if (mCurrColorMask[0] != writeColorR ||
mCurrColorMask[1] != writeColorG ||
mCurrColorMask[2] != writeColorB ||
mCurrColorMask[3] != writeAlpha)
mCurrColorMask[3] != writeAlpha || mDirty)
{
mCurrColorMask[0] = writeColorR;
mCurrColorMask[1] = writeColorG;
@@ -1635,7 +1643,7 @@ void LLRender::setAlphaRejectSettings(eCompareFunc func, F32 value)
}
if (mCurrAlphaFunc != func ||
mCurrAlphaFuncVal != value)
mCurrAlphaFuncVal != value || mDirty)
{
mCurrAlphaFunc = func;
mCurrAlphaFuncVal = value;
@@ -1679,7 +1687,7 @@ void LLRender::blendFunc(eBlendFactor sfactor, eBlendFactor dfactor)
llassert(sfactor < BF_UNDEF);
llassert(dfactor < BF_UNDEF);
if (mCurrBlendColorSFactor != sfactor || mCurrBlendColorDFactor != dfactor ||
mCurrBlendAlphaSFactor != sfactor || mCurrBlendAlphaDFactor != dfactor)
mCurrBlendAlphaSFactor != sfactor || mCurrBlendAlphaDFactor != dfactor || mDirty)
{
mCurrBlendColorSFactor = sfactor;
mCurrBlendAlphaSFactor = sfactor;
@@ -1704,7 +1712,7 @@ void LLRender::blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor,
return;
}
if (mCurrBlendColorSFactor != color_sfactor || mCurrBlendColorDFactor != color_dfactor ||
mCurrBlendAlphaSFactor != alpha_sfactor || mCurrBlendAlphaDFactor != alpha_dfactor)
mCurrBlendAlphaSFactor != alpha_sfactor || mCurrBlendAlphaDFactor != alpha_dfactor || mDirty)
{
mCurrBlendColorSFactor = color_sfactor;
mCurrBlendAlphaSFactor = alpha_sfactor;

View File

@@ -813,7 +813,6 @@ bool LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth
{
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepth);
}
check_framebuffer_status();
}
stop_glerror();

View File

@@ -25,6 +25,7 @@
*/
#include "linden_common.h"
#include <boost/filesystem.hpp> //First, because glh_linear #defines equivalent.. which boost uses internally
#include "llshadermgr.h"
@@ -53,6 +54,17 @@ LLShaderMgr * LLShaderMgr::sInstance = NULL;
LLShaderMgr::LLShaderMgr()
{
{
const std::string dumpdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"shader_dump")+gDirUtilp->getDirDelimiter();
try
{
boost::filesystem::remove_all(dumpdir);
}
catch(const boost::filesystem::filesystem_error& e)
{
llinfos << "boost::filesystem::remove_all(\""+dumpdir+"\") failed: '" + e.code().message() + "'" << llendl;
}
}
}
@@ -660,6 +672,10 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
}
}
static const LLCachedControl<bool> SHPackDeferredNormals("SHPackDeferredNormals",false);
if(SHPackDeferredNormals)
text[count++] = strdup("#define PACK_NORMALS\n");
//copy preprocessor definitions into buffer
for (std::map<std::string,std::string>::iterator iter = mDefinitions.begin(); iter != mDefinitions.end(); ++iter)
{
@@ -1116,7 +1132,7 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("ssao_max_radius");
mReservedUniforms.push_back("ssao_factor");
mReservedUniforms.push_back("ssao_factor_inv");
mReservedUniforms.push_back("ssao_effect_mat");
mReservedUniforms.push_back("ssao_effect");
mReservedUniforms.push_back("screen_res");
mReservedUniforms.push_back("near_clip");
mReservedUniforms.push_back("shadow_offset");

Some files were not shown because too many files have changed in this diff Show More