mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
Update plugins to newest divx.com release API (5.2) (why aren't these libs API stable?!?)
Original commit message from CVS: Update plugins to newest divx.com release API (5.2) (why aren't these libs API stable?!?)
This commit is contained in:
parent
8e1ee4564b
commit
c4eefdd7bc
5 changed files with 274 additions and 147 deletions
50
configure.ac
50
configure.ac
|
@ -531,16 +531,48 @@ GST_CHECK_FEATURE(DIVX, [divx plugins], divx, [
|
||||||
AC_CHECK_HEADER(encore2.h, ,
|
AC_CHECK_HEADER(encore2.h, ,
|
||||||
[ AC_MSG_WARN([Divx4linux encore headers not found]) &&
|
[ AC_MSG_WARN([Divx4linux encore headers not found]) &&
|
||||||
HAVE_DIVX=no ] )
|
HAVE_DIVX=no ] )
|
||||||
AC_CHECK_HEADER(decore.h, ,
|
if [ test x$HAVE_DIVX = xyes ]; then
|
||||||
[ AC_MSG_WARN([Divx4linux decoder headers not found]) &&
|
AC_MSG_CHECKING([Checking for valid divx4linux encore version])
|
||||||
HAVE_DIVX=no ] )
|
AC_TRY_COMPILE([
|
||||||
|
#include <encore2.h>
|
||||||
|
#if ENCORE_VERSION != 20021024
|
||||||
|
#error Wrong version of divx encore libraries
|
||||||
|
#endif
|
||||||
|
], [
|
||||||
|
return 0;
|
||||||
|
], [ HAVE_DIVX=yes && AC_MSG_RESULT(yes)],
|
||||||
|
[ HAVE_DIVX=no && AC_MSG_RESULT(no) &&
|
||||||
|
AC_MSG_WARN([Wrong version of divx4linux installed]) ])
|
||||||
|
fi
|
||||||
|
if [ test x$HAVE_DIVX = xyes ]; then
|
||||||
|
AC_CHECK_HEADER(decore.h, ,
|
||||||
|
[ AC_MSG_WARN([Divx4linux decoder headers not found]) &&
|
||||||
|
HAVE_DIVX=no ] )
|
||||||
|
fi
|
||||||
|
if [ test x$HAVE_DIVX = xyes ]; then
|
||||||
|
AC_MSG_CHECKING([Checking for valid divx4linux decore version])
|
||||||
|
AC_TRY_COMPILE([
|
||||||
|
#include <decore.h>
|
||||||
|
#if DECORE_VERSION != 20021112
|
||||||
|
#error Wrong version of divx decore libraries
|
||||||
|
#endif
|
||||||
|
], [
|
||||||
|
return 0;
|
||||||
|
], [ HAVE_DIVX=yes && AC_MSG_RESULT(yes)],
|
||||||
|
[ HAVE_DIVX=no && AC_MSG_RESULT(no) &&
|
||||||
|
AC_MSG_WARN([Wrong version of divx4linux installed]) ])
|
||||||
|
fi
|
||||||
LIBS="-lm"
|
LIBS="-lm"
|
||||||
AC_CHECK_LIB(divxencore, encore, ,
|
if test x$HAVE_DIVX = xyes; then
|
||||||
[ AC_MSG_WARN([Divx4linux encore libs not found]) &&
|
AC_CHECK_LIB(divxencore, encore, ,
|
||||||
HAVE_DIVX=no ] )
|
[ AC_MSG_WARN([Divx4linux encore libs not found]) &&
|
||||||
AC_CHECK_LIB(divxdecore, decore, ,
|
HAVE_DIVX=no ] )
|
||||||
[ AC_MSG_WARN([Divx4linux decore libs not found]) &&
|
fi
|
||||||
HAVE_DIVX=no ] )
|
if test x$HAVE_DIVX = xyes; then
|
||||||
|
AC_CHECK_LIB(divxdecore, decore, ,
|
||||||
|
[ AC_MSG_WARN([Divx4linux decore libs not found]) &&
|
||||||
|
HAVE_DIVX=no ] )
|
||||||
|
fi
|
||||||
if test x$HAVE_DIVX = xyes; then
|
if test x$HAVE_DIVX = xyes; then
|
||||||
DIVXENC_LIBS="-ldivxencore -lm"
|
DIVXENC_LIBS="-ldivxencore -lm"
|
||||||
DIVXDEC_LIBS="-ldivxdecore -lm"
|
DIVXDEC_LIBS="-ldivxdecore -lm"
|
||||||
|
|
|
@ -89,6 +89,35 @@ static GstElementClass *parent_class = NULL;
|
||||||
/* static guint gst_divxdec_signals[LAST_SIGNAL] = { 0 }; */
|
/* static guint gst_divxdec_signals[LAST_SIGNAL] = { 0 }; */
|
||||||
|
|
||||||
|
|
||||||
|
static gchar *
|
||||||
|
gst_divxdec_error (int errorcode)
|
||||||
|
{
|
||||||
|
gchar *error;
|
||||||
|
|
||||||
|
switch (errorcode) {
|
||||||
|
case DEC_OK:
|
||||||
|
error = "No error";
|
||||||
|
break;
|
||||||
|
case DEC_MEMORY:
|
||||||
|
error = "Invalid memory";
|
||||||
|
break;
|
||||||
|
case DEC_BAD_FORMAT:
|
||||||
|
error = "Invalid format";
|
||||||
|
break;
|
||||||
|
case DEC_INVALID_ARGUMENT:
|
||||||
|
error = "Invalid argument";
|
||||||
|
break;
|
||||||
|
case DEC_NOT_IMPLEMENTED:
|
||||||
|
error = "Not implemented";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error = "Unknown error";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
GType
|
GType
|
||||||
gst_divxdec_get_type(void)
|
gst_divxdec_get_type(void)
|
||||||
{
|
{
|
||||||
|
@ -145,7 +174,7 @@ gst_divxdec_init (GstDivxDec *divxdec)
|
||||||
gst_element_add_pad(GST_ELEMENT(divxdec), divxdec->srcpad);
|
gst_element_add_pad(GST_ELEMENT(divxdec), divxdec->srcpad);
|
||||||
|
|
||||||
/* bitrate, etc. */
|
/* bitrate, etc. */
|
||||||
divxdec->width = divxdec->height = divxdec->csp = -1;
|
divxdec->width = divxdec->height = divxdec->csp = divxdec->bitcnt = -1;
|
||||||
|
|
||||||
/* set divx handle to NULL */
|
/* set divx handle to NULL */
|
||||||
divxdec->handle = NULL;
|
divxdec->handle = NULL;
|
||||||
|
@ -155,20 +184,9 @@ gst_divxdec_init (GstDivxDec *divxdec)
|
||||||
static void
|
static void
|
||||||
gst_divxdec_unset (GstDivxDec *divxdec)
|
gst_divxdec_unset (GstDivxDec *divxdec)
|
||||||
{
|
{
|
||||||
/* free allocated memory */
|
|
||||||
g_free(divxdec->bufinfo.mp4_edged_ref_buffers);
|
|
||||||
g_free(divxdec->bufinfo.mp4_edged_for_buffers);
|
|
||||||
g_free(divxdec->bufinfo.mp4_edged_back_buffers);
|
|
||||||
g_free(divxdec->bufinfo.mp4_display_buffers);
|
|
||||||
g_free(divxdec->bufinfo.mp4_state);
|
|
||||||
g_free(divxdec->bufinfo.mp4_tables);
|
|
||||||
g_free(divxdec->bufinfo.mp4_stream);
|
|
||||||
g_free(divxdec->bufinfo.mp4_reference);
|
|
||||||
|
|
||||||
if (divxdec->handle) {
|
if (divxdec->handle) {
|
||||||
/* unref this instance */
|
/* unref this instance */
|
||||||
decore((gulong) divxdec->handle, DEC_OPT_RELEASE,
|
decore(divxdec->handle, DEC_OPT_RELEASE, NULL, NULL);
|
||||||
NULL, NULL);
|
|
||||||
divxdec->handle = NULL;
|
divxdec->handle = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,76 +195,40 @@ gst_divxdec_unset (GstDivxDec *divxdec)
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_divxdec_setup (GstDivxDec *divxdec)
|
gst_divxdec_setup (GstDivxDec *divxdec)
|
||||||
{
|
{
|
||||||
DEC_PARAM xdec;
|
void *handle;
|
||||||
DEC_MEM_REQS xreq;
|
DEC_INIT xinit;
|
||||||
|
DivXBitmapInfoHeader output;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* initialise parameters, see divx documentation */
|
/* initialize the handle */
|
||||||
memset(&xdec, 0, sizeof(DEC_PARAM));
|
memset(&xinit, 0, sizeof(DEC_INIT));
|
||||||
xdec.x_dim = divxdec->width;
|
if ((ret = decore(&handle, DEC_OPT_INIT, &xinit, NULL)) != 0) {
|
||||||
xdec.y_dim = divxdec->height;
|
gst_element_error(GST_ELEMENT(divxdec),
|
||||||
xdec.time_incr = 15; /* default - what is this? */
|
"Error initializing divx decoding library: %s (%d)",
|
||||||
xdec.output_format = divxdec->csp;
|
gst_divxdec_error(ret), ret);
|
||||||
|
|
||||||
if ((ret = decore((gulong) divxdec, DEC_OPT_MEMORY_REQS,
|
|
||||||
&xdec, &xreq)) != 0) {
|
|
||||||
char *error;
|
|
||||||
switch (ret) {
|
|
||||||
case DEC_MEMORY:
|
|
||||||
error = "Memory allocation error";
|
|
||||||
break;
|
|
||||||
case DEC_BAD_FORMAT:
|
|
||||||
error = "Format";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
error = "Internal failure";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
GST_DEBUG(GST_CAT_PLUGIN_INFO,
|
|
||||||
"Setting parameters %dx%d@%d failed: %s",
|
|
||||||
divxdec->width, divxdec->height, divxdec->csp, error);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate memory */
|
/* we've got a handle now */
|
||||||
xdec.buffers.mp4_edged_ref_buffers = g_malloc(xreq.mp4_edged_ref_buffers_size);
|
divxdec->handle = handle;
|
||||||
memset(xdec.buffers.mp4_edged_ref_buffers, 0, xreq.mp4_edged_ref_buffers_size);
|
|
||||||
|
|
||||||
xdec.buffers.mp4_edged_for_buffers = g_malloc(xreq.mp4_edged_for_buffers_size);
|
/* initialise parameters, see divx documentation */
|
||||||
memset(xdec.buffers.mp4_edged_for_buffers, 0, xreq.mp4_edged_for_buffers_size);
|
memset(&output, 0, sizeof(DivXBitmapInfoHeader));
|
||||||
|
output.biSize = sizeof(DivXBitmapInfoHeader);
|
||||||
|
output.biWidth = divxdec->width;
|
||||||
|
output.biHeight = divxdec->height;
|
||||||
|
output.biBitCount = divxdec->bitcnt;
|
||||||
|
output.biCompression = divxdec->csp;
|
||||||
|
|
||||||
xdec.buffers.mp4_edged_back_buffers = g_malloc(xreq.mp4_edged_back_buffers_size);
|
if ((ret = decore(divxdec->handle, DEC_OPT_SETOUT,
|
||||||
memset(xdec.buffers.mp4_edged_back_buffers, 0, xreq.mp4_edged_back_buffers_size);
|
&output, NULL)) != 0) {
|
||||||
|
|
||||||
xdec.buffers.mp4_display_buffers = g_malloc(xreq.mp4_display_buffers_size);
|
|
||||||
memset(xdec.buffers.mp4_display_buffers, 0, xreq.mp4_display_buffers_size);
|
|
||||||
|
|
||||||
xdec.buffers.mp4_state = g_malloc(xreq.mp4_state_size);
|
|
||||||
memset(xdec.buffers.mp4_state, 0, xreq.mp4_state_size);
|
|
||||||
|
|
||||||
xdec.buffers.mp4_tables = g_malloc(xreq.mp4_tables_size);
|
|
||||||
memset(xdec.buffers.mp4_tables, 0, xreq.mp4_tables_size);
|
|
||||||
|
|
||||||
xdec.buffers.mp4_stream = g_malloc(xreq.mp4_stream_size);
|
|
||||||
memset(xdec.buffers.mp4_stream, 0, xreq.mp4_stream_size);
|
|
||||||
|
|
||||||
xdec.buffers.mp4_reference = g_malloc(xreq.mp4_reference_size);
|
|
||||||
memset(xdec.buffers.mp4_reference, 0, xreq.mp4_reference_size);
|
|
||||||
|
|
||||||
divxdec->bufinfo = xdec.buffers;
|
|
||||||
|
|
||||||
if ((ret = decore((gulong) divxdec, DEC_OPT_INIT,
|
|
||||||
&xdec, &xreq)) != 0) {
|
|
||||||
gst_element_error(GST_ELEMENT(divxdec),
|
gst_element_error(GST_ELEMENT(divxdec),
|
||||||
"Expected error when confirming current settings: %d",
|
"Error setting output format: %s (%d)",
|
||||||
ret);
|
gst_divxdec_error(ret), ret);
|
||||||
gst_divxdec_unset(divxdec);
|
gst_divxdec_unset(divxdec);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* don't tell me this sucks - this is how divx4linux works... */
|
|
||||||
divxdec->handle = divxdec;
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,13 +276,14 @@ gst_divxdec_chain (GstPad *pad,
|
||||||
xframe.bitstream = (void *) GST_BUFFER_DATA(buf);
|
xframe.bitstream = (void *) GST_BUFFER_DATA(buf);
|
||||||
xframe.bmp = (void *) GST_BUFFER_DATA(outbuf);
|
xframe.bmp = (void *) GST_BUFFER_DATA(outbuf);
|
||||||
xframe.length = GST_BUFFER_SIZE(buf);
|
xframe.length = GST_BUFFER_SIZE(buf);
|
||||||
xframe.stride = divxdec->width * divxdec->bpp / 8;
|
xframe.stride = 0;
|
||||||
xframe.render_flag = 1;
|
xframe.render_flag = 1;
|
||||||
|
|
||||||
if ((ret = decore((gulong) divxdec->handle, DEC_OPT_FRAME,
|
if ((ret = decore(divxdec->handle, DEC_OPT_FRAME,
|
||||||
&xframe, NULL))) {
|
&xframe, NULL))) {
|
||||||
gst_element_error(GST_ELEMENT(divxdec),
|
gst_element_error(GST_ELEMENT(divxdec),
|
||||||
"Error decoding divx frame: %d\n", ret);
|
"Error decoding divx frame: %s (%d)",
|
||||||
|
gst_divxdec_error(ret), ret);
|
||||||
gst_buffer_unref(buf);
|
gst_buffer_unref(buf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -319,18 +302,36 @@ gst_divxdec_connect (GstPad *pad,
|
||||||
struct {
|
struct {
|
||||||
guint32 fourcc;
|
guint32 fourcc;
|
||||||
gint depth, bpp;
|
gint depth, bpp;
|
||||||
gint csp;
|
guint32 csp;
|
||||||
|
gint bitcnt;
|
||||||
} fmt_list[] = {
|
} fmt_list[] = {
|
||||||
{ GST_MAKE_FOURCC('Y','U','Y','V'), 16, 16, DEC_YUY2 },
|
{ GST_MAKE_FOURCC('Y','U','Y','2'), 16, 16,
|
||||||
{ GST_MAKE_FOURCC('U','Y','V','Y'), 16, 16, DEC_UYVY },
|
GST_MAKE_FOURCC('Y','U','Y','2'), 0 },
|
||||||
{ GST_MAKE_FOURCC('I','4','2','0'), 12, 12, DEC_420 },
|
{ GST_MAKE_FOURCC('U','Y','V','Y'), 16, 16,
|
||||||
{ GST_MAKE_FOURCC('I','Y','U','V'), 12, 12, DEC_420 },
|
GST_MAKE_FOURCC('U','Y','V','Y'), 0 },
|
||||||
{ GST_MAKE_FOURCC('Y','V','1','2'), 12, 12, DEC_YV12 },
|
{ GST_MAKE_FOURCC('I','4','2','0'), 12, 12,
|
||||||
{ GST_MAKE_FOURCC('R','G','B',' '), 32, 32, DEC_RGB32 },
|
GST_MAKE_FOURCC('I','4','2','0'), 0 },
|
||||||
{ GST_MAKE_FOURCC('R','G','B',' '), 24, 24, DEC_RGB24 },
|
{ GST_MAKE_FOURCC('I','Y','U','V'), 12, 12,
|
||||||
{ GST_MAKE_FOURCC('R','G','B',' '), 16, 16, DEC_RGB555 },
|
GST_MAKE_FOURCC('I','4','2','0'), 0 },
|
||||||
{ GST_MAKE_FOURCC('R','G','B',' '), 15, 16, DEC_RGB565 },
|
{ GST_MAKE_FOURCC('Y','V','1','2'), 12, 12,
|
||||||
{ 0, 0, 0 }
|
GST_MAKE_FOURCC('Y','V','1','2'), 0 },
|
||||||
|
{ GST_MAKE_FOURCC('R','G','B',' '), 32, 32,
|
||||||
|
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
|
||||||
|
GST_MAKE_FOURCC('A','B','G','R'), 32 },
|
||||||
|
#else
|
||||||
|
0, 32 },
|
||||||
|
#endif
|
||||||
|
{ GST_MAKE_FOURCC('R','G','B',' '), 24, 24,
|
||||||
|
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
|
||||||
|
GST_MAKE_FOURCC('A','B','G','R'), 24 },
|
||||||
|
#else
|
||||||
|
0, 24 },
|
||||||
|
#endif
|
||||||
|
{ GST_MAKE_FOURCC('R','G','B',' '), 16, 16,
|
||||||
|
3, 16 },
|
||||||
|
{ GST_MAKE_FOURCC('R','G','B',' '), 15, 16,
|
||||||
|
0, 16 },
|
||||||
|
{ 0, 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
|
@ -392,8 +393,9 @@ gst_divxdec_connect (GstPad *pad,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gst_pad_try_set_caps(divxdec->srcpad, caps) > 0) {
|
if (gst_pad_try_set_caps(divxdec->srcpad, caps) > 0) {
|
||||||
divxdec->csp = fmt_list[i].csp;
|
divxdec->csp = fmt_list[i].csp;
|
||||||
divxdec->bpp = fmt_list[i].bpp;
|
divxdec->bpp = fmt_list[i].bpp;
|
||||||
|
divxdec->bitcnt = fmt_list[i].bitcnt;
|
||||||
if (gst_divxdec_setup(divxdec))
|
if (gst_divxdec_setup(divxdec))
|
||||||
return GST_PAD_LINK_OK;
|
return GST_PAD_LINK_OK;
|
||||||
}
|
}
|
||||||
|
@ -409,6 +411,15 @@ plugin_init (GModule *module,
|
||||||
GstPlugin *plugin)
|
GstPlugin *plugin)
|
||||||
{
|
{
|
||||||
GstElementFactory *factory;
|
GstElementFactory *factory;
|
||||||
|
int lib_version;
|
||||||
|
|
||||||
|
lib_version = decore(NULL, DEC_OPT_VERSION, 0, 0);
|
||||||
|
if (lib_version != DECORE_VERSION) {
|
||||||
|
g_warning("Version mismatch! This plugin was compiled for "
|
||||||
|
"DivX version %d, while your library has version %d!",
|
||||||
|
DECORE_VERSION, lib_version);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* create an elementfactory for the v4lmjpegsrcparse element */
|
/* create an elementfactory for the v4lmjpegsrcparse element */
|
||||||
factory = gst_element_factory_new("divxdec", GST_TYPE_DIVXDEC,
|
factory = gst_element_factory_new("divxdec", GST_TYPE_DIVXDEC,
|
||||||
|
|
|
@ -50,10 +50,10 @@ struct _GstDivxDec {
|
||||||
|
|
||||||
/* divx handle */
|
/* divx handle */
|
||||||
void *handle;
|
void *handle;
|
||||||
DEC_BUFFERS bufinfo;
|
|
||||||
|
|
||||||
/* video (output) settings */
|
/* video (output) settings */
|
||||||
int csp, bpp;
|
guint32 csp;
|
||||||
|
int bitcnt, bpp;
|
||||||
int width, height;
|
int width, height;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,8 @@ enum {
|
||||||
ARG_0,
|
ARG_0,
|
||||||
ARG_BITRATE,
|
ARG_BITRATE,
|
||||||
ARG_MAXKEYINTERVAL,
|
ARG_MAXKEYINTERVAL,
|
||||||
ARG_BUFSIZE
|
ARG_BUFSIZE,
|
||||||
|
ARG_QUALITY
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -102,6 +103,39 @@ static GstElementClass *parent_class = NULL;
|
||||||
static guint gst_divxenc_signals[LAST_SIGNAL] = { 0 };
|
static guint gst_divxenc_signals[LAST_SIGNAL] = { 0 };
|
||||||
|
|
||||||
|
|
||||||
|
static gchar *
|
||||||
|
gst_divxenc_error (int errorcode)
|
||||||
|
{
|
||||||
|
gchar *error;
|
||||||
|
|
||||||
|
switch (errorcode) {
|
||||||
|
case ENC_BUFFER:
|
||||||
|
error = "Invalid buffer";
|
||||||
|
break;
|
||||||
|
case ENC_FAIL:
|
||||||
|
error = "Operation failed";
|
||||||
|
break;
|
||||||
|
case ENC_OK:
|
||||||
|
error = "No error";
|
||||||
|
break;
|
||||||
|
case ENC_MEMORY:
|
||||||
|
error = "Bad memory location";
|
||||||
|
break;
|
||||||
|
case ENC_BAD_FORMAT:
|
||||||
|
error = "Invalid format";
|
||||||
|
break;
|
||||||
|
case ENC_INTERNAL:
|
||||||
|
error = "Internal error";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error = "Unknown error";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
GType
|
GType
|
||||||
gst_divxenc_get_type(void)
|
gst_divxenc_get_type(void)
|
||||||
{
|
{
|
||||||
|
@ -152,7 +186,12 @@ gst_divxenc_class_init (GstDivxEncClass *klass)
|
||||||
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_BUFSIZE,
|
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_BUFSIZE,
|
||||||
g_param_spec_ulong("buffer_size", "Buffer Size",
|
g_param_spec_ulong("buffer_size", "Buffer Size",
|
||||||
"Size of the video buffers",
|
"Size of the video buffers",
|
||||||
0,G_MAXULONG,0,G_PARAM_READWRITE));
|
0,G_MAXULONG,0,G_PARAM_READABLE));
|
||||||
|
|
||||||
|
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_QUALITY,
|
||||||
|
g_param_spec_int("quality", "Quality",
|
||||||
|
"Amount of Motion Estimation",
|
||||||
|
1,5,3,G_PARAM_READWRITE));
|
||||||
|
|
||||||
gobject_class->set_property = gst_divxenc_set_property;
|
gobject_class->set_property = gst_divxenc_set_property;
|
||||||
gobject_class->get_property = gst_divxenc_get_property;
|
gobject_class->get_property = gst_divxenc_get_property;
|
||||||
|
@ -187,10 +226,11 @@ gst_divxenc_init (GstDivxEnc *divxenc)
|
||||||
gst_element_add_pad(GST_ELEMENT(divxenc), divxenc->srcpad);
|
gst_element_add_pad(GST_ELEMENT(divxenc), divxenc->srcpad);
|
||||||
|
|
||||||
/* bitrate, etc. */
|
/* bitrate, etc. */
|
||||||
divxenc->width = divxenc->height = divxenc->csp = -1;
|
divxenc->width = divxenc->height = divxenc->csp = divxenc->bitcnt = -1;
|
||||||
divxenc->bitrate = 512 * 1024;
|
divxenc->bitrate = 512 * 1024;
|
||||||
divxenc->max_key_interval = -1; /* default - 2*fps */
|
divxenc->max_key_interval = -1; /* default - 2*fps */
|
||||||
divxenc->buffer_size = 512 * 1024;
|
divxenc->buffer_size = 512 * 1024;
|
||||||
|
divxenc->quality = 3;
|
||||||
|
|
||||||
/* set divx handle to NULL */
|
/* set divx handle to NULL */
|
||||||
divxenc->handle = NULL;
|
divxenc->handle = NULL;
|
||||||
|
@ -200,43 +240,63 @@ gst_divxenc_init (GstDivxEnc *divxenc)
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_divxenc_setup (GstDivxEnc *divxenc)
|
gst_divxenc_setup (GstDivxEnc *divxenc)
|
||||||
{
|
{
|
||||||
ENC_PARAM xenc;
|
void *handle;
|
||||||
|
SETTINGS output;
|
||||||
|
DivXBitmapInfoHeader input;
|
||||||
gdouble fps;
|
gdouble fps;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
fps = gst_video_frame_rate(GST_PAD_PEER(divxenc->sinkpad));
|
fps = gst_video_frame_rate(GST_PAD_PEER(divxenc->sinkpad));
|
||||||
|
|
||||||
/* set it up */
|
/* set it up */
|
||||||
memset(&xenc, 0, sizeof(ENC_PARAM));
|
memset(&input, 0, sizeof(DivXBitmapInfoHeader));
|
||||||
xenc.x_dim = divxenc->width;
|
input.biSize = sizeof(DivXBitmapInfoHeader);
|
||||||
xenc.y_dim = divxenc->height;
|
input.biWidth = divxenc->width;
|
||||||
xenc.framerate = fps;
|
input.biHeight = divxenc->height;
|
||||||
|
input.biBitCount = divxenc->bitcnt;
|
||||||
|
input.biCompression = divxenc->csp;
|
||||||
|
|
||||||
xenc.rc_period = 2000;
|
memset(&output, 0, sizeof(SETTINGS));
|
||||||
xenc.rc_reaction_period = 10;
|
output.vbr_mode = 0;
|
||||||
xenc.rc_reaction_ratio = 20;
|
output.bitrate = divxenc->bitrate;
|
||||||
|
output.quantizer = 0;
|
||||||
|
output.use_bidirect = 0;
|
||||||
|
output.input_clock = 0;
|
||||||
|
output.input_frame_period = 1000000;
|
||||||
|
output.internal_timescale = fps * 1000000;
|
||||||
|
output.max_key_interval = (divxenc->max_key_interval == -1) ?
|
||||||
|
(2 * fps) :
|
||||||
|
divxenc->max_key_interval;
|
||||||
|
output.key_frame_threshold = 0;
|
||||||
|
output.vbv_bitrate = 0;
|
||||||
|
output.vbv_size = 0;
|
||||||
|
output.vbv_occupancy = 0;
|
||||||
|
output.complexity_modulation = 0;
|
||||||
|
output.deinterlace = 0;
|
||||||
|
output.quality = divxenc->quality;
|
||||||
|
output.data_partitioning = 0;
|
||||||
|
output.quarter_pel = 0;
|
||||||
|
output.use_gmc = 0;
|
||||||
|
output.psychovisual = 0;
|
||||||
|
output.pv_strength_frame = 0;
|
||||||
|
output.pv_strength_MB = 0;
|
||||||
|
output.interlace_mode = 0;
|
||||||
|
output.enable_crop = 0;
|
||||||
|
output.enable_resize = 0;
|
||||||
|
output.temporal_enable = 0;
|
||||||
|
output.spatial_passes = 0;
|
||||||
|
|
||||||
xenc.max_quantizer = 31;
|
if ((ret = encore(&handle, ENC_OPT_INIT, &input, &output))) {
|
||||||
xenc.min_quantizer = 1;
|
|
||||||
|
|
||||||
xenc.quality = 3;
|
|
||||||
xenc.bitrate = divxenc->bitrate;
|
|
||||||
|
|
||||||
xenc.deinterlace = 0;
|
|
||||||
|
|
||||||
xenc.max_key_interval = (divxenc->max_key_interval == -1) ?
|
|
||||||
(2 * xenc.framerate) :
|
|
||||||
divxenc->max_key_interval;
|
|
||||||
xenc.handle = NULL;
|
|
||||||
|
|
||||||
if ((ret = encore(NULL, ENC_OPT_INIT, &xenc, NULL))) {
|
|
||||||
gst_element_error(GST_ELEMENT(divxenc),
|
gst_element_error(GST_ELEMENT(divxenc),
|
||||||
"Error setting up divx encoder: %d\n",
|
"Error setting up divx encoder: %s (%d)",
|
||||||
ret);
|
gst_divxenc_error(ret), ret);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
divxenc->handle = xenc.handle;
|
divxenc->handle = handle;
|
||||||
|
|
||||||
|
/* set buffer size to theoretical limit (see docs on divx.com) */
|
||||||
|
divxenc->buffer_size = 6 * divxenc->width * divxenc->height;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -245,8 +305,10 @@ gst_divxenc_setup (GstDivxEnc *divxenc)
|
||||||
static void
|
static void
|
||||||
gst_divxenc_unset (GstDivxEnc *divxenc)
|
gst_divxenc_unset (GstDivxEnc *divxenc)
|
||||||
{
|
{
|
||||||
encore(divxenc->handle, ENC_OPT_RELEASE, NULL, NULL);
|
if (divxenc->handle) {
|
||||||
divxenc->handle = NULL;
|
encore(divxenc, ENC_OPT_RELEASE, NULL, NULL);
|
||||||
|
divxenc->handle = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -289,19 +351,19 @@ gst_divxenc_chain (GstPad *pad,
|
||||||
xframe.image = GST_BUFFER_DATA(buf);
|
xframe.image = GST_BUFFER_DATA(buf);
|
||||||
xframe.bitstream = (void *) GST_BUFFER_DATA(outbuf);
|
xframe.bitstream = (void *) GST_BUFFER_DATA(outbuf);
|
||||||
xframe.length = GST_BUFFER_MAXSIZE(outbuf);
|
xframe.length = GST_BUFFER_MAXSIZE(outbuf);
|
||||||
xframe.mvs = NULL;
|
xframe.produce_empty_frame = 0;
|
||||||
xframe.colorspace = divxenc->csp;
|
|
||||||
|
|
||||||
if ((ret = encore(divxenc->handle, ENC_OPT_ENCODE,
|
if ((ret = encore(divxenc->handle, ENC_OPT_ENCODE,
|
||||||
&xframe, &xres))) {
|
&xframe, &xres))) {
|
||||||
gst_element_error(GST_ELEMENT(divxenc),
|
gst_element_error(GST_ELEMENT(divxenc),
|
||||||
"Error encoding divx frame: %d\n", ret);
|
"Error encoding divx frame: %s (%d)",
|
||||||
|
gst_divxenc_error(ret), ret);
|
||||||
gst_buffer_unref(buf);
|
gst_buffer_unref(buf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_BUFFER_SIZE(outbuf) = xframe.length;
|
GST_BUFFER_SIZE(outbuf) = xframe.length;
|
||||||
if (xres.is_key_frame)
|
if (xres.cType == 'I')
|
||||||
GST_BUFFER_FLAG_SET(outbuf, GST_BUFFER_KEY_UNIT);
|
GST_BUFFER_FLAG_SET(outbuf, GST_BUFFER_KEY_UNIT);
|
||||||
|
|
||||||
/* go out, multiply! */
|
/* go out, multiply! */
|
||||||
|
@ -325,9 +387,7 @@ gst_divxenc_connect (GstPad *pad,
|
||||||
divxenc = GST_DIVXENC(gst_pad_get_parent (pad));
|
divxenc = GST_DIVXENC(gst_pad_get_parent (pad));
|
||||||
|
|
||||||
/* if there's something old around, remove it */
|
/* if there's something old around, remove it */
|
||||||
if (divxenc->handle) {
|
gst_divxenc_unset(divxenc);
|
||||||
gst_divxenc_unset(divxenc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we are not going to act on variable caps */
|
/* we are not going to act on variable caps */
|
||||||
if (!GST_CAPS_IS_FIXED(vscaps))
|
if (!GST_CAPS_IS_FIXED(vscaps))
|
||||||
|
@ -336,7 +396,8 @@ gst_divxenc_connect (GstPad *pad,
|
||||||
for (caps = vscaps; caps != NULL; caps = caps->next) {
|
for (caps = vscaps; caps != NULL; caps = caps->next) {
|
||||||
int w,h,d;
|
int w,h,d;
|
||||||
guint32 fourcc;
|
guint32 fourcc;
|
||||||
gint divx_cs;
|
guint32 divx_cs;
|
||||||
|
gint bitcnt = 0;
|
||||||
gst_caps_get_int(caps, "width", &w);
|
gst_caps_get_int(caps, "width", &w);
|
||||||
gst_caps_get_int(caps, "height", &h);
|
gst_caps_get_int(caps, "height", &h);
|
||||||
gst_caps_get_fourcc_int(caps, "format", &fourcc);
|
gst_caps_get_fourcc_int(caps, "format", &fourcc);
|
||||||
|
@ -344,25 +405,31 @@ gst_divxenc_connect (GstPad *pad,
|
||||||
switch (fourcc) {
|
switch (fourcc) {
|
||||||
case GST_MAKE_FOURCC('I','4','2','0'):
|
case GST_MAKE_FOURCC('I','4','2','0'):
|
||||||
case GST_MAKE_FOURCC('I','Y','U','V'):
|
case GST_MAKE_FOURCC('I','Y','U','V'):
|
||||||
divx_cs = ENC_CSP_I420;
|
divx_cs = GST_MAKE_FOURCC('I','4','2','0');
|
||||||
break;
|
break;
|
||||||
case GST_MAKE_FOURCC('Y','U','Y','2'):
|
case GST_MAKE_FOURCC('Y','U','Y','2'):
|
||||||
divx_cs = ENC_CSP_YUY2;
|
case GST_MAKE_FOURCC('Y','U','Y','V'):
|
||||||
|
divx_cs = GST_MAKE_FOURCC('Y','U','Y','2');
|
||||||
break;
|
break;
|
||||||
case GST_MAKE_FOURCC('Y','V','1','2'):
|
case GST_MAKE_FOURCC('Y','V','1','2'):
|
||||||
divx_cs = ENC_CSP_YV12;
|
divx_cs = GST_MAKE_FOURCC('Y','V','1','2');
|
||||||
|
break;
|
||||||
|
case GST_MAKE_FOURCC('Y','V','Y','U'):
|
||||||
|
divx_cs = GST_MAKE_FOURCC('Y','V','Y','U');
|
||||||
break;
|
break;
|
||||||
case GST_MAKE_FOURCC('U','Y','V','Y'):
|
case GST_MAKE_FOURCC('U','Y','V','Y'):
|
||||||
divx_cs = ENC_CSP_UYVY;
|
divx_cs = GST_MAKE_FOURCC('U','Y','V','Y');
|
||||||
break;
|
break;
|
||||||
case GST_MAKE_FOURCC('R','G','B',' '):
|
case GST_MAKE_FOURCC('R','G','B',' '):
|
||||||
gst_caps_get_int(caps, "depth", &d);
|
gst_caps_get_int(caps, "depth", &d);
|
||||||
switch (d) {
|
switch (d) {
|
||||||
case 24:
|
case 24:
|
||||||
divx_cs = ENC_CSP_RGB24;
|
divx_cs = 0;
|
||||||
|
bitcnt = 24;
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 32:
|
||||||
divx_cs = ENC_CSP_RGB32;
|
divx_cs = 0;
|
||||||
|
bitcnt = 32;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto trynext;
|
goto trynext;
|
||||||
|
@ -376,6 +443,7 @@ gst_divxenc_connect (GstPad *pad,
|
||||||
* linking, so we accept here, get the fps on
|
* linking, so we accept here, get the fps on
|
||||||
* the first cycle and set it all up then */
|
* the first cycle and set it all up then */
|
||||||
divxenc->csp = divx_cs;
|
divxenc->csp = divx_cs;
|
||||||
|
divxenc->bitcnt = bitcnt;
|
||||||
divxenc->width = w;
|
divxenc->width = w;
|
||||||
divxenc->height = h;
|
divxenc->height = h;
|
||||||
return gst_pad_try_set_caps(divxenc->srcpad,
|
return gst_pad_try_set_caps(divxenc->srcpad,
|
||||||
|
@ -409,12 +477,12 @@ gst_divxenc_set_property (GObject *object,
|
||||||
case ARG_BITRATE:
|
case ARG_BITRATE:
|
||||||
divxenc->bitrate = g_value_get_ulong(value);
|
divxenc->bitrate = g_value_get_ulong(value);
|
||||||
break;
|
break;
|
||||||
case ARG_BUFSIZE:
|
|
||||||
divxenc->buffer_size = g_value_get_ulong(value);
|
|
||||||
break;
|
|
||||||
case ARG_MAXKEYINTERVAL:
|
case ARG_MAXKEYINTERVAL:
|
||||||
divxenc->max_key_interval = g_value_get_int(value);
|
divxenc->max_key_interval = g_value_get_int(value);
|
||||||
break;
|
break;
|
||||||
|
case ARG_QUALITY:
|
||||||
|
divxenc->quality = g_value_get_int(value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -444,6 +512,9 @@ gst_divxenc_get_property (GObject *object,
|
||||||
case ARG_MAXKEYINTERVAL:
|
case ARG_MAXKEYINTERVAL:
|
||||||
g_value_set_int(value, divxenc->max_key_interval);
|
g_value_set_int(value, divxenc->max_key_interval);
|
||||||
break;
|
break;
|
||||||
|
case ARG_QUALITY:
|
||||||
|
g_value_set_int(value, divxenc->quality);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -456,6 +527,15 @@ plugin_init (GModule *module,
|
||||||
GstPlugin *plugin)
|
GstPlugin *plugin)
|
||||||
{
|
{
|
||||||
GstElementFactory *factory;
|
GstElementFactory *factory;
|
||||||
|
int lib_version;
|
||||||
|
|
||||||
|
lib_version = encore(NULL, ENC_OPT_VERSION, 0, 0);
|
||||||
|
if (lib_version != ENCORE_VERSION) {
|
||||||
|
g_warning("Version mismatch! This plugin was compiled for "
|
||||||
|
"DivX version %d, while your library has version %d!",
|
||||||
|
ENCORE_VERSION, lib_version);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (!gst_library_load("gstvideo"))
|
if (!gst_library_load("gstvideo"))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
|
@ -56,10 +56,14 @@ struct _GstDivxEnc {
|
||||||
/* max key interval */
|
/* max key interval */
|
||||||
gint max_key_interval;
|
gint max_key_interval;
|
||||||
|
|
||||||
|
/* amount of motion estimation to do */
|
||||||
|
gint quality;
|
||||||
|
|
||||||
/* divx handle */
|
/* divx handle */
|
||||||
void *handle;
|
void *handle;
|
||||||
int csp;
|
guint32 csp;
|
||||||
int width, height;
|
gint bitcnt;
|
||||||
|
gint width, height;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstDivxEncClass {
|
struct _GstDivxEncClass {
|
||||||
|
|
Loading…
Reference in a new issue