From 4180ce76e46329e552ecf2f8bfa72a352c86561f Mon Sep 17 00:00:00 2001 From: Andras Elso Date: Thu, 20 Feb 2014 12:50:13 +0000 Subject: [PATCH 01/13] Register all libav components version --- ffmpeg-php.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/ffmpeg-php.c b/ffmpeg-php.c index 08aeec9..36a963b 100644 --- a/ffmpeg-php.c +++ b/ffmpeg-php.c @@ -110,16 +110,40 @@ PHP_MINIT_FUNCTION(ffmpeg) FFMPEG_PHP_VERSION, CONST_CS | CONST_PERSISTENT); REGISTER_STRING_CONSTANT("FFMPEG_PHP_BUILD_DATE_STRING", __DATE__ " " __TIME__, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("LIBAVCODEC_VERSION_NUMBER", - avcodec_version(), CONST_CS | CONST_PERSISTENT); -#ifdef LIBAVCODEC_BUILD - REGISTER_LONG_CONSTANT("LIBAVCODEC_BUILD_NUMBER", - LIBAVCODEC_BUILD, CONST_CS | CONST_PERSISTENT); + +#ifndef LIBAVCODEC_BUILD +#define LIBAVCODEC_BUILD avcodec_build() +#endif +#ifndef LIBAVFORMAT_BUILD +#define LIBAVFORMAT_BUILD avformat_build() +#endif +#ifndef LIBAVUTIL_BUILD +#define LIBAVUTIL_BUILD avutils_build() +#endif +#ifndef LIBSWSCALE_BUILD +#define LIBSWSCALE_BUILD swscale_build() +#endif + +#define register_libav3(x, y, z) \ + REGISTER_LONG_CONSTANT(#x "_VERSION_NUMBER", \ + y, CONST_CS | CONST_PERSISTENT); \ + REGISTER_LONG_CONSTANT(#x "_BUILD_NUMBER", \ + z, CONST_CS | CONST_PERSISTENT) + +#define register_libav2(x, y) register_libav3(x, y, x##_BUILD) + + register_libav2(LIBAVCODEC, avcodec_version()); + register_libav2(LIBAVFORMAT, avformat_version()); + register_libav2(LIBAVUTIL, avutil_version()); +#if HAVE_SWSCALER + register_libav2(LIBSWSCALE, swscale_version()); #else - REGISTER_LONG_CONSTANT("LIBAVCODEC_BUILD_NUMBER", - avcodec_build(), CONST_CS | CONST_PERSISTENT); + register_libav3(LIBSWSCALE, 0, 0); #endif +#undef register_libav3 +#undef register_libav2 + #if HAVE_LIBGD20 REGISTER_LONG_CONSTANT("FFMPEG_PHP_GD_ENABLED", 1, CONST_CS | CONST_PERSISTENT); #else From ae29566de242c53d9ff305fd5356e90fd3d13aea Mon Sep 17 00:00:00 2001 From: Andras Elso Date: Thu, 20 Feb 2014 12:54:11 +0000 Subject: [PATCH 02/13] Display libavutil version and license in php_info() --- ffmpeg-php.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ffmpeg-php.c b/ffmpeg-php.c index 36a963b..b41efaf 100644 --- a/ffmpeg-php.c +++ b/ffmpeg-php.c @@ -185,6 +185,8 @@ PHP_MINFO_FUNCTION(ffmpeg) php_info_print_table_row(2, "ffmpeg libavcodec license", avcodec_license()); //people need to know if they can distribute php_info_print_table_row(2, "ffmpeg libavformat version", LIBAVFORMAT_IDENT); php_info_print_table_row(2, "ffmpeg libavformat license", avformat_license()); + php_info_print_table_row(2, "ffmpeg libavutil version", LIBAVUTIL_IDENT); + php_info_print_table_row(2, "ffmpeg libavutil license", avutil_license()); #if HAVE_SWSCALER php_info_print_table_row(2, "ffmpeg swscaler version", LIBSWSCALE_IDENT); php_info_print_table_row(2, "ffmpeg swscaler license", swscale_license()); From f112848f5d8755a5a6b0699074334f29af78517a Mon Sep 17 00:00:00 2001 From: Andras Elso Date: Thu, 20 Feb 2014 12:54:59 +0000 Subject: [PATCH 03/13] Allow change the ffmpeg log level --- ffmpeg-php.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/ffmpeg-php.c b/ffmpeg-php.c index b41efaf..9319676 100644 --- a/ffmpeg-php.c +++ b/ffmpeg-php.c @@ -81,10 +81,12 @@ ZEND_GET_MODULE(ffmpeg); extern void register_ffmpeg_movie_class(int); extern void register_ffmpeg_frame_class(int); +static PHP_INI_MH(OnUpdateLogLevel); PHP_INI_BEGIN() PHP_INI_ENTRY("ffmpeg.allow_persistent", "0", PHP_INI_ALL, NULL) PHP_INI_ENTRY("ffmpeg.show_warnings", "0", PHP_INI_ALL, NULL) + PHP_INI_ENTRY("ffmpeg.loglevel", "info", PHP_INI_ALL, OnUpdateLogLevel) PHP_INI_END() @@ -231,6 +233,43 @@ PHP_MINFO_FUNCTION(ffmpeg) /* }}} */ +/* {{{ PHP_INI_MH + */ +static PHP_INI_MH(OnUpdateLogLevel) +{ + const struct { const char *name; int level; } log_levels[] = { + { "quiet" , AV_LOG_QUIET }, + { "panic" , AV_LOG_PANIC }, + { "fatal" , AV_LOG_FATAL }, + { "error" , AV_LOG_ERROR }, + { "warning", AV_LOG_WARNING }, + { "info" , AV_LOG_INFO }, + { "verbose", AV_LOG_VERBOSE }, + { "debug" , AV_LOG_DEBUG } + }; + char *tail; + int level; + int i; + + for (i = 0; i < sizeof(log_levels)/sizeof(log_levels[0]); i++) { + if (!strcmp(log_levels[i].name, new_value)) { + av_log_set_level(log_levels[i].level); + return SUCCESS; + } + } + + level = strtol(new_value, &tail, 10); + if (*tail) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid loglevel \"%s\". " + "Possible levels are numbers or {quiet, panic, fatal, error, warning, info, verbose, debug}", new_value); + return FAILURE; + } + av_log_set_level(level); + return SUCCESS; +} +/* }}} */ + + /* * Local variables: * tab-width: 4 From c25fe0fe91810cf12b405549f34b2f85d8b43346 Mon Sep 17 00:00:00 2001 From: Andras Elso Date: Thu, 20 Feb 2014 12:58:20 +0000 Subject: [PATCH 04/13] Initialize libav codec and network --- ffmpeg-php.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ffmpeg-php.c b/ffmpeg-php.c index 9319676..1b86969 100644 --- a/ffmpeg-php.c +++ b/ffmpeg-php.c @@ -95,7 +95,9 @@ PHP_INI_END() PHP_MINIT_FUNCTION(ffmpeg) { /* register all codecs */ + avcodec_register_all(); av_register_all(); + avformat_network_init(); REGISTER_INI_ENTRIES(); @@ -163,6 +165,7 @@ PHP_MSHUTDOWN_FUNCTION(ffmpeg) { // TODO: Free any remaining persistent movies here? + avformat_network_deinit(); UNREGISTER_INI_ENTRIES(); return SUCCESS; From a201e418764b8bd6dde3d8ae386384f750666ebb Mon Sep 17 00:00:00 2001 From: Andras Elso Date: Thu, 20 Feb 2014 12:59:15 +0000 Subject: [PATCH 05/13] Remove multiple config.h include --- ffmpeg_frame.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/ffmpeg_frame.c b/ffmpeg_frame.c index 4178756..1b5322e 100644 --- a/ffmpeg_frame.c +++ b/ffmpeg_frame.c @@ -42,19 +42,11 @@ #include "php_globals.h" #include "ext/standard/info.h" -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include "php_ffmpeg.h" #include "ffmpeg_frame.h" #include "ffmpeg_tools.h" -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - /* 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 From 5d5634f39983ee231aae54cfcffca7a89ac3fbd9 Mon Sep 17 00:00:00 2001 From: Andras Elso Date: Thu, 20 Feb 2014 13:00:39 +0000 Subject: [PATCH 06/13] Remove duplicated code --- ffmpeg_frame.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/ffmpeg_frame.c b/ffmpeg_frame.c index 1b5322e..ba2696b 100644 --- a/ffmpeg_frame.c +++ b/ffmpeg_frame.c @@ -231,7 +231,7 @@ static int _php_get_gd_image(int w, int h TSRMLS_DC) zend_function *func; zval *retval; char *function_cname = "imagecreatetruecolor"; - int ret; + int ret = -1; if (zend_hash_find(EG(function_table), function_cname, strlen(function_cname) + 1, (void **)&func) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error can't find %s function", function_cname); @@ -252,26 +252,23 @@ static int _php_get_gd_image(int w, int h TSRMLS_DC) if (call_user_function_ex(EG(function_table), NULL, function_name, &retval, 2, argv, 0, NULL TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error calling %s function", function_cname); - - FREE_ZVAL(function_name); - FREE_ZVAL(width); - FREE_ZVAL(height); - return -1; + goto out; } - FREE_ZVAL(function_name); - FREE_ZVAL(width); - FREE_ZVAL(height); - if (!retval || Z_TYPE_P(retval) != IS_RESOURCE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error creating GD Image"); - return -1; + goto out; } ret = Z_LVAL_P(retval); zend_list_addref(ret); zval_ptr_dtor(&retval); +out: + FREE_ZVAL(function_name); + FREE_ZVAL(width); + FREE_ZVAL(height); + return ret; } /* }}} */ From f8009d6a33c7c02e94b5b1fd50a2585dc0bb291e Mon Sep 17 00:00:00 2001 From: Andras Elso Date: Thu, 20 Feb 2014 13:01:37 +0000 Subject: [PATCH 07/13] Fix codestyle --- ffmpeg_movie.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ffmpeg_movie.c b/ffmpeg_movie.c index 91b5c6e..3d1edc0 100644 --- a/ffmpeg_movie.c +++ b/ffmpeg_movie.c @@ -282,16 +282,16 @@ FFMPEG_PHP_CONSTRUCTOR(ffmpeg_movie, __construct) { int hashkey_length = 0, filename_len; char *filename = NULL, *fullpath = NULL, *hashkey = NULL; - zend_bool persistent = 0; + zend_bool persistent = 0; ff_movie_context *ffmovie_ctx = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &filename, &filename_len, &persistent) != SUCCESS) { - return; + return; } - if (persistent && !INI_BOOL("ffmpeg.allow_persistent")) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Persistent movies have been disabled in php.ini"); - RETURN_FALSE; + if (persistent && !INI_BOOL("ffmpeg.allow_persistent")) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Persistent movies have been disabled in php.ini"); + RETURN_FALSE; } if (persistent) { @@ -1333,9 +1333,9 @@ FFMPEG_PHP_METHOD(ffmpeg_movie, getFrame) GET_MOVIE_RESOURCE(ffmovie_ctx); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &wanted_frame) != SUCCESS) { - return; - } + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &wanted_frame) != SUCCESS) { + return; + } if (! _php_get_ff_frame(ffmovie_ctx, wanted_frame, INTERNAL_FUNCTION_PARAM_PASSTHRU)) { RETURN_FALSE; From 67853525c9c2d2041a153a8192772d566f80134c Mon Sep 17 00:00:00 2001 From: Andras Elso Date: Thu, 20 Feb 2014 13:03:23 +0000 Subject: [PATCH 08/13] Fix libav pts and key_frame detection --- ffmpeg_movie.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ffmpeg_movie.c b/ffmpeg_movie.c index 3d1edc0..71e7bb2 100644 --- a/ffmpeg_movie.c +++ b/ffmpeg_movie.c @@ -1175,8 +1175,16 @@ static AVFrame* _php_read_av_frame(ff_movie_context *ffmovie_ctx, avcodec_decode_video2(decoder_ctx, frame, &got_frame, &packet); if (got_frame) { +#if LIBAVCODEC_BUILD > 4640 + *is_keyframe = frame->key_frame; // http://git.libav.org/?p=libav.git;a=commitdiff;h=1e491e29c27cf6a6925666e4f4eac41b65e263d7 +#else *is_keyframe = (packet.flags & AV_PKT_FLAG_KEY); +#endif +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52,105,0) + *pts = frame->pkt_pts; // http://git.libav.org/?p=libav.git;a=commitdiff;h=393cbb963b83ecd98336502b1201f16f5eaed979 +#else *pts = packet.pts; +#endif av_free_packet(&packet); return frame; } @@ -1211,7 +1219,7 @@ static AVFrame* _php_get_av_frame(ff_movie_context *ffmovie_ctx, int wanted_fram if ( #if LIBAVFORMAT_BUILD >= 4619 - av_seek_frame(ffmovie_ctx->fmt_ctx, -1, 0, 0) + av_seek_frame(ffmovie_ctx->fmt_ctx, -1, 0, AVSEEK_FLAG_BACKWARD) #else av_seek_frame(ffmovie_ctx->fmt_ctx, -1, 0) #endif From c7ad57cdb55472a3e78af5e39866e7e581a3470d Mon Sep 17 00:00:00 2001 From: Andras Elso Date: Thu, 20 Feb 2014 13:05:16 +0000 Subject: [PATCH 09/13] Remove libav hurryup code, because it doesnt work --- ffmpeg_movie.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/ffmpeg_movie.c b/ffmpeg_movie.c index 71e7bb2..b60e6c4 100644 --- a/ffmpeg_movie.c +++ b/ffmpeg_movie.c @@ -1240,16 +1240,6 @@ static AVFrame* _php_get_av_frame(ff_movie_context *ffmovie_ctx, int wanted_fram while (1) { frame = _php_read_av_frame(ffmovie_ctx, decoder_ctx, is_keyframe, pts); - /* hurry up if we're still a ways from the target frame */ - /*if (wanted_frame != GETFRAME_KEYFRAME && - wanted_frame != GETFRAME_NEXTFRAME && - wanted_frame - ffmovie_ctx->frame_number > - decoder_ctx->gop_size + 1) { - decoder_ctx->hurry_up = 1; - } else { - decoder_ctx->hurry_up = 0; - }*/ - /*CUT? cannot hurry up ffmpeg anymore*/ ffmovie_ctx->frame_number++; /* From 9f37fe89e525963d9a95397ffa8d6715e8b2d40c Mon Sep 17 00:00:00 2001 From: Andras Elso Date: Thu, 20 Feb 2014 13:05:53 +0000 Subject: [PATCH 10/13] Set the frame number from right value --- ffmpeg_movie.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ffmpeg_movie.c b/ffmpeg_movie.c index b60e6c4..1c23532 100644 --- a/ffmpeg_movie.c +++ b/ffmpeg_movie.c @@ -1240,7 +1240,7 @@ static AVFrame* _php_get_av_frame(ff_movie_context *ffmovie_ctx, int wanted_fram while (1) { frame = _php_read_av_frame(ffmovie_ctx, decoder_ctx, is_keyframe, pts); - ffmovie_ctx->frame_number++; + ffmovie_ctx->frame_number = decoder_ctx->frame_number; /* * if caller wants next keyframe then get it and break out of loop. From 58d695ac69a5f13c40833448d4217fd478c80ed2 Mon Sep 17 00:00:00 2001 From: Andras Elso Date: Thu, 20 Feb 2014 13:06:31 +0000 Subject: [PATCH 11/13] Use is_keyframe value not the pointer --- ffmpeg_movie.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ffmpeg_movie.c b/ffmpeg_movie.c index 1c23532..c3f8a35 100644 --- a/ffmpeg_movie.c +++ b/ffmpeg_movie.c @@ -1245,7 +1245,7 @@ static AVFrame* _php_get_av_frame(ff_movie_context *ffmovie_ctx, int wanted_fram /* * if caller wants next keyframe then get it and break out of loop. */ - if (wanted_frame == GETFRAME_KEYFRAME && is_keyframe) { + if (wanted_frame == GETFRAME_KEYFRAME && *is_keyframe) { return frame; } From 04bfecd39d7c496b9f02b6076b8b81552389acfb Mon Sep 17 00:00:00 2001 From: Andras Elso Date: Thu, 20 Feb 2014 13:07:56 +0000 Subject: [PATCH 12/13] Fix memory leak --- ffmpeg_movie.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ffmpeg_movie.c b/ffmpeg_movie.c index c3f8a35..baaab8e 100644 --- a/ffmpeg_movie.c +++ b/ffmpeg_movie.c @@ -1280,6 +1280,13 @@ static int _php_get_ff_frame(ff_movie_context *ffmovie_ctx, int wanted_frame, IN */ ff_frame = _php_create_ffmpeg_frame(INTERNAL_FUNCTION_PARAM_PASSTHRU); + if (!ff_frame) { + free(frame); + php_error_docref(NULL TSRMLS_CC, E_ERROR, + "Error allocating ffmpeg_frame resource"); + return 0; + } + /* TODO: Provide function(s) for setting these in ffmpeg_frame */ ff_frame->width = _php_get_framewidth(ffmovie_ctx); ff_frame->height = _php_get_frameheight(ffmovie_ctx); @@ -1298,6 +1305,7 @@ static int _php_get_ff_frame(ff_movie_context *ffmovie_ctx, int wanted_frame, IN (AVPicture*)frame, ff_frame->pixel_format, ff_frame->width, ff_frame->height); + free(frame); return 1; } else { return 0; From de9b588385c2a13c5015498eafd85f509106a593 Mon Sep 17 00:00:00 2001 From: Andras Elso Date: Thu, 20 Feb 2014 13:10:56 +0000 Subject: [PATCH 13/13] Bounds check for wanted frame --- ffmpeg_movie.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ffmpeg_movie.c b/ffmpeg_movie.c index baaab8e..60b734e 100644 --- a/ffmpeg_movie.c +++ b/ffmpeg_movie.c @@ -1343,6 +1343,12 @@ FFMPEG_PHP_METHOD(ffmpeg_movie, getFrame) return; } + /* bounds check wanted frame */ + if (wanted_frame < 1) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Frame number must be greater than zero"); + RETURN_FALSE; + } + if (! _php_get_ff_frame(ffmovie_ctx, wanted_frame, INTERNAL_FUNCTION_PARAM_PASSTHRU)) { RETURN_FALSE; }