openbsd-ports/multimedia/ffmpeg-php/patches/patch-ffmpeg_frame_c
2009-08-17 01:40:30 +00:00

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;
}
/* }}} */