663 lines
20 KiB
Plaintext
663 lines
20 KiB
Plaintext
$OpenBSD: patch-ffmpeg_frame_c,v 1.3 2009/08/17 01:40:30 jolan Exp $
|
|
--- ffmpeg_frame.c.orig Mon Oct 13 18:02:01 2008
|
|
+++ ffmpeg_frame.c Sun Aug 16 20:01:01 2009
|
|
@@ -31,7 +31,7 @@
|
|
obligated to do so. If you do not wish to do so, delete this exception
|
|
statement from your version.
|
|
|
|
- */
|
|
+*/
|
|
|
|
#include "php.h"
|
|
#include "php_ini.h"
|
|
@@ -51,7 +51,7 @@
|
|
include gd header from local include dir. This is a copy of gd.h that is
|
|
distributed with php-5.2.5. It is distributed along with ffmpeg-php to
|
|
allow ffmpeg-php to be built without access to the php sources
|
|
- */
|
|
+ */
|
|
#if HAVE_LIBGD20
|
|
#include "gd.h"
|
|
|
|
@@ -64,7 +64,7 @@
|
|
#define gdImageBoundsSafeMacro(im, x, y) (!((((y) < (im)->cy1) || ((y) > (im)->cy2)) || (((x) < (im)->cx1) || ((x) > (im)->cx2))))
|
|
|
|
static int le_gd; // this is only valid after calling
|
|
- // FFMPEG_PHP_FETCH_IMAGE_RESOURCE()
|
|
+// FFMPEG_PHP_FETCH_IMAGE_RESOURCE()
|
|
|
|
#endif // HAVE_LIBGD20
|
|
|
|
@@ -72,39 +72,40 @@ int le_ffmpeg_frame; // not static since it is used in
|
|
|
|
static zend_class_entry *ffmpeg_frame_class_entry_ptr;
|
|
zend_class_entry ffmpeg_frame_class_entry;
|
|
-
|
|
+
|
|
/* {{{ ffmpeg_frame methods[]
|
|
- Methods of the ffmpeg_frame class
|
|
-*/
|
|
+ Methods of the ffmpeg_frame class
|
|
+ */
|
|
zend_function_entry ffmpeg_frame_class_methods[] = {
|
|
-
|
|
+
|
|
/* object can't be created from user space so no PHP constructor */
|
|
//PHP_ME(ffmpeg_frame, __construct, NULL, 0)
|
|
-
|
|
+
|
|
#if HAVE_LIBGD20
|
|
/* gd methods */
|
|
- PHP_MALIAS(ffmpeg_frame, togdimage, toGDImage, NULL, 0)
|
|
+ FFMPEG_PHP_MALIAS(ffmpeg_frame, togdimage, toGDImage, NULL, 0)
|
|
#endif // HAVE_LIBGD20
|
|
|
|
- /* methods */
|
|
- PHP_MALIAS(ffmpeg_frame, getwidth, getWidth, NULL, 0)
|
|
- PHP_MALIAS(ffmpeg_frame, getheight, getHeight, NULL, 0)
|
|
- PHP_MALIAS(ffmpeg_frame, iskeyframe, isKeyFrame, NULL, 0)
|
|
- PHP_MALIAS(ffmpeg_frame, getpresentationtimestamp, getPresentationTimestamp, NULL, 0)
|
|
- PHP_MALIAS(ffmpeg_frame, getpts, getPresentationTimestamp, NULL, 0)
|
|
- {NULL, NULL, NULL}
|
|
+ /* methods */
|
|
+ FFMPEG_PHP_MALIAS(ffmpeg_frame, getwidth, getWidth, NULL, 0)
|
|
+ FFMPEG_PHP_MALIAS(ffmpeg_frame, getheight, getHeight, NULL, 0)
|
|
+ FFMPEG_PHP_MALIAS(ffmpeg_frame, resize, resize, NULL, 0)
|
|
+ FFMPEG_PHP_MALIAS(ffmpeg_frame, iskeyframe, isKeyFrame, NULL, 0)
|
|
+ FFMPEG_PHP_MALIAS(ffmpeg_frame, getpresentationtimestamp, getPresentationTimestamp, NULL, 0)
|
|
+ FFMPEG_PHP_MALIAS(ffmpeg_frame, getpts, getPresentationTimestamp, NULL, 0)
|
|
+ FFMPEG_PHP_END_METHODS
|
|
};
|
|
/* }}} */
|
|
|
|
|
|
/* {{{ _php_alloc_ff_frame()
|
|
- */
|
|
+*/
|
|
static ff_frame_context* _php_alloc_ff_frame()
|
|
{
|
|
ff_frame_context *ff_frame = NULL;
|
|
|
|
ff_frame = emalloc(sizeof(ff_frame_context));
|
|
-
|
|
+
|
|
if (!ff_frame) {
|
|
zend_error(E_ERROR, "Error allocating ffmpeg_frame");
|
|
}
|
|
@@ -123,16 +124,16 @@ static ff_frame_context* _php_alloc_ff_frame()
|
|
creates an ffmpeg_frame object, adds a ffmpeg_frame resource to the
|
|
object, registers the resource and returns a direct pointer to the
|
|
resource.
|
|
- */
|
|
+ */
|
|
ff_frame_context* _php_create_ffmpeg_frame(INTERNAL_FUNCTION_PARAMETERS)
|
|
{
|
|
int ret;
|
|
- ff_frame_context *ff_frame;
|
|
-
|
|
+ ff_frame_context *ff_frame;
|
|
+
|
|
ff_frame = _php_alloc_ff_frame();
|
|
-
|
|
- ret = ZEND_REGISTER_RESOURCE(NULL, ff_frame, le_ffmpeg_frame);
|
|
-
|
|
+
|
|
+ ret = ZEND_REGISTER_RESOURCE(NULL, ff_frame, le_ffmpeg_frame);
|
|
+
|
|
object_init_ex(return_value, ffmpeg_frame_class_entry_ptr);
|
|
add_property_resource(return_value, "ffmpeg_frame", ret);
|
|
return ff_frame;
|
|
@@ -141,7 +142,7 @@ ff_frame_context* _php_create_ffmpeg_frame(INTERNAL_FU
|
|
|
|
|
|
/* {{{ _php_free_av_frame()
|
|
- */
|
|
+*/
|
|
static void _php_free_av_frame(AVFrame *av_frame)
|
|
{
|
|
if (av_frame) {
|
|
@@ -156,7 +157,7 @@ static void _php_free_av_frame(AVFrame *av_frame)
|
|
|
|
|
|
/* {{{ _php_free_ffmpeg_frame()
|
|
- */
|
|
+*/
|
|
static void _php_free_ffmpeg_frame(zend_rsrc_list_entry *rsrc TSRMLS_DC)
|
|
{
|
|
ff_frame_context *ff_frame = (ff_frame_context*)rsrc->ptr;
|
|
@@ -167,7 +168,7 @@ static void _php_free_ffmpeg_frame(zend_rsrc_list_entr
|
|
|
|
|
|
/* {{{ register_ffmpeg_frame_class()
|
|
- */
|
|
+*/
|
|
void register_ffmpeg_frame_class(int module_number)
|
|
{
|
|
TSRMLS_FETCH();
|
|
@@ -187,36 +188,33 @@ void register_ffmpeg_frame_class(int module_number)
|
|
|
|
/* {{{ _php_convert_frame()
|
|
*/
|
|
-int _php_convert_frame(ff_frame_context *ff_frame_ctx, int dst_fmt) {
|
|
- AVFrame *src_frame;
|
|
+int _php_convert_frame(ff_frame_context *ff_frame, int dst_fmt) {
|
|
AVFrame *dst_frame;
|
|
int result = 0;
|
|
|
|
- if (!ff_frame_ctx->av_frame) {
|
|
+ if (!ff_frame->av_frame) {
|
|
return -1;
|
|
}
|
|
|
|
- src_frame = ff_frame_ctx->av_frame;
|
|
+ if (dst_fmt == ff_frame->pixel_format) {
|
|
+ return 0; // NOP
|
|
+ }
|
|
|
|
dst_frame = avcodec_alloc_frame();
|
|
- avpicture_alloc((AVPicture*)dst_frame, dst_fmt, ff_frame_ctx->width,
|
|
- ff_frame_ctx->height);
|
|
+ avpicture_alloc((AVPicture*)dst_frame, dst_fmt, ff_frame->width,
|
|
+ ff_frame->height);
|
|
|
|
- result = ffmpeg_img_convert((AVPicture*)dst_frame, dst_fmt,
|
|
- (AVPicture *)src_frame,
|
|
- ff_frame_ctx->pixel_format, ff_frame_ctx->width,
|
|
- ff_frame_ctx->height);
|
|
+ result = phpimg_convert( (AVPicture *)dst_frame, dst_fmt,
|
|
+ (AVPicture *) ff_frame->av_frame, ff_frame->pixel_format, ff_frame->width, ff_frame->height);
|
|
|
|
if (result) {
|
|
zend_error(E_ERROR, "Error converting frame");
|
|
- goto fail;
|
|
+ _php_free_av_frame(dst_frame);
|
|
+ } else {
|
|
+ ff_frame->av_frame = dst_frame;
|
|
+ ff_frame->pixel_format = dst_fmt;
|
|
}
|
|
|
|
- ff_frame_ctx->av_frame = dst_frame;
|
|
- ff_frame_ctx->pixel_format = dst_fmt;
|
|
-
|
|
-fail:
|
|
- _php_free_av_frame(src_frame);
|
|
return result;
|
|
}
|
|
/* }}} */
|
|
@@ -224,7 +222,7 @@ fail:
|
|
#if HAVE_LIBGD20
|
|
|
|
/* {{{ _php_get_gd_image()
|
|
- */
|
|
+*/
|
|
static int _php_get_gd_image(int w, int h)
|
|
{
|
|
zval *function_name, *width, *height;
|
|
@@ -234,7 +232,7 @@ static int _php_get_gd_image(int w, int h)
|
|
char *function_cname = "imagecreatetruecolor";
|
|
int ret;
|
|
TSRMLS_FETCH();
|
|
-
|
|
+
|
|
if (zend_hash_find(EG(function_table), function_cname,
|
|
strlen(function_cname) + 1, (void **)&func) == FAILURE) {
|
|
zend_error(E_ERROR, "Error can't find %s function", function_cname);
|
|
@@ -255,11 +253,11 @@ static int _php_get_gd_image(int w, int h)
|
|
&retval, 2, argv, 0, NULL TSRMLS_CC) == FAILURE) {
|
|
zend_error(E_ERROR, "Error calling %s function", function_cname);
|
|
}
|
|
-
|
|
+
|
|
FREE_ZVAL(function_name);
|
|
FREE_ZVAL(width);
|
|
FREE_ZVAL(height);
|
|
-
|
|
+
|
|
if (!retval || retval->type != IS_RESOURCE) {
|
|
php_error_docref(NULL TSRMLS_CC, E_ERROR,
|
|
"Error creating GD Image");
|
|
@@ -277,7 +275,7 @@ static int _php_get_gd_image(int w, int h)
|
|
|
|
|
|
/* {{{ _php_avframe_to_gd_image()
|
|
- */
|
|
+*/
|
|
static int _php_avframe_to_gd_image(AVFrame *frame, gdImage *dest, int width,
|
|
int height)
|
|
{
|
|
@@ -286,13 +284,8 @@ static int _php_avframe_to_gd_image(AVFrame *frame, gd
|
|
|
|
for (y = 0; y < height; y++) {
|
|
for (x = 0; x < width; x++) {
|
|
-
|
|
- if (gdImageBoundsSafeMacro(dest, x, y)) {
|
|
- /* copy pixel to gdimage buffer zeroing the alpha channel */
|
|
- dest->tpixels[y][x] = src[x] & 0x00ffffff;
|
|
- } else {
|
|
- return -1;
|
|
- }
|
|
+ /* copy pixel to gdimage buffer zeroing the alpha channel */
|
|
+ dest->tpixels[y][x] = src[x] & 0x00ffffff;
|
|
}
|
|
src += width;
|
|
}
|
|
@@ -302,7 +295,7 @@ static int _php_avframe_to_gd_image(AVFrame *frame, gd
|
|
|
|
|
|
/* {{{ _php_gd_image_to_avframe()
|
|
- */
|
|
+*/
|
|
static int _php_gd_image_to_avframe(gdImage *src, AVFrame *frame, int width,
|
|
int height)
|
|
{
|
|
@@ -325,7 +318,7 @@ static int _php_gd_image_to_avframe(gdImage *src, AVFr
|
|
|
|
|
|
/* {{{ proto resource toGDImage()
|
|
- */
|
|
+*/
|
|
FFMPEG_PHP_METHOD(ffmpeg_frame, toGDImage)
|
|
{
|
|
ff_frame_context *ff_frame;
|
|
@@ -333,7 +326,7 @@ FFMPEG_PHP_METHOD(ffmpeg_frame, toGDImage)
|
|
|
|
GET_FRAME_RESOURCE(getThis(), ff_frame);
|
|
|
|
- _php_convert_frame(ff_frame, PIX_FMT_RGBA32);
|
|
+ _php_convert_frame(ff_frame, PIX_FMT_RGB32);
|
|
|
|
return_value->value.lval = _php_get_gd_image(ff_frame->width,
|
|
ff_frame->height);
|
|
@@ -343,36 +336,15 @@ FFMPEG_PHP_METHOD(ffmpeg_frame, toGDImage)
|
|
FFMPEG_PHP_FETCH_IMAGE_RESOURCE(gd_img, &return_value);
|
|
|
|
if (_php_avframe_to_gd_image(ff_frame->av_frame, gd_img,
|
|
- ff_frame->width, ff_frame->height)) {
|
|
+ ff_frame->width, ff_frame->height)) {
|
|
zend_error(E_ERROR, "failed to convert frame to gd image");
|
|
}
|
|
}
|
|
/* }}} */
|
|
|
|
|
|
-/* {{{ proto object _php_read_frame_from_file(mixed)
|
|
- */
|
|
-/*_php_read_frame_from_file(ff_frame_context *ff_frame, char* filename)
|
|
-{
|
|
- AVFrame *frame = NULL;
|
|
- AVFormatContext *ic;
|
|
- AVFormatParameters *ap;
|
|
- int err;
|
|
-
|
|
- // open the input file with generic libav function
|
|
- err = av_open_input_file(&ic, filename, NULL, 0, ap);
|
|
- if (err < 0) {
|
|
- zend_error(E_ERROR, "Can't open image file %d, %d", err,
|
|
- AVERROR_NOFMT);
|
|
- }
|
|
-
|
|
-
|
|
-}*/
|
|
-/* }}} */
|
|
-
|
|
-
|
|
/* {{{ proto object ffmpeg_frame(mixed)
|
|
- */
|
|
+*/
|
|
FFMPEG_PHP_METHOD(ffmpeg_frame, ffmpeg_frame)
|
|
{
|
|
zval **argv[1];
|
|
@@ -392,17 +364,17 @@ FFMPEG_PHP_METHOD(ffmpeg_frame, ffmpeg_frame)
|
|
}
|
|
|
|
ff_frame = _php_alloc_ff_frame();
|
|
-
|
|
- ret = ZEND_REGISTER_RESOURCE(NULL, ff_frame, le_ffmpeg_frame);
|
|
-
|
|
+
|
|
+ ret = ZEND_REGISTER_RESOURCE(NULL, ff_frame, le_ffmpeg_frame);
|
|
+
|
|
object_init_ex(getThis(), ffmpeg_frame_class_entry_ptr);
|
|
add_property_resource(getThis(), "ffmpeg_frame", ret);
|
|
-
|
|
+
|
|
switch (Z_TYPE_PP(argv[0])) {
|
|
case IS_STRING:
|
|
convert_to_string_ex(argv[0]);
|
|
zend_error(E_ERROR,
|
|
- "Creating an ffmpeg_frame from a file is not implemented\n");
|
|
+ "Creating an ffmpeg_frame from a file is not implemented\n");
|
|
//_php_read_frame_from_file(ff_frame, Z_STRVAL_PP(argv[0]));
|
|
break;
|
|
case IS_RESOURCE:
|
|
@@ -418,18 +390,18 @@ FFMPEG_PHP_METHOD(ffmpeg_frame, ffmpeg_frame)
|
|
|
|
/* create a an av_frame and allocate space for it */
|
|
frame = avcodec_alloc_frame();
|
|
- avpicture_alloc((AVPicture*)frame, PIX_FMT_RGBA32, width, height);
|
|
+ avpicture_alloc((AVPicture*)frame, PIX_FMT_RGB32, width, height);
|
|
|
|
/* copy the gd image to the av_frame */
|
|
_php_gd_image_to_avframe(gd_img, frame, width, height);
|
|
-
|
|
+
|
|
/* set the ffmepg_frame to point to this av_frame */
|
|
ff_frame->av_frame = frame;
|
|
-
|
|
+
|
|
/* set the ffpmeg_frame's properties */
|
|
ff_frame->width = width;
|
|
ff_frame->height = height;
|
|
- ff_frame->pixel_format = PIX_FMT_RGBA32;
|
|
+ ff_frame->pixel_format = PIX_FMT_RGB32;
|
|
break;
|
|
default:
|
|
zend_error(E_ERROR, "Invalid argument\n");
|
|
@@ -441,53 +413,298 @@ FFMPEG_PHP_METHOD(ffmpeg_frame, ffmpeg_frame)
|
|
|
|
|
|
/* {{{ proto int getPresentationTimestamp()
|
|
- */
|
|
+*/
|
|
FFMPEG_PHP_METHOD(ffmpeg_frame, getPresentationTimestamp)
|
|
{
|
|
ff_frame_context *ff_frame;
|
|
|
|
GET_FRAME_RESOURCE(getThis(), ff_frame);
|
|
-
|
|
+
|
|
RETURN_DOUBLE((double)ff_frame->pts / AV_TIME_BASE);
|
|
}
|
|
/* }}} */
|
|
|
|
|
|
/* {{{ proto int isKeyFrame()
|
|
- */
|
|
+*/
|
|
FFMPEG_PHP_METHOD(ffmpeg_frame, isKeyFrame)
|
|
{
|
|
ff_frame_context *ff_frame;
|
|
|
|
GET_FRAME_RESOURCE(getThis(), ff_frame);
|
|
-
|
|
+
|
|
RETURN_LONG(ff_frame->keyframe);
|
|
}
|
|
/* }}} */
|
|
|
|
|
|
/* {{{ proto int getWidth()
|
|
- */
|
|
+*/
|
|
FFMPEG_PHP_METHOD(ffmpeg_frame, getWidth)
|
|
{
|
|
ff_frame_context *ff_frame;
|
|
|
|
GET_FRAME_RESOURCE(getThis(), ff_frame);
|
|
-
|
|
+
|
|
RETURN_LONG(ff_frame->width);
|
|
}
|
|
/* }}} */
|
|
|
|
|
|
/* {{{ proto int getHeight()
|
|
- */
|
|
+*/
|
|
FFMPEG_PHP_METHOD(ffmpeg_frame, getHeight)
|
|
{
|
|
ff_frame_context *ff_frame;
|
|
|
|
GET_FRAME_RESOURCE(getThis(), ff_frame);
|
|
-
|
|
+
|
|
RETURN_LONG(ff_frame->height);
|
|
+}
|
|
+/* }}} */
|
|
+
|
|
+
|
|
+/* {{{ _php_resample_frame()
|
|
+*/
|
|
+int _php_resample_frame(ff_frame_context *ff_frame,
|
|
+ int wanted_width, int wanted_height, int crop_top, int crop_bottom,
|
|
+ int crop_left, int crop_right)
|
|
+{
|
|
+ AVFrame *resampled_frame;
|
|
+ phpImgReSampleContext *img_resample_ctx = NULL;
|
|
+
|
|
+ if (!ff_frame->av_frame) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * do nothing if width and height are the same as the frame and no
|
|
+ * cropping was specified
|
|
+ * */
|
|
+ if (wanted_width == ff_frame->width &&
|
|
+ wanted_height == ff_frame->height &&
|
|
+ (!crop_left && !crop_right && !crop_top && !crop_bottom)) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ /* convert to PIX_FMT_YUV420P required for resampling */
|
|
+ _php_convert_frame(ff_frame, PIX_FMT_YUV420P);
|
|
+
|
|
+ img_resample_ctx = phpimg_resample_full_init(
|
|
+ wanted_width, wanted_height,
|
|
+ ff_frame->width, ff_frame->height,
|
|
+ crop_top, crop_bottom, crop_left, crop_right,
|
|
+ 0, 0, 0, 0);
|
|
+ if (!img_resample_ctx) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ resampled_frame = avcodec_alloc_frame();
|
|
+ avpicture_alloc((AVPicture*)resampled_frame, PIX_FMT_YUV420P,
|
|
+ wanted_width, wanted_height);
|
|
+
|
|
+ phpimg_resample(img_resample_ctx, (AVPicture*)resampled_frame,
|
|
+ (AVPicture*)ff_frame->av_frame);
|
|
+
|
|
+ _php_free_av_frame(ff_frame->av_frame);
|
|
+
|
|
+ phpimg_resample_close(img_resample_ctx);
|
|
+
|
|
+ ff_frame->av_frame = resampled_frame;
|
|
+ ff_frame->width = wanted_width;
|
|
+ ff_frame->height = wanted_height;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+/* }}} */
|
|
+
|
|
+
|
|
+/* {{{ proto boolean resize(int width, int height [, int crop_top [, int crop_bottom [, int crop_left [, int crop_right ]]]])
|
|
+*/
|
|
+FFMPEG_PHP_METHOD(ffmpeg_frame, resize)
|
|
+{
|
|
+ zval ***argv;
|
|
+ ff_frame_context *ff_frame = NULL;
|
|
+ int wanted_width = 0, wanted_height = 0;
|
|
+ int crop_top = 0, crop_bottom = 0, crop_left = 0, crop_right = 0;
|
|
+
|
|
+ GET_FRAME_RESOURCE(getThis(), ff_frame);
|
|
+
|
|
+ /* retrieve arguments */
|
|
+ argv = (zval ***) safe_emalloc(sizeof(zval **), ZEND_NUM_ARGS(), 0);
|
|
+
|
|
+ if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), argv) != SUCCESS) {
|
|
+ efree(argv);
|
|
+ php_error_docref(NULL TSRMLS_CC, E_ERROR,
|
|
+ "Error parsing arguments");
|
|
+ }
|
|
+
|
|
+ switch (ZEND_NUM_ARGS()) {
|
|
+ case 6:
|
|
+ convert_to_long_ex(argv[5]);
|
|
+ crop_right = Z_LVAL_PP(argv[5]);
|
|
+
|
|
+ /* crop right must be even number for lavc cropping */
|
|
+ if (crop_right % 2) {
|
|
+ php_error_docref(NULL TSRMLS_CC, E_ERROR,
|
|
+ "Crop right must be an even number");
|
|
+ }
|
|
+ /* fallthru */
|
|
+ case 5:
|
|
+ convert_to_long_ex(argv[4]);
|
|
+ crop_left = Z_LVAL_PP(argv[4]);
|
|
+
|
|
+ /* crop left must be even number for lavc cropping */
|
|
+ if (crop_left % 2) {
|
|
+ php_error_docref(NULL TSRMLS_CC, E_ERROR,
|
|
+ "Crop left must be an even number");
|
|
+ }
|
|
+
|
|
+ /* fallthru */
|
|
+ case 4:
|
|
+ convert_to_long_ex(argv[3]);
|
|
+ crop_bottom = Z_LVAL_PP(argv[3]);
|
|
+
|
|
+ /* crop bottom must be even number for lavc cropping */
|
|
+ if (crop_bottom % 2) {
|
|
+ php_error_docref(NULL TSRMLS_CC, E_ERROR,
|
|
+ "Crop bottom must be an even number");
|
|
+ }
|
|
+
|
|
+ /* fallthru */
|
|
+ case 3:
|
|
+ convert_to_long_ex(argv[2]);
|
|
+ crop_top = Z_LVAL_PP(argv[2]);
|
|
+
|
|
+ /* crop top must be even number for lavc cropping */
|
|
+ if (crop_top % 2) {
|
|
+ php_error_docref(NULL TSRMLS_CC, E_ERROR,
|
|
+ "Crop top must be an even number");
|
|
+ }
|
|
+
|
|
+ /* fallthru */
|
|
+ case 2:
|
|
+ /* height arg */
|
|
+ convert_to_long_ex(argv[1]);
|
|
+ wanted_height = Z_LVAL_PP(argv[1]);
|
|
+
|
|
+ /* bounds check wanted height */
|
|
+ if (wanted_height < 1) {
|
|
+ php_error_docref(NULL TSRMLS_CC, E_ERROR,
|
|
+ "Frame height must be greater than zero");
|
|
+ }
|
|
+
|
|
+ /* wanted height must be even number for lavc resample */
|
|
+ if (wanted_height % 2) {
|
|
+ php_error_docref(NULL TSRMLS_CC, E_ERROR,
|
|
+ "Frame height must be an even number");
|
|
+ }
|
|
+ /* fallthru */
|
|
+ case 1:
|
|
+ /* width arg */
|
|
+ convert_to_long_ex(argv[0]);
|
|
+ wanted_width = Z_LVAL_PP(argv[0]);
|
|
+
|
|
+ /* bounds check wanted width */
|
|
+ if (wanted_width < 1) {
|
|
+ php_error_docref(NULL TSRMLS_CC, E_ERROR,
|
|
+ "Frame width must be greater than zero");
|
|
+ }
|
|
+
|
|
+ /* wanted width must be even number for lavc resample */
|
|
+ if (wanted_width % 2) {
|
|
+ php_error_docref(NULL TSRMLS_CC, E_ERROR,
|
|
+ "Frame width must be an even number");
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ WRONG_PARAM_COUNT;
|
|
+ }
|
|
+
|
|
+ efree(argv);
|
|
+
|
|
+ /* resize frame */
|
|
+ _php_resample_frame(ff_frame, wanted_width, wanted_height,
|
|
+ crop_top, crop_bottom, crop_left, crop_right);
|
|
+
|
|
+ RETURN_TRUE;
|
|
+}
|
|
+/* }}} */
|
|
+
|
|
+
|
|
+/* {{{ proto boolean crop([, int crop_top [, int crop_bottom [, int crop_left [, int crop_right ]]]])
|
|
+*/
|
|
+PHP_FUNCTION(crop)
|
|
+{
|
|
+ zval ***argv;
|
|
+ ff_frame_context *ff_frame;
|
|
+ int crop_top = 0, crop_bottom = 0, crop_left = 0, crop_right = 0;
|
|
+
|
|
+ GET_FRAME_RESOURCE(getThis(), ff_frame);
|
|
+
|
|
+ /* retrieve arguments */
|
|
+ argv = (zval ***) safe_emalloc(sizeof(zval **), ZEND_NUM_ARGS(), 0);
|
|
+
|
|
+ if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), argv) != SUCCESS) {
|
|
+ efree(argv);
|
|
+ php_error_docref(NULL TSRMLS_CC, E_ERROR,
|
|
+ "Error parsing arguments");
|
|
+ }
|
|
+
|
|
+ switch (ZEND_NUM_ARGS()) {
|
|
+ case 4:
|
|
+ convert_to_long_ex(argv[3]);
|
|
+ crop_right = Z_LVAL_PP(argv[3]);
|
|
+
|
|
+ /* crop right must be even number for lavc cropping */
|
|
+ if (crop_right % 2) {
|
|
+ php_error_docref(NULL TSRMLS_CC, E_ERROR,
|
|
+ "Crop right must be an even number");
|
|
+ }
|
|
+ /* fallthru */
|
|
+ case 3:
|
|
+ convert_to_long_ex(argv[2]);
|
|
+ crop_left = Z_LVAL_PP(argv[2]);
|
|
+
|
|
+ /* crop left must be even number for lavc cropping */
|
|
+ if (crop_left % 2) {
|
|
+ php_error_docref(NULL TSRMLS_CC, E_ERROR,
|
|
+ "Crop left must be an even number");
|
|
+ }
|
|
+
|
|
+ /* fallthru */
|
|
+ case 2:
|
|
+ convert_to_long_ex(argv[1]);
|
|
+ crop_bottom = Z_LVAL_PP(argv[1]);
|
|
+
|
|
+ /* crop bottom must be even number for lavc cropping */
|
|
+ if (crop_bottom % 2) {
|
|
+ php_error_docref(NULL TSRMLS_CC, E_ERROR,
|
|
+ "Crop bottom must be an even number");
|
|
+ }
|
|
+
|
|
+ /* fallthru */
|
|
+ case 1:
|
|
+ convert_to_long_ex(argv[0]);
|
|
+ crop_top = Z_LVAL_PP(argv[0]);
|
|
+
|
|
+ /* crop top must be even number for lavc cropping */
|
|
+ if (crop_top % 2) {
|
|
+ php_error_docref(NULL TSRMLS_CC, E_ERROR,
|
|
+ "Crop top must be an even number");
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ WRONG_PARAM_COUNT;
|
|
+ }
|
|
+
|
|
+ efree(argv);
|
|
+
|
|
+ /* resample with same dimensions */
|
|
+ _php_resample_frame(ff_frame, ff_frame->width, ff_frame->height,
|
|
+ crop_top, crop_bottom, crop_left, crop_right);
|
|
+
|
|
+ RETURN_TRUE;
|
|
}
|
|
/* }}} */
|
|
|