comparison libvo/vo_zr.c @ 4348:d4acef803c94

use the new jpeg encoder - patch by Rik Snel <rsnel@cube.dyndns.org>
author arpi
date Sat, 26 Jan 2002 00:53:29 +0000
parents f96a2b9b41eb
children ed5b85b713a3
comparison
equal deleted inserted replaced
4347:d036a9992baf 4348:d4acef803c94
16 #include <linux/types.h> 16 #include <linux/types.h>
17 #include <linux/videodev.h> 17 #include <linux/videodev.h>
18 #include "zoran.h" 18 #include "zoran.h"
19 19
20 #include "config.h" 20 #include "config.h"
21 #define ZR_USES_LIBJPEG
22 21
23 #include "video_out.h" 22 #include "video_out.h"
24 #include "video_out_internal.h" 23 #include "video_out_internal.h"
25 #include "../mp_msg.h" 24 #include "../mp_msg.h"
26 #include "../cfgparser.h" 25 #include "../cfgparser.h"
38 37
39 /* General variables */ 38 /* General variables */
40 39
41 static int image_width; 40 static int image_width;
42 static int image_height; 41 static int image_height;
43 static int off_y, off_c, stride; /* for use by 'draw slice' */ 42 static int off_y, off_c, stride; /* for use by 'draw slice/frame' */
44 static int framenum; 43 static int framenum;
45 static int fields = 1; /* currently no interlacing */ 44 static int fields = 1; /* currently no interlacing */
46 static int forceinter = 0; 45 static int zrfd = 0;
46 static int bw = 0; /* if bw == 1, then display in black&white */
47 static int vdec = 1; 47 static int vdec = 1;
48 static int hdec = 1;
48 static int size; 49 static int size;
49 static int quality = 70; 50 static int quality = 1;
50 51
51 typedef struct { 52 typedef struct {
52 int width; 53 int width;
53 int height; 54 int height;
54 int xoff; 55 int xoff;
78 #define VO_ZR_DEFAULT_DEVICE "/dev/video" 79 #define VO_ZR_DEFAULT_DEVICE "/dev/video"
79 #endif 80 #endif
80 char *device = NULL; 81 char *device = NULL;
81 82
82 83
83 #ifdef ZR_USES_LIBJPEG 84 extern int mjpeg_encode_frame(char *bufr, int field);
84 #include<jpeglib.h> 85 extern void mjpeg_encoder_init(int w, int h, unsigned char *y,
85 int ccount; 86 int y_psize, int y_rsize, unsigned char *u,
86 unsigned char *ccbuf; 87 int u_psize, int u_rsize, unsigned char *v,
87 struct jpeg_compress_struct cinfo; 88 int v_psize, int v_rsize, int f, int cu, int q, int b);
88 struct jpeg_destination_mgr jdest;
89 struct jpeg_error_mgr jerr;
90
91 /* minimal destination handler to output to buffer */
92 METHODDEF(void) init_destination(struct jpeg_compress_struct *cinfo) {
93 // printf("init_destination called %p %d\n", ccbuf, ccount);
94 cinfo->dest->next_output_byte = (JOCTET*)(ccbuf+ccount);
95 cinfo->dest->free_in_buffer = MJPEG_SIZE - ccount;
96 }
97
98 METHODDEF(boolean) empty_output_buffer(struct jpeg_compress_struct *cinfo) {
99 // printf("empty_output_buffer called\n");
100 mp_msg(MSGT_VO, MSGL_ERR, "empty_output_buffer called, may not happen because buffer must me large enough\n");
101 return(FALSE);
102 }
103
104 METHODDEF(void) term_destination(struct jpeg_compress_struct *cinfo) {
105 // printf("term_destination called %p %d\n", ccbuf, ccount);
106 ccount = MJPEG_SIZE - cinfo->dest->free_in_buffer;
107 }
108 /* end of minimal destination handler */
109
110 JSAMPARRAY ***jsi;
111
112 #else
113 #include "../libavcodec/avcodec.h"
114 AVCodec *codec;
115 AVCodecContext codec_context;
116 AVPicture picture;
117 #endif
118
119 static int jpegdct = JDCT_IFAST;
120
121 int init_codec() {
122 #ifdef ZR_USES_LIBJPEG
123 int i, j, k;
124 cinfo.err = jpeg_std_error(&jerr);
125 jpeg_create_compress(&cinfo);
126
127 cinfo.dest = &jdest;
128 cinfo.dest->init_destination = init_destination;
129 cinfo.dest->empty_output_buffer = empty_output_buffer;
130 cinfo.dest->term_destination = term_destination;
131
132 cinfo.input_components = 3;
133
134 jpeg_set_defaults(&cinfo);
135
136 cinfo.image_width = image_width;
137 cinfo.image_height = image_height/fields;
138 cinfo.input_gamma = 1.0;
139 cinfo.in_color_space = JCS_YCbCr;
140 cinfo.raw_data_in = TRUE;
141 cinfo.comp_info[0].h_samp_factor = 2;
142 cinfo.comp_info[0].v_samp_factor = 1;
143 cinfo.comp_info[1].h_samp_factor = 1;
144 cinfo.comp_info[1].v_samp_factor = 1;
145 cinfo.comp_info[2].h_samp_factor = 1;
146 cinfo.comp_info[2].v_samp_factor = 1;
147 cinfo.dct_method = jpegdct;
148 jpeg_set_quality(&cinfo, quality, FALSE);
149 jsi = malloc(sizeof(JSAMPARRAY**)*fields);
150
151 /* Just some clutter to give libjpeg the pointers,
152 * and I don't want to recalculate everything everytime
153 * it is needed */
154 for (k = 0; k < fields; k++) {
155 jsi[k] = malloc(sizeof(JSAMPARRAY*)*image_height/(8*fields));
156
157 for (i = 0; i < image_height/(8*fields); i++) {
158 jsi[k][i] = malloc(3*sizeof(JSAMPARRAY));
159 jsi[k][i][0] = malloc(8*sizeof(JSAMPROW));
160 jsi[k][i][1] = malloc(8*sizeof(JSAMPROW));
161 jsi[k][i][2] = malloc(8*sizeof(JSAMPROW));
162 for (j = 0; j < 8; j++) {
163 jsi[k][i][0][j] = (JSAMPROW)(image +
164 (fields*(8*i + j) + k)*image_width);
165 jsi[k][i][1][j] = (JSAMPROW)(image + size +
166 (fields*(8*i + j)/2)*image_width/2);
167 jsi[k][i][2][j] = (JSAMPROW)(image + 3*size/2 +
168 (fields*(8*i + j)/2)*image_width/2);
169 }
170 }
171
172 }
173 #else
174 AVCodecContext *c = &codec_context;
175 codec = avcodec_find_encoder(CODEC_ID_MJPEG);
176 if (!codec) {
177 /* maybe libavcodec was not initialized */
178 avcodec_init();
179 avcodec_register_all();
180 codec = avcodec_find_encoder(CODEC_ID_MJPEG);
181 if (!codec) {
182 mp_msg(MSGT_VO, MSGL_ERR, "MJPG codec not found in libavcodec\n");
183 return 1;
184 }
185 }
186 /* put default values */
187 memset(c, 0, sizeof(*c));
188
189 c->width = image_width;
190 c->height = image_height;
191 c->bit_rate = 4000000;
192 c->frame_rate = 25*FRAME_RATE_BASE;
193 //c->gop_size = 1;
194 c->pix_fmt = PIX_FMT_YUV422P;
195
196 if (avcodec_open(c, codec) < 0) {
197 mp_msg(MSGT_VO, MSGL_ERR, "MJPG codec could not be opened\n");
198 return 1;
199 }
200
201 picture.data[0] = image;
202 picture.data[1] = image + size;
203 picture.data[2] = image + 3*size/2;
204 picture.linesize[0] = image_width;
205 picture.linesize[1] = image_width/2;
206 picture.linesize[2] = image_width/2;
207 #endif
208 return 0;
209 }
210
211 89
212 int zoran_getcap() { 90 int zoran_getcap() {
213 char* dev = device ? device : VO_ZR_DEFAULT_DEVICE; 91 char* dev = device ? device : VO_ZR_DEFAULT_DEVICE;
214 vdes = open(dev, O_RDWR); 92 vdes = open(dev, O_RDWR);
215 /* before we can ask for the maximum resolution, we must set 93 /* before we can ask for the maximum resolution, we must set
250 mp_msg(MSGT_VO, MSGL_V, "zr36067 reports: maxwidth=%d, maxheight=%d\n", vc.maxwidth, vc.maxheight); 128 mp_msg(MSGT_VO, MSGL_V, "zr36067 reports: maxwidth=%d, maxheight=%d\n", vc.maxwidth, vc.maxheight);
251 129
252 return 0; 130 return 0;
253 } 131 }
254 132
255 int init_zoran() { 133 int init_zoran(int zrhdec, int zrvdec) {
256 /* center the image, and stretch it as far as possible (try to keep 134 /* center the image, and stretch it as far as possible (try to keep
257 * aspect) and check if it fits */ 135 * aspect) and check if it fits */
258 if (image_width > vc.maxwidth) { 136 if (image_width/hdec > vc.maxwidth) {
259 mp_msg(MSGT_VO, MSGL_ERR, "movie to be played is too wide, max width currenty %d\n", vc.maxwidth); 137 mp_msg(MSGT_VO, MSGL_ERR, "movie to be played is too wide, max width currenty %d\n", vc.maxwidth);
260 return 1; 138 return 1;
261 } 139 }
262 140
263 if (image_height > vc.maxheight) { 141 if (image_height > vc.maxheight) {
264 mp_msg(MSGT_VO, MSGL_ERR, "movie to be played is too high, max height currenty %d\n", vc.maxheight); 142 mp_msg(MSGT_VO, MSGL_ERR, "movie to be played is too high, max height currenty %d\n", vc.maxheight);
265 return 1; 143 return 1;
266 } 144 }
267 145
268 zp.decimation = 0; 146 zp.decimation = 0;
269 zp.HorDcm = (vc.maxwidth >= 2*(int)image_width) ? 2 : 1; 147 zp.HorDcm = zrhdec;
270 zp.VerDcm = 1; 148 zp.VerDcm = zrvdec;
271 if (zp.HorDcm == 2 && 4*image_width <= vc.maxwidth &&
272 4*image_height/fields <= vc.maxheight) {
273 zp.HorDcm = 4;
274 zp.VerDcm = 2;
275 }
276 if (((forceinter == 0 && vdec >= 2) || (forceinter == 1 && vdec == 4)) && 4*image_height/fields <= vc.maxheight) {
277 zp.VerDcm = 2;
278 }
279 zp.TmpDcm = 1; 149 zp.TmpDcm = 1;
280 zp.field_per_buff = fields; 150 zp.field_per_buff = fields;
281 zp.img_x = (vc.maxwidth - zp.HorDcm*(int)image_width)/2; 151 zp.img_x = (vc.maxwidth - zp.HorDcm*(int)image_width/hdec)/2;
282 zp.img_y = (vc.maxheight - zp.VerDcm*(3-fields)*(int)image_height)/4; 152 zp.img_y = (vc.maxheight - zp.VerDcm*(3-fields)*(int)image_height)/4;
283 zp.img_width = zp.HorDcm*image_width; 153 zp.img_width = zp.HorDcm*image_width/hdec;
284 zp.img_height = zp.VerDcm*image_height/fields; 154 zp.img_height = zp.VerDcm*image_height/fields;
285 mp_msg(MSGT_VO, MSGL_V, "zr: geometry (after 'scaling'): %dx%d+%d+%d fields=%d, w=%d, h=%d\n", zp.img_width, zp.img_height, zp.img_x, zp.img_y, fields, image_width, image_height); 155 mp_msg(MSGT_VO, MSGL_V, "zr: geometry (after 'scaling'): %dx%d+%d+%d fields=%d, w=%d, h=%d\n", zp.img_width, (3-fields)*zp.img_height, zp.img_x, zp.img_y, fields, image_width/hdec, image_height);
286 156
287 if (ioctl(vdes, BUZIOC_S_PARAMS, &zp) < 0) { 157 if (ioctl(vdes, BUZIOC_S_PARAMS, &zp) < 0) {
288 mp_msg(MSGT_VO, MSGL_ERR, "error setting display parameters\n"); 158 mp_msg(MSGT_VO, MSGL_ERR, "error setting display parameters\n");
289 return 1; 159 return 1;
290 } 160 }
325 } 195 }
326 196
327 static uint32_t init(uint32_t width, uint32_t height, uint32_t d_width, 197 static uint32_t init(uint32_t width, uint32_t height, uint32_t d_width,
328 uint32_t d_height, uint32_t fullscreen, char *title, uint32_t format) 198 uint32_t d_height, uint32_t fullscreen, char *title, uint32_t format)
329 { 199 {
330 int j; 200 int j, stretchx, stretchy;
331 /* this allows to crop parts from incoming picture, 201 /* this allows to crop parts from incoming picture,
332 * for easy 512x240 -> 352x240 */ 202 * for easy 512x240 -> 352x240 */
333 /* These values must be multples of 2 */ 203 /* These values must be multples of 2 */
334 204 if (format != IMGFMT_YV12 && format != IMGFMT_YUY2) {
205 printf("vo_zr called with wrong format");
206 exit(1);
207 }
208 stride = 2*width;
335 if (g.set) { 209 if (g.set) {
336 if (g.width%2 != 0 || g.height%2 != 0 || 210 if (g.width%2 != 0 || g.height%2 != 0 ||
337 g.xoff%2 != 0 || g.yoff%2 != 0) { 211 g.xoff%2 != 0 || g.yoff%2 != 0) {
338 mp_msg(MSGT_VO, MSGL_ERR, "arguments in -zrcrop must be multiples of 2\n"); 212 mp_msg(MSGT_VO, MSGL_ERR, "arguments in -zrcrop must be multiples of 2\n");
339 return 1; 213 return 1;
358 g.yoff = 0; 232 g.yoff = 0;
359 } 233 }
360 /* we must know the maximum resolution of the device 234 /* we must know the maximum resolution of the device
361 * it differs for DC10+ and buz for example */ 235 * it differs for DC10+ and buz for example */
362 zoran_getcap(); /*must be called before init_zoran */ 236 zoran_getcap(); /*must be called before init_zoran */
363 if (g.height/vdec > vc.maxheight/2 || (forceinter == 1 && vdec == 1)) 237 /* make the scaling decision
238 * we are capable of stretching the image in the horizontal
239 * direction by factors 1, 2 and 4
240 * we can stretch the image in the vertical direction by a factor
241 * of 1 and 2 AND we must decide about interlacing */
242 if (g.width > vc.maxwidth/2 || g.height > vc.maxheight/2) {
243 stretchx = 1;
244 stretchy = 1;
364 fields = 2; 245 fields = 2;
365 printf("fields=%d\n", fields); 246 if (vdec == 2) {
247 fields = 1;
248 } else if (vdec == 4) {
249 stretchy = 2;
250 }
251 stretchx = hdec;
252 } else if (g.width > vc.maxwidth/4 || g.height > vc.maxheight/4) {
253 stretchx = 2;
254 stretchy = 1;
255 fields = 1;
256 if (vdec == 2) {
257 stretchy = 2;
258 } else if (vdec == 4) {
259 if (!zrfd) {
260 mp_msg(MSGT_VO, MSGL_WARN, "vo_zr: vertical decimation too high, changing to 2 (use -zrfd to keep vdec=4)\n");
261 vdec = 2;
262 }
263 stretchy = 2;
264 }
265 if (hdec == 2) {
266 stretchx = 4;
267 } else if (hdec == 4){
268 if (!zrfd) {
269 mp_msg(MSGT_VO, MSGL_WARN, "vo_zr: horizontal decimation too high, changing to 2 (use -zrfd to keep hdec=4)\n");
270 hdec = 2;
271 }
272 stretchx = 4;
273 }
274 } else {
275 /* output image is maximally stretched */
276 stretchx = 4;
277 stretchy = 2;
278 fields = 1;
279 if (vdec != 1 && !zrfd) {
280 mp_msg(MSGT_VO, MSGL_WARN, "vo_zr: vertical decimation too high, changing to 1 (use -zrfd to keep vdec=%d)\n", vdec);
281 vdec = 1;
282 }
283
284 if (hdec != 1 && !zrfd) {
285 mp_msg(MSGT_VO, MSGL_WARN, "vo_zr: vertical decimation too high, changing to 1 (use -zrfd to keep hdec=%d)\n", hdec);
286 hdec = 1;
287 }
288 }
366 /* the height must be a multiple of fields*8 and the width 289 /* the height must be a multiple of fields*8 and the width
367 * must be a multiple of 16 */ 290 * must be a multiple of 16 */
368 /* add some black borders to make it so, and center the image*/ 291 /* add some black borders to make it so, and center the image*/
369 image_height = fields*8*((g.height/vdec - 1)/(fields*8) + 1); 292 image_height = fields*8*((g.height/vdec - 1)/(fields*8) + 1);
370 image_width = 16*((g.width - 1)/16 + 1); 293 image_width = (hdec*16)*((g.width - 1)/(hdec*16) + 1);
371 off_y = (image_height - g.height/vdec)/2; 294 off_y = (image_height - g.height/vdec)/2;
372 if (off_y%2 != 0) off_y++; 295 if (off_y%2 != 0) off_y++;
373 off_y *= image_width; 296 off_y *= image_width;
374 off_c = off_y/4; 297 off_c = off_y/4;
375 off_y += (image_width - g.width)/2; 298 off_y += (image_width - g.width)/2;
376 if (off_y%2 != 0) off_y--; 299 if (off_y%2 != 0) off_y--;
377 off_c += (image_width - g.width)/4; 300 off_c += (image_width - g.width)/4;
378 framenum = 0; 301 framenum = 0;
379 size = image_width*image_height; 302 size = image_width*image_height;
380 mp_msg(MSGT_VO, MSGL_V, "input: %dx%d, cropped: %dx%d, output: %dx%d, off_y=%d, off_c=%d\n", width, height, g.width, g.height, image_width, image_height, off_y, off_c); 303 mp_msg(MSGT_VO, MSGL_V, "input: %dx%d, cropped: %dx%d, output: %dx%d, off_y=%d, off_c=%d\n", width/hdec, height, g.width, g.height, image_width, image_height, off_y, off_c);
381 304
382 image = malloc(2*size); /* this buffer allows for YUV422 data, 305 image = malloc(2*size); /* this buffer allows for YUV422 data,
383 * so it is a bit too big for YUV420 */ 306 * so it is a bit too big for YUV420 */
384 if (!image) { 307 if (!image) {
385 mp_msg(MSGT_VO, MSGL_ERR, "Memory exhausted\n"); 308 mp_msg(MSGT_VO, MSGL_ERR, "Memory exhausted\n");
386 return 1; 309 return 1;
387 } 310 }
388 /* and make sure that the borders are _really_ black */ 311 /* and make sure that the borders are _really_ black */
389 memset(image, 0, image_width*image_height); 312 switch (format) {
390 memset(image + size, 0x80, image_width*image_height/4); 313 case IMGFMT_YV12:
391 memset(image + 3*size/2, 0x80, image_width*image_height/4); 314 memset(image, 0, image_width*image_height);
392 315 memset(image + size, 0x80, image_width*image_height/4);
393 if (init_codec()) { 316 memset(image + 3*size/2, 0x80, image_width*image_height/4);
394 return 1; 317 mjpeg_encoder_init(image_width/hdec, image_height,
395 } 318 image, hdec, image_width,
396 319 image + image_width*image_height,
397 if (init_zoran()) { 320 hdec, image_width/2,
398 #ifdef ZR_USES_LIBJPEG 321 image + 3*image_width*image_height/2,
399 jpeg_destroy_compress(&cinfo); 322 hdec, image_width/2, fields, 1,
400 #else 323 quality, bw);
401 avcodec_close(&codec_context); 324 break;
402 #endif 325 case IMGFMT_YUY2:
326 for (j = 0; j < 2*size; j+=4) {
327 image[j] = 0;
328 image[j+1] = 0x80;
329 image[j+2] = 0;
330 image[j+3] = 0x80;
331 }
332 mjpeg_encoder_init(image_width/hdec, image_height,
333 image, hdec*2, image_width*2,
334 image + 1, hdec*4, image_width*2,
335 image + 3, hdec*4, image_width*2,
336 fields, 0, quality, bw);
337 break;
338 default:
339 mp_msg(MSGT_VO, MSGL_FATAL, "internal inconsistency in vo_zr\n");
340 }
341
342
343 if (init_zoran(stretchx, stretchy)) {
403 return 1; 344 return 1;
404 } 345 }
405 346
406 return 0; 347 return 0;
407 } 348 }
412 353
413 static void draw_osd(void) { 354 static void draw_osd(void) {
414 } 355 }
415 356
416 static void flip_page (void) { 357 static void flip_page (void) {
417 #ifdef ZR_USES_LIBJPEG
418 int i, j, k; 358 int i, j, k;
419 #else 359 /*FILE *fp;
420 AVCodecContext *c = &codec_context; 360 char filename[100];*/
421 #endif
422
423 /* do we have a free buffer? */ 361 /* do we have a free buffer? */
424 if (queue-synco < zrq.count) { 362 if (queue-synco < zrq.count) {
425 frame = queue; 363 frame = queue;
426 } else { 364 } else {
427 if (ioctl(vdes, BUZIOC_SYNC, &zs) < 0) 365 if (ioctl(vdes, BUZIOC_SYNC, &zs) < 0)
428 mp_msg(MSGT_VO, MSGL_ERR, "error waiting for buffers to become free"); 366 mp_msg(MSGT_VO, MSGL_ERR, "error waiting for buffers to become free");
429 frame = zs.frame; 367 frame = zs.frame;
430 synco++; 368 synco++;
431 } 369 }
432 370 k=0;
433 #ifdef ZR_USES_LIBJPEG 371 for (i = 0; i < fields; i++)
434 ccbuf = buf + frame*zrq.size; 372 k+=mjpeg_encode_frame(buf+frame*zrq.size+k, i);
435 ccount = 0; 373 /* Warning, Quantization and Huffman tables are only
436 k = fields; 374 * written in the first frame by default (to preserver bandwidth) */
437 for (j=0; j < k; j++) { 375 /*sprintf(filename, "test%04d.jpg", framenum);
438 376 fp = fopen(filename, "w");
439 jpeg_start_compress(&cinfo, TRUE); 377 if (!fp) exit(1);
440 i=0; 378 fwrite(buf+frame*zrq.size, 1, k, fp);
441 while (cinfo.next_scanline < cinfo.image_height) { 379 fclose(fp);*/
442 jpeg_write_raw_data(&cinfo, jsi[j][i], 8); 380 /*fp = fopen("test1.jpg", "r");
443 i++; 381 fread(buf+frame*zrq.size, 1, 2126, fp);
444 } 382 fclose(fp);*/
445 jpeg_finish_compress(&cinfo); 383
446
447 }
448 #else
449 avcodec_encode_video(c, buf + frame*zrq.size, MJPEG_SIZE, &picture);
450 #endif
451
452 if (ioctl(vdes, BUZIOC_QBUF_PLAY, &frame) < 0) 384 if (ioctl(vdes, BUZIOC_QBUF_PLAY, &frame) < 0)
453 mp_msg(MSGT_VO, MSGL_ERR, 385 mp_msg(MSGT_VO, MSGL_ERR,
454 "error queueing buffer for playback"); 386 "error queueing buffer for playback");
455 queue++; 387 queue++;
456 388
457 framenum++; 389 framenum++;
458 return; 390 return;
459 } 391 }
460 392
461 static uint32_t draw_frame(uint8_t * src[]) { 393 static uint32_t draw_frame(uint8_t * src[]) {
394 int i;
395 char *source, *dest;
396 //printf("draw frame called\n");
397 source = src[0] + 2*g.yoff*image_width + 2*g.xoff;
398 dest = image + 2*off_y;
399 for (i = 0; i < g.height/vdec; i++) {
400 memcpy(dest, source, image_width*2);
401 dest += 2*image_width;
402 source += vdec*stride;
403 }
462 return 0; 404 return 0;
463 } 405 }
464 406
465 static uint32_t query_format(uint32_t format) { 407 static uint32_t query_format(uint32_t format) {
466 if(format==IMGFMT_YV12) return 1; 408 if(format==IMGFMT_YV12) return 1;
409 if(format==IMGFMT_YUY2) return 1;
467 return 0; 410 return 0;
468 } 411 }
469 412
470 static void uninit(void) { 413 static void uninit(void) {
471 uninit_zoran(); 414 uninit_zoran();
472
473 #ifdef ZR_USES_LIBJPEG
474 jpeg_destroy_compress(&cinfo);
475 #else
476 avcodec_close(&codec_context);
477 #endif
478 } 415 }
479 416
480 static void check_events(void) { 417 static void check_events(void) {
481 } 418 }
482 419
526 dst+=image_width; 463 dst+=image_width;
527 } 464 }
528 src+=stride[0]; 465 src+=stride[0];
529 466
530 } 467 }
531 { 468 if (!bw) {
532 // copy U+V: 469 // copy U+V:
533 uint8_t *src1=srcimg[1]; 470 uint8_t *src1=srcimg[1];
534 uint8_t *src2=srcimg[2]; 471 uint8_t *src2=srcimg[2];
535 uint8_t *dst1=image + size + off_c+ (y/(vdec*2))*image_width/2+(x/2); 472 uint8_t *dst1=image + size + off_c+ (y/(vdec*2))*image_width/2+(x/2);
536 uint8_t *dst2=image + 3*size/2 + off_c + 473 uint8_t *dst2=image + 3*size/2 + off_c +
563 //aaopt_osdcolor=i; 500 //aaopt_osdcolor=i;
564 device = malloc(strlen(param)+1); 501 device = malloc(strlen(param)+1);
565 strcpy(device, param); 502 strcpy(device, param);
566 mp_msg(MSGT_VO, MSGL_V, "zr: using device %s\n", device); 503 mp_msg(MSGT_VO, MSGL_V, "zr: using device %s\n", device);
567 return 1; 504 return 1;
568 } else if (!strcasecmp(opt, "zrfi")) { 505 } else if (!strcasecmp(opt, "zrbw")) {
569 if (param != NULL) { 506 if (param != NULL) {
570 return ERR_OUT_OF_RANGE; 507 return ERR_OUT_OF_RANGE;
571 } 508 }
572 forceinter = 1; 509 bw = 1;
510 return 1;
511 } else if (!strcasecmp(opt, "zrfd")) {
512 if (param != NULL) {
513 return ERR_OUT_OF_RANGE;
514 }
515 zrfd = 1;
573 return 1; 516 return 1;
574 } else if (!strcasecmp(opt, "zrcrop")){ 517 } else if (!strcasecmp(opt, "zrcrop")){
575 if (param == NULL) return ERR_MISSING_PARAM; 518 if (param == NULL) return ERR_MISSING_PARAM;
576 if (sscanf(param, "%dx%d+%d+%d", &g.width, &g.height, 519 if (sscanf(param, "%dx%d+%d+%d", &g.width, &g.height,
577 &g.xoff, &g.yoff) != 4) { 520 &g.xoff, &g.yoff) != 4) {
582 } 525 }
583 } 526 }
584 g.set = 1; 527 g.set = 1;
585 mp_msg(MSGT_VO, MSGL_V, "zr: cropping %s\n", param); 528 mp_msg(MSGT_VO, MSGL_V, "zr: cropping %s\n", param);
586 return 1; 529 return 1;
530 }else if (!strcasecmp(opt, "zrhdec")) {
531 i = atoi(param);
532 if (i != 1 && i != 2 && i != 4) return ERR_OUT_OF_RANGE;
533 hdec = i;
534 return 1;
587 }else if (!strcasecmp(opt, "zrvdec")) { 535 }else if (!strcasecmp(opt, "zrvdec")) {
588 i = atoi(param); 536 i = atoi(param);
589 if (i != 1 && i != 2 && i != 4) return ERR_OUT_OF_RANGE; 537 if (i != 1 && i != 2 && i != 4) return ERR_OUT_OF_RANGE;
590 vdec = i; 538 vdec = i;
591 return 1; 539 return 1;
592 }else if (!strcasecmp(opt, "zrquality")) { 540 }else if (!strcasecmp(opt, "zrquality")) {
593 i = atoi(param); 541 i = atoi(param);
594 if (i < 30 || i > 100) return ERR_OUT_OF_RANGE; 542 if (i < 1 || i > 20) return ERR_OUT_OF_RANGE;
595 quality = i; 543 quality = i;
596 return 1; 544 return 1;
597 }else if (!strcasecmp(opt, "zrdct")) {
598 if (param == NULL) return ERR_MISSING_PARAM;
599 if (!strcasecmp(param, "IFAST")) {
600 jpegdct = JDCT_IFAST;
601 return 1;
602 } else if (!strcasecmp(param, "ISLOW")) {
603 jpegdct = JDCT_ISLOW;
604 return 1;
605 } else if (!strcasecmp(param, "FLOAT")) {
606 jpegdct = JDCT_FLOAT;
607 return 1;
608 } else {
609 return ERR_OUT_OF_RANGE;
610 }
611 }else if (!strcasecmp(opt, "zrnorm")) { 545 }else if (!strcasecmp(opt, "zrnorm")) {
612 if (param == NULL) return ERR_MISSING_PARAM; 546 if (param == NULL) return ERR_MISSING_PARAM;
613 if (!strcasecmp(param, "NTSC")) { 547 if (!strcasecmp(param, "NTSC")) {
614 mp_msg(MSGT_VO, MSGL_V, "zr: Norm set to NTSC\n"); 548 mp_msg(MSGT_VO, MSGL_V, "zr: Norm set to NTSC\n");
615 norm = VIDEO_MODE_NTSC; 549 norm = VIDEO_MODE_NTSC;
629 "\n" 563 "\n"
630 " -zrcrop specify part of the input image that\n" 564 " -zrcrop specify part of the input image that\n"
631 " you want to see as an x-style geometry string\n" 565 " you want to see as an x-style geometry string\n"
632 " example: -zrcrop 352x288+16+0\n" 566 " example: -zrcrop 352x288+16+0\n"
633 " -zrvdec vertical decimation 1, 2 or 4\n" 567 " -zrvdec vertical decimation 1, 2 or 4\n"
634 " -zrfi force interlacing ('wide screen')\n" 568 " -zrhdec horizontal decimation 1, 2 or 4\n"
635 " (by default we only interlace if the movie\n" 569 " -zrfd decimation is only done if the primitive\n"
636 " is higher than half of the screen height)\n" 570 " hardware upscaler can correct for the decimation,\n"
637 " -zrquality jpeg compression quality 30-100\n" 571 " this switch allows you to see the effects\n"
638 " -zrdct specify DCT method: IFAST, ISLOW or FLOAT\n" 572 " of too much decimation\n"
573 " -zrbw display in black&white (speed increase)\n"
574 " -zrquality jpeg compression quality [BEST] 1 - 20 [VERY BAD]\n"
639 " -zrdev playback device (example -zrdev /dev/video1\n" 575 " -zrdev playback device (example -zrdev /dev/video1\n"
640 " -zrnorm specify norm PAL/NTSC [dev: leave at current setting]\n" 576 " -zrnorm specify norm PAL/NTSC [dev: leave at current setting]\n"
641 "\n" 577 "\n"
642 ); 578 );
643 exit(0); 579 exit(0);
650 586
651 if (!strcasecmp(param, "zrdev")) { 587 if (!strcasecmp(param, "zrdev")) {
652 if(device) 588 if(device)
653 free(device); 589 free(device);
654 device=NULL; 590 device=NULL;
655 } else if (!strcasecmp(param, "zrfi")) 591 } else if (!strcasecmp(param, "zrbw"))
656 forceinter=0; 592 bw=0;
593 else if (!strcasecmp(param, "zrfd"))
594 zrfd=0;
657 else if (!strcasecmp(param, "zrcrop")) 595 else if (!strcasecmp(param, "zrcrop"))
658 g.set = g.xoff = g.yoff = 0; 596 g.set = g.xoff = g.yoff = 0;
597 else if (!strcasecmp(param, "zrhdec"))
598 hdec = 1;
659 else if (!strcasecmp(param, "zrvdec")) 599 else if (!strcasecmp(param, "zrvdec"))
660 vdec = 1; 600 vdec = 1;
661 else if (!strcasecmp(param, "zrquality")) 601 else if (!strcasecmp(param, "zrquality"))
662 quality = 70; 602 quality = 1;
663 else if (!strcasecmp(param, "zrdct"))
664 jpegdct = JDCT_IFAST;
665 else if (!strcasecmp(param, "zrnorm")) 603 else if (!strcasecmp(param, "zrnorm"))
666 norm = VIDEO_MODE_AUTO; 604 norm = VIDEO_MODE_AUTO;
667 605
668 } 606 }