提交 2ed8e047 authored 作者: Steve Underwood's avatar Steve Underwood

Tweaks to the spandsp alloc functions, and a fix for bi-level image row

squashing.
上级 8f0dbcaa
...@@ -50,21 +50,25 @@ ...@@ -50,21 +50,25 @@
#include "spandsp/telephony.h" #include "spandsp/telephony.h"
#include "spandsp/alloc.h" #include "spandsp/alloc.h"
#ifdef _MSC_VER #if defined(_MSC_VER)
#pragma warning(push) #pragma warning(push)
#pragma warning(disable:4232) /* address of dllimport is not static, identity not guaranteed */ #pragma warning(disable:4232) /* address of dllimport is not static, identity not guaranteed */
#endif #endif
#if defined(HAVE_ALIGNED_ALLOC) #if defined(HAVE_ALIGNED_ALLOC)
static span_aligned_alloc_t __span_aligned_alloc = aligned_alloc; static span_aligned_alloc_t __span_aligned_alloc = aligned_alloc;
static span_aligned_free_t __span_aligned_free = free;
#elif defined(HAVE_MEMALIGN) #elif defined(HAVE_MEMALIGN)
static span_aligned_alloc_t __span_aligned_alloc = memalign; static span_aligned_alloc_t __span_aligned_alloc = memalign;
#elif defined(HAVE_POSIX_MEMALIGN) static span_aligned_free_t __span_aligned_free = free;
static void *fake_posix_memalign(size_t alignment, size_t size); #elif defined(__MSVC__)
static span_aligned_alloc_t __span_aligned_alloc = fake_posix_memalign; static void *fake_aligned_alloc(size_t alignment, size_t size);
static span_aligned_alloc_t __span_aligned_alloc = fake_aligned_alloc;
static span_aligned_free_t __span_aligned_free = _aligned_free;
#else #else
static void *fake_aligned_alloc(size_t alignment, size_t size); static void *fake_aligned_alloc(size_t alignment, size_t size);
static span_aligned_alloc_t __span_aligned_alloc = fake_aligned_alloc; static span_aligned_alloc_t __span_aligned_alloc = fake_aligned_alloc;
static span_aligned_free_t __span_aligned_free = free;
#endif #endif
static span_alloc_t __span_alloc = malloc; static span_alloc_t __span_alloc = malloc;
static span_realloc_t __span_realloc = realloc; static span_realloc_t __span_realloc = realloc;
...@@ -76,12 +80,19 @@ static span_free_t __span_free = free; ...@@ -76,12 +80,19 @@ static span_free_t __span_free = free;
#if defined(HAVE_ALIGNED_ALLOC) #if defined(HAVE_ALIGNED_ALLOC)
#elif defined(HAVE_MEMALIGN) #elif defined(HAVE_MEMALIGN)
#elif defined(__MSVC__)
static void *fake_aligned_alloc(size_t alignment, size_t size)
{
/* Make Microsoft's _aligned_malloc() look like the C11 aligned_alloc */
return _aligned_malloc(size, alignment);
}
/*- End of function --------------------------------------------------------*/
#elif defined(HAVE_POSIX_MEMALIGN) #elif defined(HAVE_POSIX_MEMALIGN)
static void *fake_posix_memalign(size_t alignment, size_t size) static void *fake_aligned_alloc(size_t alignment, size_t size)
{ {
void *ptr; void *ptr;
/* Make posix_memalign look like the more modern aligned_alloc */ /* Make posix_memalign() look like the C11 aligned_alloc */
posix_memalign(&ptr, alignment, size); posix_memalign(&ptr, alignment, size);
return ptr; return ptr;
} }
...@@ -94,12 +105,6 @@ static void *fake_aligned_alloc(size_t alignment, size_t size) ...@@ -94,12 +105,6 @@ static void *fake_aligned_alloc(size_t alignment, size_t size)
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
#endif #endif
SPAN_DECLARE(void *) span_aligned_alloc(size_t alignment, size_t size)
{
return __span_aligned_alloc(alignment, size);
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void *) span_alloc(size_t size) SPAN_DECLARE(void *) span_alloc(size_t size)
{ {
return __span_alloc(size); return __span_alloc(size);
...@@ -118,11 +123,28 @@ SPAN_DECLARE(void) span_free(void *ptr) ...@@ -118,11 +123,28 @@ SPAN_DECLARE(void) span_free(void *ptr)
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) span_mem_allocators(span_aligned_alloc_t custom_aligned_alloc, SPAN_DECLARE(void *) span_aligned_alloc(size_t alignment, size_t size)
span_alloc_t custom_alloc, {
return __span_aligned_alloc(alignment, size);
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) span_aligned_free(void *ptr)
{
__span_aligned_free(ptr);
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) span_mem_allocators(span_alloc_t custom_alloc,
span_realloc_t custom_realloc, span_realloc_t custom_realloc,
span_free_t custom_free) span_free_t custom_free,
span_aligned_alloc_t custom_aligned_alloc,
span_aligned_free_t custom_aligned_free)
{ {
__span_alloc = (custom_alloc) ? custom_alloc : malloc;
__span_realloc = (custom_realloc) ? custom_realloc : realloc;
__span_free = (custom_free) ? custom_free : free;
__span_aligned_alloc = (custom_aligned_alloc) __span_aligned_alloc = (custom_aligned_alloc)
? ?
custom_aligned_alloc custom_aligned_alloc
...@@ -131,14 +153,18 @@ SPAN_DECLARE(int) span_mem_allocators(span_aligned_alloc_t custom_aligned_alloc, ...@@ -131,14 +153,18 @@ SPAN_DECLARE(int) span_mem_allocators(span_aligned_alloc_t custom_aligned_alloc,
aligned_alloc; aligned_alloc;
#elif defined(HAVE_MEMALIGN) #elif defined(HAVE_MEMALIGN)
memalign; memalign;
#elif defined(HAVE_POSIX_MEMALIGN)
fake_posix_memalign;
#else #else
fake_aligned_alloc; fake_aligned_alloc;
#endif #endif
__span_alloc = (custom_alloc) ? custom_alloc : malloc; __span_aligned_free = (custom_aligned_free)
__span_realloc = (custom_realloc) ? custom_realloc : realloc; ?
__span_free = (custom_free) ? custom_free : free; custom_aligned_free
:
#if defined(__MSVC__)
_aligned_free;
#else
free;
#endif
return 0; return 0;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
......
...@@ -28,7 +28,17 @@ ...@@ -28,7 +28,17 @@
#if !defined(_SPANDSP_ALLOC_H_) #if !defined(_SPANDSP_ALLOC_H_)
#define _SPANDSP_ALLOC_H_ #define _SPANDSP_ALLOC_H_
/* Notes:
- Most platforms don't have an aligned realloc function, so we don't try to
support an aligned realloc on any platform.
- Some platforms use a special free function for memory which was allocated
by alligned allocation functions. We use a separate aligned_free function
on all platforms, for compatibility, even though it may simply reduce to
free().
*/
typedef void *(*span_aligned_alloc_t)(size_t alignment, size_t size); typedef void *(*span_aligned_alloc_t)(size_t alignment, size_t size);
typedef void (*span_aligned_free_t)(void *ptr);
typedef void *(*span_alloc_t)(size_t size); typedef void *(*span_alloc_t)(size_t size);
typedef void *(*span_realloc_t)(void *ptr, size_t size); typedef void *(*span_realloc_t)(void *ptr, size_t size);
typedef void (*span_free_t)(void *ptr); typedef void (*span_free_t)(void *ptr);
...@@ -41,20 +51,24 @@ extern "C" ...@@ -41,20 +51,24 @@ extern "C"
/* Allocate size bytes allocated to ALIGNMENT bytes. */ /* Allocate size bytes allocated to ALIGNMENT bytes. */
SPAN_DECLARE(void *) span_aligned_alloc(size_t alignment, size_t size); SPAN_DECLARE(void *) span_aligned_alloc(size_t alignment, size_t size);
/* Free a block allocated by span_aligned_alloc, or span_aligned_realloc. */
SPAN_DECLARE(void) span_aligned_free(void *ptr);
/* Allocate size bytes of memory. */ /* Allocate size bytes of memory. */
SPAN_DECLARE(void *) span_alloc(size_t size); SPAN_DECLARE(void *) span_alloc(size_t size);
/* Re-allocate the previously allocated block in ptr, making the new block size bytes long. */ /* Re-allocate the previously allocated block in ptr, making the new block size bytes long. */
SPAN_DECLARE(void *) span_realloc(void *ptr, size_t size); SPAN_DECLARE(void *) span_realloc(void *ptr, size_t size);
/* Free a block allocated by span_alloc, span_aligned_alloc, or span_realloc. */ /* Free a block allocated by span_alloc or span_realloc. */
SPAN_DECLARE(void) span_free(void *ptr); SPAN_DECLARE(void) span_free(void *ptr);
SPAN_DECLARE(int) span_mem_allocators(span_aligned_alloc_t custom_aligned_alloc, SPAN_DECLARE(int) span_mem_allocators(span_alloc_t custom_alloc,
span_alloc_t custom_alloc,
span_realloc_t custom_realloc, span_realloc_t custom_realloc,
span_free_t custom_free); span_free_t custom_free,
span_aligned_alloc_t custom_aligned_alloc,
span_aligned_free_t custom_aligned_free);
#if defined(__cplusplus) #if defined(__cplusplus)
} }
#endif #endif
......
...@@ -91,6 +91,13 @@ typedef struct ...@@ -91,6 +91,13 @@ typedef struct
const char *dcs; const char *dcs;
} t4_rx_metadata_t; } t4_rx_metadata_t;
typedef struct
{
uint8_t *buf;
int buf_len;
int buf_ptr;
} no_decoder_state_t;
/*! /*!
T.4 FAX decompression descriptor. This defines the working state T.4 FAX decompression descriptor. This defines the working state
for a single instance of a T.4 FAX decompression channel. for a single instance of a T.4 FAX decompression channel.
...@@ -114,6 +121,7 @@ struct t4_rx_state_s ...@@ -114,6 +121,7 @@ struct t4_rx_state_s
union union
{ {
no_decoder_state_t no_decoder;
t4_t6_decode_state_t t4_t6; t4_t6_decode_state_t t4_t6;
t85_decode_state_t t85; t85_decode_state_t t85;
#if defined(SPANDSP_SUPPORT_T88) #if defined(SPANDSP_SUPPORT_T88)
...@@ -132,11 +140,6 @@ struct t4_rx_state_s ...@@ -132,11 +140,6 @@ struct t4_rx_state_s
int current_decoder; int current_decoder;
uint8_t *pre_encoded_buf;
int pre_encoded_len;
int pre_encoded_ptr;
int pre_encoded_bit;
/* Supporting information, like resolutions, which the backend may want. */ /* Supporting information, like resolutions, which the backend may want. */
t4_rx_metadata_t metadata; t4_rx_metadata_t metadata;
......
...@@ -100,6 +100,14 @@ typedef struct ...@@ -100,6 +100,14 @@ typedef struct
int resolution_code; int resolution_code;
} t4_tx_metadata_t; } t4_tx_metadata_t;
typedef struct
{
uint8_t *buf;
int buf_len;
int buf_ptr;
int bit;
} no_encoder_state_t;
/*! /*!
T.4 FAX compression descriptor. This defines the working state T.4 FAX compression descriptor. This defines the working state
for a single instance of a T.4 FAX compression channel. for a single instance of a T.4 FAX compression channel.
...@@ -149,6 +157,7 @@ struct t4_tx_state_s ...@@ -149,6 +157,7 @@ struct t4_tx_state_s
union union
{ {
no_encoder_state_t no_encoder;
t4_t6_encode_state_t t4_t6; t4_t6_encode_state_t t4_t6;
t85_encode_state_t t85; t85_encode_state_t t85;
#if defined(SPANDSP_SUPPORT_T88) #if defined(SPANDSP_SUPPORT_T88)
...@@ -176,10 +185,7 @@ struct t4_tx_state_s ...@@ -176,10 +185,7 @@ struct t4_tx_state_s
int pack_row; int pack_row;
int pack_bit_mask; int pack_bit_mask;
uint8_t *pre_encoded_buf; no_encoder_state_t no_encoder;
int pre_encoded_len;
int pre_encoded_ptr;
int pre_encoded_bit;
/*! \brief Supporting information, like resolutions, which the backend may want. */ /*! \brief Supporting information, like resolutions, which the backend may want. */
t4_tx_metadata_t metadata; t4_tx_metadata_t metadata;
......
...@@ -76,6 +76,8 @@ SPAN_DECLARE(void) set_lab_gamut2(lab_params_t *s, int L_P, int L_Q, int a_P, in ...@@ -76,6 +76,8 @@ SPAN_DECLARE(void) set_lab_gamut2(lab_params_t *s, int L_P, int L_Q, int a_P, in
SPAN_DECLARE(void) get_lab_gamut2(lab_params_t *s, int *L_P, int *L_Q, int *a_P, int *a_Q, int *b_P, int *b_Q); SPAN_DECLARE(void) get_lab_gamut2(lab_params_t *s, int *L_P, int *L_Q, int *a_P, int *a_Q, int *b_P, int *b_Q);
SPAN_DECLARE(bool) t42_analyse_header(uint32_t *width, uint32_t *length, const uint8_t data[], size_t len);
SPAN_DECLARE(void) t42_encode_set_options(t42_encode_state_t *s, uint32_t l0, int quality, int options); SPAN_DECLARE(void) t42_encode_set_options(t42_encode_state_t *s, uint32_t l0, int quality, int options);
SPAN_DECLARE(int) t42_encode_set_image_width(t42_encode_state_t *s, uint32_t image_width); SPAN_DECLARE(int) t42_encode_set_image_width(t42_encode_state_t *s, uint32_t image_width);
......
...@@ -64,6 +64,8 @@ extern "C" ...@@ -64,6 +64,8 @@ extern "C"
{ {
#endif #endif
SPAN_DECLARE(bool) t85_analyse_header(uint32_t *width, uint32_t *length, const uint8_t data[], size_t len);
/*! \brief Check if we are at the end of the current document page. /*! \brief Check if we are at the end of the current document page.
\param s The T.85 context. \param s The T.85 context.
\return 0 for more data to come. SIG_STATUS_END_OF_DATA for no more data. */ \return 0 for more data to come. SIG_STATUS_END_OF_DATA for no more data. */
......
...@@ -1505,8 +1505,6 @@ static int build_dcs(t30_state_t *s) ...@@ -1505,8 +1505,6 @@ static int build_dcs(t30_state_t *s)
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE); set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE);
if (image_type == T4_IMAGE_TYPE_GRAY_12BIT || image_type == T4_IMAGE_TYPE_COLOUR_12BIT) if (image_type == T4_IMAGE_TYPE_GRAY_12BIT || image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_12BIT_COMPONENT); set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_12BIT_COMPONENT);
//if (???????? & T4_COMPRESSION_NO_SUBSAMPLING))
// set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_NO_SUBSAMPLING);
set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, T30_DCS_BIT_MIN_SCAN_LINE_TIME_1); set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, T30_DCS_BIT_MIN_SCAN_LINE_TIME_1);
use_bilevel = false; use_bilevel = false;
break; break;
...@@ -1789,17 +1787,13 @@ static int analyze_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len) ...@@ -1789,17 +1787,13 @@ static int analyze_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
} }
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_400_CAPABLE)) if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_400_CAPABLE))
{ {
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_INCH_RESOLUTION_PREFERRED)) s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_200_400;
s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_200_400; s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_R8_SUPERFINE;
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_METRIC_RESOLUTION_PREFERRED))
s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_R8_SUPERFINE;
} }
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE)) if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE))
{ {
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_INCH_RESOLUTION_PREFERRED)) s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_200_200;
s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_200_200; s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_R8_FINE;
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_METRIC_RESOLUTION_PREFERRED))
s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_R8_FINE;
s->mutual_colour_resolutions &= ~T4_RESOLUTION_200_200; s->mutual_colour_resolutions &= ~T4_RESOLUTION_200_200;
} }
else else
...@@ -6706,8 +6700,8 @@ SPAN_DECLARE(t30_state_t *) t30_init(t30_state_t *s, ...@@ -6706,8 +6700,8 @@ SPAN_DECLARE(t30_state_t *) t30_init(t30_state_t *s,
| T4_SUPPORT_LENGTH_A4 | T4_SUPPORT_LENGTH_A4
| T4_SUPPORT_LENGTH_B4 | T4_SUPPORT_LENGTH_B4
| T4_SUPPORT_LENGTH_UNLIMITED; | T4_SUPPORT_LENGTH_UNLIMITED;
/* Set the output encoding to something safe. For bi-level images ost things get /* Set the output encoding to something safe. For bi-level images most things
1D and 2D encoding right. Quite a lot get other things wrong. */ get 1D and 2D encoding right. Quite a lot get other things wrong. */
s->supported_output_compressions = T4_COMPRESSION_T4_2D | T4_COMPRESSION_JPEG; s->supported_output_compressions = T4_COMPRESSION_T4_2D | T4_COMPRESSION_JPEG;
s->local_min_scan_time_code = T30_MIN_SCAN_0MS; s->local_min_scan_time_code = T30_MIN_SCAN_0MS;
span_log_init(&s->logging, SPAN_LOG_NONE, NULL); span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
......
...@@ -72,7 +72,7 @@ ...@@ -72,7 +72,7 @@
#include "spandsp/private/t85.h" #include "spandsp/private/t85.h"
#include "spandsp/private/t42.h" #include "spandsp/private/t42.h"
/* The open_memstream() and fmemopen() in older versions of glibc seems quirky */ /* The open_memstream() and fmemopen() in older versions of glibc seem quirky */
#if defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 12)) #if defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 12))
#undef OPEN_MEMSTREAM #undef OPEN_MEMSTREAM
#endif #endif
...@@ -230,6 +230,38 @@ static __inline__ int unpack_16(uint8_t *s, uint16_t value) ...@@ -230,6 +230,38 @@ static __inline__ int unpack_16(uint8_t *s, uint16_t value)
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
SPAN_DECLARE(bool) t42_analyse_header(uint32_t *width, uint32_t *length, const uint8_t data[], size_t len)
{
int type;
int seg;
int pos;
/* Search the image data for its width and length */
*length = 0;
*width = 0;
pos = 0;
if (pack_16(&data[pos]) != 0xFFD8)
return false;
pos += 2;
while (pos < len)
{
type = pack_16(&data[pos]);
pos += 2;
seg = pack_16(&data[pos]) - 2;
pos += 2;
if (type == 0xFFC0)
{
*length = pack_16(&data[pos + 1]);
*width = pack_16(&data[pos + 3]);
return true;
}
pos += seg;
}
return false;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) xyz_to_corrected_color_temp(float *temp, float xyz[3]) SPAN_DECLARE(int) xyz_to_corrected_color_temp(float *temp, float xyz[3])
{ {
float us; float us;
......
...@@ -865,7 +865,8 @@ SPAN_DECLARE(int) t43_decode_restart(t43_decode_state_t *s) ...@@ -865,7 +865,8 @@ SPAN_DECLARE(int) t43_decode_restart(t43_decode_state_t *s)
{ {
/* ITULAB */ /* ITULAB */
/* Illuminant D50 */ /* Illuminant D50 */
set_lab_illuminant(&s->lab, 96.422f, 100.000f, 82.521f); //set_lab_illuminant(&s->lab, 96.422f, 100.000f, 82.521f);
set_lab_illuminant(&s->lab, 100.0f, 100.0f, 100.0f);
set_lab_gamut(&s->lab, 0, 100, -85, 85, -75, 125, false); set_lab_gamut(&s->lab, 0, 100, -85, 85, -75, 125, false);
s->t85.min_bit_planes = 1; s->t85.min_bit_planes = 1;
...@@ -898,7 +899,8 @@ SPAN_DECLARE(t43_decode_state_t *) t43_decode_init(t43_decode_state_t *s, ...@@ -898,7 +899,8 @@ SPAN_DECLARE(t43_decode_state_t *) t43_decode_init(t43_decode_state_t *s,
/* ITULAB */ /* ITULAB */
/* Illuminant D50 */ /* Illuminant D50 */
set_lab_illuminant(&s->lab, 96.422f, 100.000f, 82.521f); //set_lab_illuminant(&s->lab, 96.422f, 100.000f, 82.521f);
set_lab_illuminant(&s->lab, 100.0f, 100.0f, 100.0f);
set_lab_gamut(&s->lab, 0, 100, -85, 85, -75, 125, false); set_lab_gamut(&s->lab, 0, 100, -85, 85, -75, 125, false);
s->t85.min_bit_planes = 1; s->t85.min_bit_planes = 1;
......
差异被折叠。
差异被折叠。
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
#include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t81_t82_arith_coding.h"
#include "spandsp/private/t85.h" #include "spandsp/private/t85.h"
static __inline__ int32_t pack_32(uint8_t *s) static __inline__ int32_t pack_32(const uint8_t *s)
{ {
int32_t value; int32_t value;
...@@ -265,6 +265,16 @@ static int finish_sde(t85_decode_state_t *s) ...@@ -265,6 +265,16 @@ static int finish_sde(t85_decode_state_t *s)
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
SPAN_DECLARE(bool) t85_analyse_header(uint32_t *width, uint32_t *length, const uint8_t data[], size_t len)
{
if (len < 20)
return false;
*width = pack_32(&data[6]);
*length = pack_32(&data[10]);
return true;
}
/*- End of function --------------------------------------------------------*/
static int check_bih(t85_decode_state_t *s) static int check_bih(t85_decode_state_t *s)
{ {
/* Check that the fixed parameters have the values they are expected to be /* Check that the fixed parameters have the values they are expected to be
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论