コード例 #1
0
static int config(uint32_t width, uint32_t height, uint32_t d_width,
	uint32_t d_height, uint32_t flags, char *title, uint32_t format)
{
	int i, tmp, stretchx, stretchy;
	framenum = 0;
	if (format != IMGFMT_YV12 && format != IMGFMT_YUY2) {
		printf("vo_zr called with wrong format");
		return 1;
	}
	for (i = 0; i < zr_count; i++) {
		zr_info_t *zr = &zr_info[i];
		geo_t *g = &zr->g;

		zr->stride = 2*width;
		if (zr_geometry_sane(g, width, height)) return 1;

		/* we must know the maximum resolution of the device
	 	 * it differs for DC10+ and buz for example */
		zoran_getcap(zr); /*must be called before init_zoran */
		/* make the scaling decision
		 * we are capable of stretching the image in the horizontal
		 * direction by factors 1, 2 and 4
		 * we can stretch the image in the vertical direction by a
		 * factor of 1 and 2 AND we must decide about interlacing */
		if (g->width > zr->vc.maxwidth/2 ||
				g->height > zr->vc.maxheight/2) {
			stretchx = 1;
			stretchy = 1;
			zr->fields = 2;
			if (zr->vdec == 2) {
				zr->fields = 1;
			} else if (zr->vdec == 4) {
				zr->fields = 1;
				stretchy = 2;
			}
			stretchx = zr->hdec;
		} else if (g->width > zr->vc.maxwidth/4 ||
				g->height > zr->vc.maxheight/4) {
			stretchx = 2;
			stretchy = 1;
			zr->fields = 1;
			if (zr->vdec == 2) {
				stretchy = 2;
			} else if (zr->vdec == 4) {
				if (!zr->fd) {
					mp_msg(MSGT_VO, MSGL_WARN, "zr: vertical decimation too high, changing to 2 (use -zrfd to keep vdec=4)\n");
					zr->vdec = 2;
				}
				stretchy = 2;
			}
			if (zr->hdec == 2) {
				stretchx = 4;
			} else if (zr->hdec == 4){
				if (!zr->fd) {
					mp_msg(MSGT_VO, MSGL_WARN, "zr: horizontal decimation too high, changing to 2 (use -zrfd to keep hdec=4)\n");
					zr->hdec = 2;
				}
				stretchx = 4;
			}
		} else {
			/* output image is maximally stretched */
			stretchx = 4;
			stretchy = 2;
			zr->fields = 1;
			if (zr->vdec != 1 && !zr->fd) {
				mp_msg(MSGT_VO, MSGL_WARN, "zr: vertical decimation too high, changing to 1 (use -zrfd to keep vdec=%d)\n", zr->vdec);
				zr->vdec = 1;
			}
			if (zr->hdec != 1 && !zr->fd) {
				mp_msg(MSGT_VO, MSGL_WARN, "zr: vertical decimation too high, changing to 1 (use -zrfd to keep hdec=%d)\n", zr->hdec);
				zr->hdec = 1;
			}
		}
		/* It can be that the original frame was too big for display,
		 * or that the width of the decimated image (for example) after
		 * padding up to a multiple of 16 has become too big. (orig
		 * width 720 (exactly right for the Buz) after decimation 360,
		 * after padding up to a multiple of 16 368, display 736 -> too
		 * large). In these situations we auto(re)crop. */
		tmp = 16*((g->width - 1)/(zr->hdec*16) + 1);
		if (stretchx*tmp > zr->vc.maxwidth) {
			g->xoff += 2*((g->width - zr->hdec*(tmp-16))/4);
			/* g->off must be a multiple of 2 */
			g->width = zr->hdec*(tmp - 16);
			g->set = 0; /* we abuse this field to
				       report that g has changed*/
		}
		tmp = 8*zr->fields*((g->height - 1)/(zr->vdec*zr->fields*8)+1);
		if (stretchy*tmp > zr->vc.maxheight) {
			g->yoff += 2*((g->height - zr->vdec*
						(tmp - 8*zr->fields))/4);
			g->height = zr->vdec*(tmp - 8*zr->fields);
			g->set = 0;
		}
		if (!g->set)
			mp_msg(MSGT_VO, MSGL_V, "zr: auto(re)cropping %dx%d+%d+%d to make the image fit on the screen\n", g->width, g->height, g->xoff, g->yoff);

		/* the height must be a multiple of fields*8 and the width
		 * must be a multiple of 16 */
		/* add some black borders to make it so, and center the image*/
		zr->image_height = zr->fields*8*((g->height/zr->vdec - 1)/
				(zr->fields*8) + 1);
		zr->image_width = (zr->hdec*16)*((g->width - 1)/(zr->hdec*16) + 1);
		zr->off_y = (zr->image_height - g->height/zr->vdec)/2;
		if (zr->off_y%2 != 0) zr->off_y++;
		zr->off_y *= zr->image_width;
		zr->off_c = zr->off_y/4;
		zr->off_y += (zr->image_width - g->width)/2;
		if (zr->off_y%2 != 0) zr->off_y--;
		zr->off_c += (zr->image_width - g->width)/4;
		zr->size = zr->image_width*zr->image_height;
		mp_msg(MSGT_VO, MSGL_V, "zr: input: %dx%d, cropped: %dx%d, output: %dx%d, off_y=%d, off_c=%d\n", width, height, g->width, g->height, zr->image_width, zr->image_height, zr->off_y, zr->off_c);

		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;
}
コード例 #2
0
ファイル: vf_zrmjpeg.c プロジェクト: jlelli/mplayer-dl
/**
 * \param vf video filter instance pointer
 * \param width image source width in pixels
 * \param height image source height in pixels
 * \param d_width width of requested window, just a hint
 * \param d_height height of requested window, just a hint
 * \param flags vf filter flags
 * \param outfmt
 *
 * \returns returns 0 on error
 *
 * This routine will make the necessary hardware-related decisions for
 * the ZRMJPEG filter, do the initialization of the MJPEG encoder, and
 * then select one of the ZRJMJPEGIT or ZRMJPEGNI filters and then
 * arrange to dispatch to the config() entry pointer for the one
 * selected.
 */
static int config(struct vf_instance *vf, int width, int height, int d_width,
		int d_height, unsigned int flags, unsigned int outfmt){
	struct vf_priv_s *priv = vf->priv;
	float aspect_decision;
	int stretchx, stretchy, err = 0, maxstretchx = 4;
	priv->fields = 1;

	VERBOSE("config() called\n");

	if (priv->j) {
		VERBOSE("re-configuring, resetting JPEG encoder\n");
		jpeg_enc_uninit(priv->j);
		priv->j = NULL;
	}

	aspect_decision = ((float)d_width/(float)d_height)/
		((float)width/(float)height);

	if (aspect_decision > 1.8 && aspect_decision < 2.2) {
		VERBOSE("should correct aspect by stretching x times 2, %d %d\n", 2*width, priv->maxwidth);
		if (2*width <= priv->maxwidth) {
			d_width = 2*width;
			d_height = height;
			maxstretchx = 2;
		} else {
			WARNING("unable to correct aspect by stretching, because resulting X will be too large, aspect correction by decimating y not yet implemented\n");
			d_width = width;
			d_height = height;
		}
		/* prestretch movie */
	} else {
		/* uncorrecting output for now */
		d_width = width;
		d_height = height;
	}
	/* make the scaling decision
	 * we are capable of stretching the image in the horizontal
	 * direction by factors 1, 2 and 4
	 * we can stretch the image in the vertical direction by a
	 * factor of 1 and 2 AND we must decide about interlacing */
	if (d_width > priv->maxwidth/2 || height > priv->maxheight/2
			|| maxstretchx == 1) {
		stretchx = 1;
		stretchy = 1;
		priv->fields = 2;
		if (priv->vdec == 2) {
			priv->fields = 1;
		} else if (priv->vdec == 4) {
			priv->fields = 1;
			stretchy = 2;
		}
		if (priv->hdec > maxstretchx) {
			if (priv->fd) {
				WARNING("horizontal decimation too high, "
						"changing to %d (use fd to keep"
						" hdec=%d)\n",
						maxstretchx, priv->hdec);
				priv->hdec = maxstretchx;
			}
		}
		stretchx = priv->hdec;
	} else if (d_width > priv->maxwidth/4 ||
			height > priv->maxheight/4 ||
			maxstretchx == 2) {
		stretchx = 2;
		stretchy = 1;
		priv->fields = 1;
		if (priv->vdec == 2) {
			stretchy = 2;
		} else if (priv->vdec == 4) {
			if (!priv->fd) {
				WARNING("vertical decimation too high, "
						"changing to 2 (use fd to keep "
						"vdec=4)\n");
				priv->vdec = 2;
			}
			stretchy = 2;
		}
		if (priv->hdec == 2) {
			stretchx = 4;
		} else if (priv->hdec == 4) {
			if (priv->fd) {
				WARNING("horizontal decimation too high, "
						"changing to 2 (use fd to keep "
						"hdec=4)\n");
				priv->hdec = 2;
			}
			stretchx = 4;
		}
	} else {
		/* output image is maximally stretched */
		stretchx = 4;
		stretchy = 2;
		priv->fields = 1;
		if (priv->vdec != 1 && !priv->fd) {
			WARNING("vertical decimation too high, changing to 1 "
					"(use fd to keep vdec=%d)\n",
					priv->vdec);
			priv->vdec = 1;
		}
		if (priv->hdec != 1 && !priv->fd) {
			WARNING("horizontal decimation too high, changing to 1 (use fd to keep hdec=%d)\n", priv->hdec);
			priv->hdec = 1;
		}
	}

	VERBOSE("generated JPEG's %dx%s%d%s, stretched to %dx%d\n",
			width/priv->hdec, (priv->fields == 2) ? "(" : "",
			height/(priv->vdec*priv->fields),
			(priv->fields == 2) ? "x2)" : "",
			(width/priv->hdec)*stretchx,
			(height/(priv->vdec*priv->fields))*
			stretchy*priv->fields);


	if ((width/priv->hdec)*stretchx > priv->maxwidth ||
			(height/(priv->vdec*priv->fields))*
			 stretchy*priv->fields  > priv->maxheight) {
		ERROR("output dimensions too large (%dx%d), max (%dx%d) "
				"insert crop to fix\n",
				(width/priv->hdec)*stretchx,
				(height/(priv->vdec*priv->fields))*
				stretchy*priv->fields,
				priv->maxwidth, priv->maxheight);
		err = 1;
	}

	if (width%(16*priv->hdec) != 0) {
		ERROR("width must be a multiple of 16*hdec (%d), use expand\n",
				priv->hdec*16);
		err = 1;
	}

	if (height%(8*priv->fields*priv->vdec) != 0) {
		ERROR("height must be a multiple of 8*fields*vdec (%d),"
				" use expand\n", priv->vdec*priv->fields*8);
		err = 1;
	}

	if (err) return 0;

	priv->y_stride = width;
	priv->c_stride = width/2;
	priv->j = jpeg_enc_init(width, height/priv->fields,
				priv->fields*priv->y_stride,
				priv->fields*priv->c_stride,
				priv->fields*priv->c_stride,
				1, priv->quality, priv->bw);

	if (!priv->j) return 0;
	return vf_next_config(vf, width, height, d_width, d_height, flags,
		(priv->fields == 2) ? IMGFMT_ZRMJPEGIT : IMGFMT_ZRMJPEGNI);
}