vo_zr.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 827 行 · 第 1/2 页

C
827
字号
			zr->image = malloc(2*zr->size); /* this buffer allows for YUV422 data,					 * so it is a bit too big for YUV420 */		if (!zr->image) {			mp_msg(MSGT_VO, MSGL_ERR, "zr: Memory exhausted\n");			return 1;		}		/* and make sure that the borders are _really_ black */		switch (format) {			case IMGFMT_YV12:				memset(zr->image, 0, zr->size);				memset(zr->image + zr->size, 0x80, zr->size/4);				memset(zr->image + 3*zr->size/2, 0x80, zr->size/4);				zr->y_data = zr->image;				zr->u_data = zr->image + zr->size;				zr->v_data = zr->image + 3*zr->size/2;					zr->y_stride = zr->image_width;				zr->u_stride = zr->image_width/2;				zr->v_stride = zr->image_width/2;					zr->j = jpeg_enc_init(zr->image_width/zr->hdec, 						zr->image_height/zr->fields,						zr->hdec, zr->y_stride*zr->fields,						zr->hdec, zr->u_stride*zr->fields,						zr->hdec, zr->v_stride*zr->fields, 						1, zr->quality, zr->bw);				break;			case IMGFMT_YUY2:				for (tmp = 0; tmp < 2*zr->size; tmp+=4) {					zr->image[tmp] = 0;					zr->image[tmp+1] = 0x80;					zr->image[tmp+2] = 0;					zr->image[tmp+3] = 0x80;				}					zr->y_data = zr->image;				zr->u_data = zr->image + 1;				zr->v_data = zr->image + 3;					zr->y_stride = 2*zr->image_width;				zr->u_stride = 2*zr->image_width;				zr->v_stride = 2*zr->image_width;					zr->j = jpeg_enc_init(zr->image_width/zr->hdec, 						zr->image_height/zr->fields,						zr->hdec*2, 						zr->y_stride*zr->fields,						zr->hdec*4, 						zr->u_stride*zr->fields,						zr->hdec*4, 						zr->v_stride*zr->fields,						0, zr->quality, zr->bw);				break;			default:				mp_msg(MSGT_VO, MSGL_FATAL, "zr: internal inconsistency in vo_zr\n");		}				if (zr->j == NULL) {			mp_msg(MSGT_VO, MSGL_ERR, "zr: error initializing the jpeg encoder\n");			return 1;		}			if (init_zoran(zr, stretchx, stretchy)) {			return 1;		}		}	return 0;}static void draw_osd(void) {}static void flip_page (void) {	int i, j, k;	//FILE *fp;	//char filename[100];	/* do we have a free buffer? */	for (j = 0; j < zr_count; j++) {		zr_info_t *zr = &zr_info[j];		/* using MJPEG_NBUFFERS here, using the real number of 		 * buffers may give sync issues (real number of buffers		 * is always sufficient) */		if (zr->queue-zr->synco < MJPEG_NBUFFERS) {			zr->frame = zr->queue;		} else {			if (ioctl(zr->vdes, MJPIOC_SYNC, &zr->zs) < 0) 				mp_msg(MSGT_VO, MSGL_ERR, "zr: error waiting for buffers to become free\n"); 			zr->frame = zr->zs.frame;			zr->synco++;		}		k=0;		for (i = 0; i < zr->fields; i++) 			k+=jpeg_enc_frame(zr->j, zr->y_data + i*zr->y_stride, 					zr->u_data + i*zr->u_stride, 					zr->v_data + i*zr->v_stride, 					zr->buf + zr->frame*zr->zrq.size+k);		if (k > zr->zrq.size) mp_msg(MSGT_VO, MSGL_WARN, "zr: jpeg image too large for maximum buffer size. Lower the jpeg encoding\nquality or the resolution of the movie.\n");	}	/* Warning: Only the first jpeg image contains huffman- and 	 * quantisation tables, so don't expect files other than	 * test0001.jpg to be readable */	/*sprintf(filename, "test%04d.jpg", framenum);	fp = fopen(filename, "w");	if (!fp) exit(1);	fwrite(buf+frame*zrq.size, 1, k, fp);	fclose(fp);*/	/*fp = fopen("test1.jpg", "r");	fread(buf+frame*zrq.size, 1, 2126, fp);	fclose(fp);*/		for (j = 0; j < zr_count; j++) {		zr_info_t *zr = &zr_info[j];		if (ioctl(zr->vdes, MJPIOC_QBUF_PLAY, &zr->frame) < 0) 			mp_msg(MSGT_VO, MSGL_ERR, "zr: error queueing buffer for playback\n");		zr->queue++;	}	framenum++;	return;}static int draw_frame(uint8_t * src[]) {	int i, j;	char *source, *dest;	//printf("draw frame called\n");	for (j = 0; j < zr_count; j++) {		zr_info_t *zr = &zr_info[j];		geo_t *g = &zr->g;		source = src[0] + 2*g->yoff*zr->vdec*zr->stride + 2*g->xoff;		dest = zr->image + 2*zr->off_y;		for (i = 0; i < g->height/zr->vdec; i++) {			fast_memcpy(dest, source, zr->image_width*2);			dest += 2*zr->image_width;			source += zr->vdec*zr->stride;		}	}	return 0;}static int query_format(uint32_t format) {	if(format==IMGFMT_YV12 || format==IMGFMT_YUY2) 	    return VFCAP_CSP_SUPPORTED|VFCAP_CSP_SUPPORTED_BY_HW;	return 0;}static void uninit(void) {	int j;	mp_msg(MSGT_VO, MSGL_V, "zr: uninit called\n");	for (j = 0; j < zr_count; j++) {		jpeg_enc_uninit(zr_info[j].j);		uninit_zoran(&zr_info[j]);	}}static void check_events(void) {}static int draw_slice(uint8_t *srcimg[], int stride[],		int wf, int hf, int xf, int yf) {	int i, j, w, h, x, y;	/* Apply 'geometry', crop unwanted parts */	uint8_t *dst;	//printf("before: w=%d, h=%d, x=%d, y=%d, src0=%p, src1=%p, src2=%p\n", w, h, x, y, srcimg[0], srcimg[1], srcimg[2]);	for (j = 0; j < zr_count; j++) {		uint8_t *src=srcimg[0];		uint8_t *src1=srcimg[1];		uint8_t *src2=srcimg[2];		zr_info_t *zr = &zr_info[j];		geo_t *g = &zr->g;		w = wf; h = hf; x = xf; y = yf;		if (x < g->xoff) {			src += g->xoff - x;			src1 += (g->xoff - x)/2;			src2 += (g->xoff - x)/2;			w -= g->xoff - x;			if (w < 0) break; //return 0;			x = 0 /*g.xoff*/;		} else {			x -= g->xoff;		}		if (x + w > g->width) {			w = g->width - x;			if (w < 0) break; //return 0;		}		if (y < g->yoff) {			src += (g->yoff - y)*stride[0];			src1 += ((g->yoff - y)/2)*stride[1];			src2 += ((g->yoff - y)/2)*stride[2];			h -= g->yoff - y;			if (h < 0) break; //return 0;			y = 0;		} else {			y -= g->yoff;		}		if (y + h > g->height) {			h = g->height - y;			if (h < 0) break; //return 0;		}		//printf("after: w=%d, h=%d, x=%d, y=%d, src0=%p, src1=%p, src2=%p\n", w, h, x, y, srcimg[0], srcimg[1], srcimg[2]);		dst=zr->image + zr->off_y + zr->image_width*(y/zr->vdec)+x;		// copy Y:		for (i = 0; i < h; i++) {			if ((i + x)%zr->vdec == 0) {				fast_memcpy(dst,src,w);				dst+=zr->image_width;			}			src+=stride[0];		}		if (!zr->bw) {    			// copy U+V:			uint8_t *dst1=zr->image + zr->size + zr->off_c+ (y/(zr->vdec*2))*zr->image_width/2+(x/2);			uint8_t *dst2=zr->image + 3*zr->size/2 + zr->off_c + 					(y/(zr->vdec*2))*					zr->image_width/2+(x/2);			for (i = 0; i< h/2; i++) {				if ((i+x/2)%zr->vdec == 0) {					fast_memcpy(dst1,src1,w/2);					fast_memcpy(dst2,src2,w/2);					dst1+=zr->image_width/2;					dst2+=zr->image_width/2;				}				src1+=stride[1];				src2+=stride[2];			}    		}	} 	return 0;}/* copied and adapted from vo_aa_parseoption */intvo_zr_parseoption(m_option_t* conf, char *opt, char *param){    /* got an option starting with zr */    zr_info_t *zr = &zr_info[zr_parsing];    int i;    /* do WE need it ?, always */    if (!strcasecmp(opt, "zrdev")) {	if (param == NULL) return ERR_MISSING_PARAM;	//if ((i=getcolor(param))==-1) return ERR_OUT_OF_RANGE;	//aaopt_osdcolor=i;	free(zr->device);	zr->device = malloc(strlen(param)+1);	strcpy(zr->device, param);	mp_msg(MSGT_VO, MSGL_V, "zr: using device %s\n", zr->device);	return 1;    } else if (!strcasecmp(opt, "zrbw")) {	    if (param != NULL) {		    return ERR_OUT_OF_RANGE;	    }	    zr->bw = 1;	    return 1;    } else if (!strcasecmp(opt, "zrfd")) {	    if (param != NULL) {		    return ERR_OUT_OF_RANGE;	    }	    zr->fd = 1;	    return 1;    } else if (!strcasecmp(opt, "zrcrop")){        geo_t *g = &zr->g;	if (g->set == 1) {		zr_parsing++;		zr_count++;    		zr = &zr_info[zr_parsing];        	g = &zr->g;		if (zr_count > 4) {			mp_msg(MSGT_VO, MSGL_ERR, "zr: too many simultaneus display devices requested (max. is 4)\n");			return ERR_OUT_OF_RANGE;		}	}	if (param == NULL) return ERR_MISSING_PARAM;	if (sscanf(param, "%dx%d+%d+%d", &g->width, &g->height, 				&g->xoff, &g->yoff) != 4) {		g->xoff = 0; g->yoff = 0;		if (sscanf(param, "%dx%d", &g->width, &g->height) != 2) {			mp_msg(MSGT_VO, MSGL_ERR, "zr: argument to -zrcrop must be of the form 352x288+16+0\n");			return ERR_OUT_OF_RANGE;		}	}	g->set = 1;	mp_msg(MSGT_VO, MSGL_V, "zr: cropping %s\n", param);	return 1;    }else if (!strcasecmp(opt, "zrhdec")) {        i = atoi(param);	if (i != 1 && i != 2 && i != 4) return ERR_OUT_OF_RANGE;	zr->hdec = i;	return 1;    }else if (!strcasecmp(opt, "zrvdec")) {        i = atoi(param);	if (i != 1 && i != 2 && i != 4) return ERR_OUT_OF_RANGE;	zr->vdec = i;	return 1;    }else if (!strcasecmp(opt, "zrxdoff")) {        i = atoi(param);	zr->xdoff = i;	return 1;    }else if (!strcasecmp(opt, "zrydoff")) {        i = atoi(param);	zr->ydoff = i;	return 1;    }else if (!strcasecmp(opt, "zrquality")) {        i = atoi(param);	if (i < 1 || i > 20) return ERR_OUT_OF_RANGE;	zr->quality = i;	return 1;    }else if (!strcasecmp(opt, "zrnorm")) {	if (param == NULL) return ERR_MISSING_PARAM;	if (!strcasecmp(param, "NTSC")) {            mp_msg(MSGT_VO, MSGL_V, "zr: Norm set to NTSC\n");            zr->norm = VIDEO_MODE_NTSC;	    return 1;	} else if (!strcasecmp(param, "PAL")) {	    mp_msg(MSGT_VO, MSGL_V, "zr: Norm set to PAL\n");            zr->norm = VIDEO_MODE_PAL;	    return 1;	} else {           return ERR_OUT_OF_RANGE;        }    }else if (!strcasecmp(opt, "zrhelp")){	printf("Help for -vo zr: Zoran ZR360[56]7/ZR36060 based MJPEG capture/playback cards\n");	printf("\n");	printf("Here are the zr options:\n");	printf(		    "\n"		    "  -zrcrop     specify part of the input image that\n"		    "              you want to see as an x-style geometry string\n"		    "              example: -zrcrop 352x288+16+0\n"		    "  -zrvdec     vertical decimation 1, 2 or 4\n"		    "  -zrhdec     horizontal decimation 1, 2 or 4\n"		    "  -zrfd       decimation is only done if the primitive\n"		    "              hardware upscaler can correct for the decimation,\n"		    "              this switch allows you to see the effects\n"		    "              of too much decimation\n"		    "  -zrbw       display in black&white (speed increase)\n"		    "  -zrxdoff    x offset from upper-left of TV screen (default is 'centered')\n"		    "  -zrydoff    y offset from upper-left of TV screen (default is 'centered')\n"		    "  -zrquality  jpeg compression quality [BEST] 1 - 20 [VERY BAD]\n"		    "  -zrdev      playback device (example -zrdev /dev/video1)\n"		    "  -zrnorm     specify norm PAL/NTSC (default: leave at current setting)\n"		    "\n"		    "Cinerama support: additional occurances of -zrcrop activate cinerama mode,\n"		    "suppose you have a 704x272 movie, two DC10+ cards and two beamers (or tv's),\n"              		    "then you would issue the following command:\n\n"		    "mplayer -vo zr -zrcrop 352x272+0+0 -zrdev /dev/video0 -zrcrop 352x272+352+0 \\\n"		    "       -zrdev /dev/video1 movie.avi\n\n"		    "Options appearing after the second -zrcrop apply to the second card, it is\n"		    "possible to dispay at a different jpeg quality or at different decimations.\n\n"		    "The parameters -zrxdoff and -zrydoff can be used to align the two images.\n"		    "The maximum number of zoran cards participating in cinerama is 4, so you can\n"		    "build a 2x2 vidiwall. (untested for obvious reasons, the setup wit a buz and\n"		    "a DC10+ (and no beamers) is tested, however)\n"	      );	exit(0);		    }    return ERR_NOT_AN_OPTION;}void vo_zr_revertoption(m_option_t* opt,char* param) {  zr_info_t *zr = &zr_info[1];  zr_count = 1;  zr_parsing = 0;  if (!strcasecmp(param, "zrdev")) {    if(zr->device)      free(zr->device);    zr->device=NULL;  } else if (!strcasecmp(param, "zrbw"))    zr->bw=0;  else if (!strcasecmp(param, "zrfd"))    zr->fd=0;  else if (!strcasecmp(param, "zrcrop"))    zr->g.set = zr->g.xoff = zr->g.yoff = 0;  else if (!strcasecmp(param, "zrhdec"))    zr->hdec = 1;  else if (!strcasecmp(param, "zrvdec"))    zr->vdec = 1;  else if (!strcasecmp(param, "zrxdoff"))    zr->xdoff = -1;  else if (!strcasecmp(param, "zrydoff"))    zr->ydoff = -1;  else if (!strcasecmp(param, "zrquality"))    zr->quality = 2;  else if (!strcasecmp(param, "zrnorm"))    zr->norm = VIDEO_MODE_AUTO;}static int preinit(const char *arg){    if(arg)     {	printf("vo_zr: Unknown subdevice: %s\n",arg);	return ENOSYS;    }    return 0;}static int control(uint32_t request, void *data, ...){  switch (request) {  case VOCTRL_QUERY_FORMAT:    return query_format(*((uint32_t*)data));  }  return VO_NOTIMPL;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?