Skip to content
82 changes: 75 additions & 7 deletions ffmpeg-php.c
Original file line number Diff line number Diff line change
Expand Up @@ -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()


Expand All @@ -93,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();

Expand All @@ -110,16 +114,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
Expand All @@ -137,6 +165,7 @@ PHP_MSHUTDOWN_FUNCTION(ffmpeg)
{
// TODO: Free any remaining persistent movies here?

avformat_network_deinit();
UNREGISTER_INI_ENTRIES();

return SUCCESS;
Expand All @@ -161,6 +190,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());
Expand Down Expand Up @@ -205,6 +236,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
Expand Down
27 changes: 8 additions & 19 deletions ffmpeg_frame.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -239,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);
Expand All @@ -260,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;
}
/* }}} */
Expand Down
54 changes: 33 additions & 21 deletions ffmpeg_movie.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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
Expand All @@ -1232,22 +1240,12 @@ 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++;
ffmovie_ctx->frame_number = decoder_ctx->frame_number;

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

Expand Down Expand Up @@ -1282,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);
Expand All @@ -1300,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;
Expand Down Expand Up @@ -1333,9 +1339,15 @@ 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;
}

/* 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;
Expand Down