Mercurial > mplayer.hg
annotate libmpcodecs/ve_xvid.c @ 9278:caea8ed36b48
The reason why mplayer crashes (in some cases) when using x11
output and -wid (>0) parameter is this:
Mplayer by default creates a colormap using DirectColor visual. If the
window given to mplayer uses TrueColor visual there will be an error
when mplayer sets the colormap for the window. This patch
modifies mplayer to use TrueColor visual if the window given to mplayer
uses TrueColor. Another solution is to make sure that the window given to
mplayer is created using DirectColor visual if it is supported by the
display.
Jouni Tulkki <jitulkki@cc.hut.fi>
author | arpi |
---|---|
date | Tue, 04 Feb 2003 18:31:44 +0000 |
parents | c671e9adbe22 |
children | 4563dfa92a5b |
rev | line source |
---|---|
7456 | 1 #include <stdio.h> |
2 #include <stdlib.h> | |
3 #include <string.h> | |
8078 | 4 #include <errno.h> |
7456 | 5 |
6 #include "../config.h" | |
7 #include "../mp_msg.h" | |
8 | |
9 #ifdef HAVE_XVID | |
10 | |
11 #include "codec-cfg.h" | |
12 #include "stream.h" | |
13 #include "demuxer.h" | |
14 #include "stheader.h" | |
15 | |
8585 | 16 #include "muxer.h" |
7456 | 17 |
18 #include "img_format.h" | |
19 #include "mp_image.h" | |
20 #include "vf.h" | |
21 | |
22 #include <xvid.h> | |
23 #include "xvid_vbr.h" | |
24 | |
8491
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
25 #include "cfgparser.h" |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
26 |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
27 |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
28 #ifdef XVID_API_UNSTABLE |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
29 #warning ******************************************************************* |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
30 #warning ** ** |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
31 #warning ** Y O U '' R E U S I N G U N S T A B L E S O F T W A R E ** |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
32 #warning ** ** |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
33 #warning ** Streams produced by this version aren''nt probably compatible ** |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
34 #warning ** with anything else, even the xvid decoder itself. There are ** |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
35 #warning ** bugs, this code could crash, could blow up your PC or the ** |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
36 #warning ** whole building ! ** |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
37 #warning ** If you want stable code and compatible streams, use stable ** |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
38 #warning ** XViD releases (currently 0.9.x). ** |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
39 #warning ** ** |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
40 #warning ******************************************************************* |
8462
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
41 #endif |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
42 |
7456 | 43 /**********************************************************************/ |
8462
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
44 /* motion estimation quality presets */ |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
45 static int const motion_presets[7] = { |
8491
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
46 #ifdef XVID_API_UNSTABLE |
8462
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
47 0, |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
48 PMV_QUICKSTOP16, |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
49 0, |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
50 0, |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
51 PMV_HALFPELREFINE16 | PMV_HALFPELDIAMOND8, |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
52 PMV_HALFPELREFINE16 | PMV_HALFPELDIAMOND8 | PMV_ADVANCEDDIAMOND16, |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
53 PMV_HALFPELREFINE16 | PMV_EXTSEARCH16 | PMV_HALFPELREFINE8 | PMV_HALFPELDIAMOND8 | PMV_USESQUARES16 |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
54 #else |
8078 | 55 0, |
56 PMV_QUICKSTOP16, | |
7456 | 57 PMV_EARLYSTOP16, |
8078 | 58 PMV_EARLYSTOP16 | PMV_EARLYSTOP8, |
59 PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EARLYSTOP8 | PMV_HALFPELDIAMOND8, | |
60 PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EARLYSTOP8 | PMV_HALFPELDIAMOND8 | PMV_ADVANCEDDIAMOND16, | |
61 PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EXTSEARCH16 | PMV_EARLYSTOP8 | PMV_HALFPELREFINE8 | | |
62 PMV_HALFPELDIAMOND8 | PMV_USESQUARES16 | |
63 | |
8462
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
64 #endif |
7456 | 65 }; |
66 | |
8078 | 67 extern char* passtmpfile; |
7456 | 68 |
8078 | 69 static int xvidenc_pass = 0; |
8462
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
70 static int xvidenc_quality = 4; |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
71 static int xvidenc_4mv = 0; |
8078 | 72 static int xvidenc_bitrate = -1; |
73 static int xvidenc_rc_reaction_delay_factor = -1; | |
74 static int xvidenc_rc_averaging_period = -1; | |
75 static int xvidenc_rc_buffer = -1; | |
8247
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
76 static char* xvidenc_quant_range = "2-31/2-31"; |
8221 | 77 static int xvidenc_min_key_interval = -1; |
8078 | 78 static int xvidenc_max_key_interval = -1; |
79 static int xvidenc_mpeg_quant = 0; | |
8192 | 80 static int xvidenc_mod_quant = 0; |
8078 | 81 static int xvidenc_lumi_mask = 0; |
8221 | 82 static int xvidenc_keyframe_boost = -1; |
8192 | 83 static int xvidenc_kfthreshold = -1; |
84 static int xvidenc_kfreduction = -1; | |
8078 | 85 static int xvidenc_fixed_quant = 0; |
86 static int xvidenc_debug = 0; | |
87 static int xvidenc_hintedme = 0; | |
88 static char* xvidenc_hintfile = "xvid_hint_me.dat"; | |
8491
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
89 #ifdef XVID_API_UNSTABLE |
8462
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
90 static int xvidenc_qpel = 0; |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
91 static int xvidenc_max_bframes = 0; |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
92 static int xvidenc_bquant_ratio = 125; |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
93 static int xvidenc_bquant_offset = 60; |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
94 static int xvidenc_gmc = 0; |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
95 static int xvidenc_me_colour = 0; |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
96 static int xvidenc_reduced = 0; |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
97 #endif |
7458 | 98 |
7456 | 99 struct config xvidencopts_conf[] = { |
8078 | 100 { "pass", &xvidenc_pass, CONF_TYPE_INT, CONF_RANGE, 0, 2, NULL}, |
8462
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
101 { "me_quality", &xvidenc_quality, CONF_TYPE_INT, CONF_RANGE, 0, |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
102 sizeof(motion_presets) / sizeof(motion_presets[0]) - 1, NULL}, |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
103 { "4mv", &xvidenc_4mv, CONF_TYPE_FLAG, 0, 0, 1, NULL}, |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
104 { "bitrate", &xvidenc_bitrate, CONF_TYPE_INT, CONF_RANGE, 4, 24000000, NULL}, |
8078 | 105 { "rc_reaction_delay_factor", &xvidenc_rc_reaction_delay_factor, CONF_TYPE_INT, 0, 0, 0, NULL}, |
106 { "rc_averaging_period", &xvidenc_rc_averaging_period, CONF_TYPE_INT, 0, 0, 0, NULL}, | |
107 { "rc_buffer", &xvidenc_rc_buffer, CONF_TYPE_INT, 0, 0, 0, NULL}, | |
8247
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
108 { "quant_range", &xvidenc_quant_range, CONF_TYPE_STRING, 0, 0, 0, NULL}, |
8078 | 109 { "min_key_interval", &xvidenc_min_key_interval, CONF_TYPE_INT, 0, 0, 0, NULL}, /* for XVID_MODE_2PASS_2 */ |
110 { "max_key_interval", &xvidenc_max_key_interval, CONF_TYPE_INT, 0, 0, 0, NULL}, | |
111 { "mpeg_quant", &xvidenc_mpeg_quant, CONF_TYPE_FLAG, 0, 0, 1, NULL}, | |
8192 | 112 { "mod_quant", &xvidenc_mod_quant, CONF_TYPE_FLAG, 0, 0, 1, NULL}, |
8078 | 113 { "lumi_mask", &xvidenc_lumi_mask, CONF_TYPE_FLAG, 0, 0, 1, NULL}, |
8193 | 114 { "keyframe_boost", &xvidenc_keyframe_boost, CONF_TYPE_INT, CONF_RANGE, 0, 1000, NULL}, /* for XVID_MODE_2PASS_2 */ |
8078 | 115 { "kfthreshold", &xvidenc_kfthreshold, CONF_TYPE_INT, 0, 0, 0, NULL}, /* for XVID_MODE_2PASS_2 */ |
8192 | 116 { "kfreduction", &xvidenc_kfreduction, CONF_TYPE_INT, CONF_RANGE, 0, 100, NULL}, /* for XVID_MODE_2PASS_2 */ |
8078 | 117 { "fixed_quant", &xvidenc_fixed_quant, CONF_TYPE_INT, CONF_RANGE, 1, 31, NULL}, /* for XVID_MODE_FIXED_QUANT */ |
118 { "debug", &xvidenc_debug, CONF_TYPE_FLAG, 0, 0, 1, NULL}, | |
119 { "hintedme", &xvidenc_hintedme, CONF_TYPE_FLAG, 0, 0, 1, NULL}, | |
120 { "hintfile", &xvidenc_hintfile, CONF_TYPE_STRING, 0, 0, 0, NULL}, | |
8491
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
121 #ifdef XVID_API_UNSTABLE |
8462
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
122 { "qpel", &xvidenc_qpel, CONF_TYPE_FLAG, 0, 0, 1, NULL}, |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
123 { "max_bframes", &xvidenc_max_bframes, CONF_TYPE_INT, CONF_RANGE, 0, 4, NULL}, |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
124 { "bquant_ratio", &xvidenc_bquant_ratio, CONF_TYPE_INT, CONF_RANGE, 0, 1000, NULL}, |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
125 { "bquant_offset", &xvidenc_bquant_offset, CONF_TYPE_INT, CONF_RANGE, -1000, 1000, NULL}, |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
126 { "reduced", &xvidenc_reduced, CONF_TYPE_FLAG, 0, 0, 1, NULL}, |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
127 { "gmc", &xvidenc_gmc, CONF_TYPE_FLAG, 0, 0, 1, NULL}, |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
128 { "me_colour", &xvidenc_me_colour, CONF_TYPE_FLAG, 0, 0, 1, NULL}, |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
129 #endif |
7456 | 130 { NULL, NULL, 0, 0, 0, 0, NULL} |
131 }; | |
132 | |
133 struct vf_priv_s { | |
8585 | 134 muxer_stream_t* mux; |
7456 | 135 XVID_ENC_FRAME enc_frame; |
136 void* enc_handle; | |
137 vbr_control_t vbr_state; | |
138 FILE *hintfile; | |
8078 | 139 void *hintstream; |
7456 | 140 }; |
141 | |
142 static int | |
143 config(struct vf_instance_s* vf, | |
144 int width, int height, int d_width, int d_height, | |
145 unsigned int flags, unsigned int outfmt) | |
146 { | |
147 XVID_ENC_PARAM enc_param; | |
8078 | 148 struct vf_priv_s *fp = vf->priv; |
8247
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
149 unsigned int min_iq, max_iq, min_pq, max_pq; |
7456 | 150 |
8078 | 151 fp->mux->bih->biWidth = width; |
152 fp->mux->bih->biHeight = height; | |
153 fp->mux->bih->biSizeImage = fp->mux->bih->biWidth * fp->mux->bih->biHeight * 3; | |
154 mp_msg(MSGT_MENCODER,MSGL_INFO,"videocodec: XViD (%dx%d fourcc=%x [%.4s])\n", | |
155 width, height, fp->mux->bih->biCompression, (char *)&fp->mux->bih->biCompression); | |
7456 | 156 |
8247
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
157 // {min,max}_{i,p}quantizer parsing & validation |
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
158 if (sscanf (xvidenc_quant_range, "%u-%u/%u-%u", &min_iq, &max_iq, &min_pq, &max_pq) < 4) { |
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
159 mp_msg (MSGT_MENCODER, MSGL_ERR, |
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
160 "xvid: ERROR: cannot parse \"quant_range=%s\"\n", xvidenc_quant_range); |
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
161 return 0; |
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
162 } |
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
163 if (min_iq < 1 || min_iq > 31 || max_iq < 1 || max_iq > 31 || min_iq > max_iq || |
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
164 min_pq < 1 || min_pq > 31 || max_pq < 1 || max_pq > 31 || min_pq > max_pq) { |
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
165 mp_msg (MSGT_MENCODER, MSGL_ERR, |
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
166 "xvid: ERROR: {min,max} {I,P} quantizer must be in [1,31] and min must be <= max.\n"); |
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
167 mp_msg (MSGT_MENCODER, MSGL_ERR, |
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
168 "xvid: ERROR: cannot use \"quant_range=%s\"\n", xvidenc_quant_range); |
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
169 return -1; |
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
170 } |
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
171 |
8491
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
172 #ifdef XVID_API_UNSTABLE |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
173 mp_msg (MSGT_MENCODER, MSGL_WARN, |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
174 "\n" |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
175 "*******************************************************************\n" |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
176 "** **\n" |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
177 "** Y O U ' R E U S I N G U N S T A B L E S O F T W A R E **\n" |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
178 "** **\n" |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
179 "** Streams produced by this version aren'nt probably compatible **\n" |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
180 "** with anything else, even the xvid decoder itself. There are **\n" |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
181 "** bugs, this code could crash, could blow up your PC or the **\n" |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
182 "** whole building ! **\n" |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
183 "** If you want stable code and compatible streams, use stable **\n" |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
184 "** XViD releases (currently 0.9.x). **\n" |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
185 "** **\n" |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
186 "*******************************************************************\n" |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
187 "\n"); |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
188 #endif |
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
189 |
8078 | 190 // initialize XViD core parameters |
191 // =============================== | |
7456 | 192 memset(&enc_param, 0, sizeof(enc_param)); |
193 enc_param.width = width; | |
194 enc_param.height = height; | |
8078 | 195 enc_param.fincr = fp->mux->h.dwScale; |
196 enc_param.fbase = fp->mux->h.dwRate; | |
197 if (xvidenc_bitrate > 16000) | |
198 enc_param.rc_bitrate = xvidenc_bitrate; | |
199 else if (xvidenc_bitrate > 0) | |
200 enc_param.rc_bitrate = xvidenc_bitrate * 1000; | |
201 else | |
202 enc_param.rc_bitrate = -1; | |
8491
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
203 #ifdef XVID_API_UNSTABLE |
8462
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
204 if (xvidenc_max_bframes >= 1 && xvidenc_pass >= 1) { |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
205 mp_msg(MSGT_MENCODER,MSGL_WARN, "xvid: cannot use bframes with 2-pass, disabling bframes\n"); |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
206 xvidenc_max_bframes = 0; |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
207 } |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
208 enc_param.max_bframes = xvidenc_max_bframes; |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
209 enc_param.bquant_ratio = xvidenc_bquant_ratio; |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
210 enc_param.bquant_offset = xvidenc_bquant_offset; |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
211 if (xvidenc_reduced) |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
212 enc_param.global |= XVID_GLOBAL_REDUCED; |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
213 #endif |
8078 | 214 enc_param.rc_reaction_delay_factor = xvidenc_rc_reaction_delay_factor; |
215 enc_param.rc_averaging_period = xvidenc_rc_averaging_period; | |
216 enc_param.rc_buffer = xvidenc_rc_buffer; | |
8247
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
217 enc_param.min_quantizer = min_iq; |
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
218 enc_param.max_quantizer = max_iq; |
8221 | 219 if( xvidenc_max_key_interval <= 0 ) |
220 xvidenc_max_key_interval = 10 * enc_param.fbase / enc_param.fincr; | |
221 enc_param.max_key_interval = xvidenc_max_key_interval; | |
7456 | 222 switch (xvid_encore(NULL, XVID_ENC_CREATE, &enc_param, NULL)) { |
223 case XVID_ERR_FAIL: | |
8078 | 224 mp_msg(MSGT_MENCODER,MSGL_ERR, "xvid: encoder creation failed\n"); |
7456 | 225 return 0; |
226 case XVID_ERR_MEMORY: | |
8078 | 227 mp_msg(MSGT_MENCODER,MSGL_ERR, "xvid: encoder creation failed, out of memory\n"); |
7456 | 228 return 0; |
229 case XVID_ERR_FORMAT: | |
8078 | 230 mp_msg(MSGT_MENCODER,MSGL_ERR, "xvid: encoder creation failed, bad format\n"); |
7456 | 231 return 0; |
232 } | |
8078 | 233 fp->enc_handle = enc_param.handle; |
7456 | 234 |
8078 | 235 // initialize XViD per-frame static parameters |
236 // =========================================== | |
8462
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
237 fp->enc_frame.motion = motion_presets[xvidenc_quality]; |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
238 fp->enc_frame.general = XVID_HALFPEL | (xvidenc_mpeg_quant ? XVID_MPEGQUANT : XVID_H263QUANT); |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
239 if (xvidenc_4mv) |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
240 fp->enc_frame.general |= XVID_INTER4V; |
8078 | 241 if (xvidenc_lumi_mask) |
242 fp->enc_frame.general |= XVID_LUMIMASKING; | |
8491
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
243 #ifdef XVID_API_UNSTABLE |
8462
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
244 if (xvidenc_qpel) { |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
245 fp->enc_frame.general |= XVID_QUARTERPEL; |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
246 fp->enc_frame.motion |= PMV_QUARTERPELREFINE16 | PMV_QUARTERPELREFINE8; |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
247 } |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
248 if (xvidenc_gmc) |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
249 fp->enc_frame.general |= XVID_GMC; |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
250 if (xvidenc_me_colour) |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
251 fp->enc_frame.general |= XVID_ME_COLOUR; |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
252 if(xvidenc_reduced) |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
253 fp->enc_frame.general |= XVID_REDUCED; |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
254 #endif |
8078 | 255 |
7456 | 256 switch (outfmt) { |
257 case IMGFMT_YV12: | |
8078 | 258 fp->enc_frame.colorspace = XVID_CSP_YV12; |
7456 | 259 break; |
260 case IMGFMT_IYUV: case IMGFMT_I420: | |
8078 | 261 fp->enc_frame.colorspace = XVID_CSP_I420; |
7456 | 262 break; |
263 case IMGFMT_YUY2: | |
8078 | 264 fp->enc_frame.colorspace = XVID_CSP_YUY2; |
7456 | 265 break; |
266 case IMGFMT_UYVY: | |
8078 | 267 fp->enc_frame.colorspace = XVID_CSP_UYVY; |
7456 | 268 break; |
269 case IMGFMT_RGB24: case IMGFMT_BGR24: | |
8078 | 270 fp->enc_frame.colorspace = XVID_CSP_RGB24; |
7456 | 271 break; |
272 default: | |
273 mp_msg(MSGT_MENCODER,MSGL_ERR,"xvid: unsupported picture format (%s)!\n", | |
274 vo_format_name(outfmt)); | |
275 return 0; | |
276 } | |
8078 | 277 fp->enc_frame.quant_intra_matrix = 0; |
278 fp->enc_frame.quant_inter_matrix = 0; | |
279 | |
280 // hinted ME | |
281 fp->hintstream = NULL; | |
282 fp->hintfile = NULL; | |
283 if (xvidenc_hintedme && (xvidenc_pass == 1 || xvidenc_pass == 2)) { | |
284 fp->hintstream = malloc( 100000 ); // this is what the vfw code in XViD CVS allocates | |
285 if (fp->hintstream == NULL) | |
286 mp_msg(MSGT_MENCODER,MSGL_ERR, "xvid: cannot allocate memory for hinted ME\n"); | |
287 else { | |
288 fp->hintfile = fopen(xvidenc_hintfile, xvidenc_pass == 1 ? "w" : "r"); | |
289 if (fp->hintfile == NULL) { | |
290 mp_msg(MSGT_MENCODER,MSGL_ERR, "xvid: %s: %s\n", strerror(errno), xvidenc_hintfile); | |
291 free(fp->hintstream); | |
292 } | |
293 } | |
294 if (fp->hintstream == NULL || fp->hintfile == NULL) | |
295 xvidenc_hintedme = 0; | |
296 } | |
7456 | 297 |
8078 | 298 // initialize VBR engine |
299 // ===================== | |
300 vbrSetDefaults(&fp->vbr_state); | |
8221 | 301 if (xvidenc_min_key_interval < 0) |
302 xvidenc_min_key_interval = fp->vbr_state.min_key_interval; | |
303 | |
304 // pass | |
8078 | 305 if (xvidenc_pass == 0) { |
306 if (xvidenc_fixed_quant >= 1) { | |
307 fp->vbr_state.mode = VBR_MODE_FIXED_QUANT; | |
308 fp->vbr_state.fixed_quant = xvidenc_fixed_quant; | |
309 } else | |
310 fp->vbr_state.mode = VBR_MODE_1PASS; | |
7456 | 311 } |
8078 | 312 else if (xvidenc_pass == 1) |
313 fp->vbr_state.mode = VBR_MODE_2PASS_1; | |
314 else if (xvidenc_pass == 2) | |
315 fp->vbr_state.mode = VBR_MODE_2PASS_2; | |
316 else | |
317 return -1; | |
8221 | 318 |
319 // misc | |
8078 | 320 fp->vbr_state.fps = (double)enc_param.fbase / enc_param.fincr; |
321 fp->vbr_state.filename = passtmpfile; | |
322 fp->vbr_state.desired_bitrate = enc_param.rc_bitrate; | |
8247
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
323 fp->vbr_state.min_iquant = min_iq; |
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
324 fp->vbr_state.max_iquant = max_iq; |
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
325 fp->vbr_state.min_pquant = min_pq; |
91edcb091dc6
Instead of min_quantizer, max_quantizer, min_iquantizer, etc... use a
rguyom
parents:
8221
diff
changeset
|
326 fp->vbr_state.max_pquant = max_pq; |
8221 | 327 if (xvidenc_keyframe_boost >= 0) |
8078 | 328 fp->vbr_state.keyframe_boost = xvidenc_keyframe_boost; |
8192 | 329 if (xvidenc_kfthreshold >= 0) |
8078 | 330 fp->vbr_state.kftreshold = xvidenc_kfthreshold; |
8192 | 331 if (xvidenc_kfreduction >= 0) |
8078 | 332 fp->vbr_state.kfreduction = xvidenc_kfreduction; |
8221 | 333 if (xvidenc_min_key_interval >= 0) |
8078 | 334 fp->vbr_state.min_key_interval = xvidenc_min_key_interval; |
335 fp->vbr_state.max_key_interval = enc_param.max_key_interval; | |
336 fp->vbr_state.debug = xvidenc_debug; | |
8221 | 337 |
8078 | 338 vbrInit(&fp->vbr_state); |
339 | |
7456 | 340 return 1; |
341 } | |
342 | |
343 static void | |
344 uninit(struct vf_instance_s* vf) | |
345 { | |
8078 | 346 struct vf_priv_s *fp = vf->priv; |
347 | |
348 if (fp->hintfile) | |
349 fclose(fp->hintfile); | |
350 if (fp->hintstream) | |
351 free(fp->hintstream); | |
352 vbrFinish(&fp->vbr_state); | |
7456 | 353 } |
354 | |
355 static int | |
356 control(struct vf_instance_s* vf, int request, void* data) | |
357 { | |
358 return CONTROL_UNKNOWN; | |
359 } | |
360 | |
361 static int | |
362 query_format(struct vf_instance_s* vf, unsigned int fmt) | |
363 { | |
364 switch(fmt){ | |
365 case IMGFMT_YV12: case IMGFMT_IYUV: case IMGFMT_I420: | |
366 return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW; | |
367 case IMGFMT_YUY2: case IMGFMT_UYVY: | |
368 return VFCAP_CSP_SUPPORTED; | |
369 case IMGFMT_RGB24: case IMGFMT_BGR24: | |
370 return VFCAP_CSP_SUPPORTED | VFCAP_FLIPPED; | |
371 } | |
372 return 0; | |
373 } | |
374 | |
375 static int | |
376 put_image(struct vf_instance_s* vf, mp_image_t *mpi) | |
377 { | |
378 XVID_ENC_STATS enc_stats; | |
8078 | 379 struct vf_priv_s *fp = vf->priv; |
7456 | 380 |
8078 | 381 fp->enc_frame.bitstream = fp->mux->buffer; |
382 fp->enc_frame.length = -1 /* fp->mux->buffer_size */; | |
383 fp->enc_frame.image = mpi->planes[0]; | |
8561 | 384 #ifdef XVID_API_UNSTABLE |
385 fp->enc_frame.stride = mpi->stride[0]; | |
386 #endif | |
8192 | 387 |
388 // get quantizers & I/P decision from the VBR engine | |
8491
ce25d80dd6c3
Use the XVID_API_UNSTABLE macro instead of a home-made one.
rguyom
parents:
8462
diff
changeset
|
389 #ifdef XVID_API_UNSTABLE |
8462
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
390 if (xvidenc_max_bframes >= 1) { |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
391 if (!xvidenc_fixed_quant) { |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
392 // hack, the internal VBR engine isn't fixed-quant aware |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
393 fp->enc_frame.quant = xvidenc_fixed_quant; |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
394 fp->enc_frame.intra = -1; |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
395 fp->enc_frame.bquant = (xvidenc_fixed_quant * xvidenc_bquant_ratio + xvidenc_bquant_offset) / 100; |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
396 } else |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
397 // use the internal VBR engine since the external one isn't bframe aware |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
398 fp->enc_frame.quant = fp->enc_frame.intra = fp->enc_frame.bquant = -1; |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
399 } else { |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
400 fp->enc_frame.quant = vbrGetQuant(&fp->vbr_state); |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
401 fp->enc_frame.intra = vbrGetIntra(&fp->vbr_state); |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
402 } |
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
403 #else |
8078 | 404 fp->enc_frame.quant = vbrGetQuant(&fp->vbr_state); |
405 fp->enc_frame.intra = vbrGetIntra(&fp->vbr_state); | |
8462
800d77666843
Support the latest development code from XViD dev-api-3 CVS
rguyom
parents:
8247
diff
changeset
|
406 #endif |
8192 | 407 |
408 // modulated quantizer type | |
409 if (xvidenc_mod_quant && xvidenc_pass == 2) { | |
410 fp->enc_frame.general |= (fp->enc_frame.quant < 4) ? XVID_MPEGQUANT : XVID_H263QUANT; | |
411 fp->enc_frame.general &= (fp->enc_frame.quant < 4) ? ~XVID_H263QUANT : ~XVID_MPEGQUANT; | |
412 } | |
413 | |
414 // hinted ME, 1st part | |
8078 | 415 if (xvidenc_hintedme && xvidenc_pass == 1) { |
416 fp->enc_frame.hint.hintstream = fp->hintstream; | |
417 fp->enc_frame.hint.rawhints = 0; | |
418 fp->enc_frame.general |= XVID_HINTEDME_GET; | |
7456 | 419 } |
8078 | 420 else if (xvidenc_hintedme && xvidenc_pass == 2) { |
421 size_t read; | |
422 int blocksize; | |
423 fp->enc_frame.general &= ~XVID_HINTEDME_SET; | |
424 read = fread(&blocksize, sizeof(blocksize), 1, fp->hintfile); | |
425 if (read == 1) { | |
426 read = fread(fp->hintstream, (size_t)blocksize, 1, fp->hintfile); | |
7456 | 427 if (read == 1) { |
8078 | 428 fp->enc_frame.hint.hintstream = fp->hintstream; |
429 fp->enc_frame.hint.hintlength = 0; | |
430 fp->enc_frame.hint.rawhints = 0; | |
431 fp->enc_frame.general |= XVID_HINTEDME_SET; | |
432 } | |
7456 | 433 else |
8078 | 434 perror("xvid: hint file read block failure"); |
435 } | |
436 else | |
437 perror("xvid: hint file read failure"); | |
7456 | 438 } |
8192 | 439 |
440 // encode frame | |
8078 | 441 switch (xvid_encore(fp->enc_handle, XVID_ENC_ENCODE, &fp->enc_frame, &enc_stats)) { |
7456 | 442 case XVID_ERR_OK: |
443 break; | |
444 case XVID_ERR_MEMORY: | |
445 mp_msg(MSGT_MENCODER, MSGL_ERR, "xvid: out of memory\n"); | |
446 break; | |
447 case XVID_ERR_FORMAT: | |
448 mp_msg(MSGT_MENCODER, MSGL_ERR, "xvid: bad format\n"); | |
449 break; | |
450 default: | |
451 mp_msg(MSGT_MENCODER, MSGL_ERR, "xvid: failure\n"); | |
452 break; | |
453 } | |
8192 | 454 |
455 // write output | |
9014
c671e9adbe22
Cleanup of the muxer API, func parameters muxer & muxer_f eliminated.
arpi
parents:
8585
diff
changeset
|
456 muxer_write_chunk(fp->mux, fp->enc_frame.length, fp->enc_frame.intra==1 ? 0x10 : 0); |
8192 | 457 |
458 // update the VBR engine | |
8078 | 459 vbrUpdate(&fp->vbr_state, enc_stats.quant, fp->enc_frame.intra, |
460 enc_stats.hlength, fp->enc_frame.length, enc_stats.kblks, enc_stats.mblks, enc_stats.ublks); | |
8192 | 461 |
462 // hinted ME, 2nd part | |
8078 | 463 if (fp->enc_frame.general & XVID_HINTEDME_GET) { |
464 size_t wrote = fwrite(&fp->enc_frame.hint.hintlength, sizeof(fp->enc_frame.hint.hintlength), 1, fp->hintfile); | |
465 if (wrote == 1) { | |
466 wrote = fwrite(fp->enc_frame.hint.hintstream, fp->enc_frame.hint.hintlength, 1, fp->hintfile); | |
467 if (wrote != 1) | |
468 perror("xvid: hint write block failure"); | |
7456 | 469 } |
8078 | 470 else |
471 perror("xvid: hint write failure"); | |
7456 | 472 } |
473 return 1; | |
474 } | |
475 | |
476 //===========================================================================// | |
477 | |
478 static int | |
479 vf_open(vf_instance_t *vf, char* args) | |
480 { | |
481 XVID_INIT_PARAM params = { 0, 0, 0}; | |
482 vf->config = config; | |
483 vf->control = control; | |
484 vf->uninit = uninit; | |
485 vf->query_format = query_format; | |
486 vf->put_image = put_image; | |
487 vf->priv = malloc(sizeof(struct vf_priv_s)); | |
488 memset(vf->priv, 0, sizeof(struct vf_priv_s)); | |
8585 | 489 vf->priv->mux = (muxer_stream_t*)args; |
7456 | 490 |
491 vf->priv->mux->bih = malloc(sizeof(BITMAPINFOHEADER)); | |
492 vf->priv->mux->bih->biSize = sizeof(BITMAPINFOHEADER); | |
493 vf->priv->mux->bih->biWidth = 0; | |
494 vf->priv->mux->bih->biHeight = 0; | |
495 vf->priv->mux->bih->biPlanes = 1; | |
496 vf->priv->mux->bih->biBitCount = 24; | |
497 vf->priv->mux->bih->biCompression = mmioFOURCC('X','V','I','D'); | |
498 | |
499 if (xvid_init(NULL, 0, ¶ms, NULL) != XVID_ERR_OK) { | |
8078 | 500 mp_msg(MSGT_MENCODER,MSGL_ERR, "xvid: initialisation failure\n"); |
7456 | 501 abort(); |
502 } | |
503 if (params.api_version != API_VERSION) { | |
8078 | 504 mp_msg(MSGT_MENCODER,MSGL_ERR, "xvid: XviD library API version mismatch\n" |
7456 | 505 "\texpected %d.%d, got %d.%d, you should recompile MPlayer.\n", |
506 API_VERSION >> 16, API_VERSION & 0xff, | |
507 params.api_version >> 16, params.api_version & 0xff); | |
508 abort(); | |
509 } | |
510 | |
511 return 1; | |
512 } | |
513 | |
514 vf_info_t ve_info_xvid = { | |
515 "XviD encoder", | |
516 "xvid", | |
8078 | 517 "Kim Minh Kaplan & Rémi Guyomarch", |
7456 | 518 "for internal use by mencoder", |
519 vf_open | |
520 }; | |
521 | |
522 //===========================================================================// | |
523 #endif |