|
Packit |
bc1512 |
/* This file is an image processing operation for GEGL
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* GEGL is free software; you can redistribute it and/or
|
|
Packit |
bc1512 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
bc1512 |
* License as published by the Free Software Foundation; either
|
|
Packit |
bc1512 |
* version 3 of the License, or (at your option) any later version.
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* GEGL is distributed in the hope that it will be useful,
|
|
Packit |
bc1512 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
bc1512 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
bc1512 |
* Lesser General Public License for more details.
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
bc1512 |
* License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* Copyright 2003, 2006 Øyvind Kolås <pippin@gimp.org>
|
|
Packit |
bc1512 |
*/
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#include "config.h"
|
|
Packit |
bc1512 |
#include <glib/gi18n-lib.h>
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#ifdef GEGL_CHANT_PROPERTIES
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl_chant_file_path (path, _("File"), "/home/pippin/input.avi", _("Path of file to load"))
|
|
Packit |
bc1512 |
gegl_chant_int (frame, _("Frame"), 0, 1000000, 0, _("Frame number"))
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#else
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#define GEGL_CHANT_TYPE_SOURCE
|
|
Packit |
bc1512 |
#define GEGL_CHANT_C_FILE "ff-load.c"
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#include "gegl-chant.h"
|
|
Packit |
bc1512 |
#include <errno.h>
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#ifdef HAVE_LIBAVFORMAT_AVFORMAT_H
|
|
Packit |
bc1512 |
#include <libavformat/avformat.h>
|
|
Packit |
bc1512 |
#else
|
|
Packit |
bc1512 |
#include <avformat.h>
|
|
Packit |
bc1512 |
#endif
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
typedef struct
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gdouble frames;
|
|
Packit |
bc1512 |
gint width;
|
|
Packit |
bc1512 |
gint height;
|
|
Packit |
bc1512 |
gdouble fps;
|
|
Packit |
bc1512 |
gchar *codec_name;
|
|
Packit |
bc1512 |
gchar *fourcc;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
int video_stream;
|
|
Packit |
bc1512 |
AVFormatContext *ic;
|
|
Packit |
bc1512 |
AVStream *video_st;
|
|
Packit |
bc1512 |
AVCodecContext *enc;
|
|
Packit |
bc1512 |
AVCodec *codec;
|
|
Packit |
bc1512 |
AVPacket pkt;
|
|
Packit |
bc1512 |
AVFrame *lavc_frame;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
glong coded_bytes;
|
|
Packit |
bc1512 |
guchar *coded_buf;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gchar *loadedfilename; /* to remember which file is "cached" */
|
|
Packit |
bc1512 |
glong prevframe; /* previously decoded frame in loadedfile */
|
|
Packit |
bc1512 |
} Priv;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
print_error (const char *filename, int err)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
switch (err)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
#if LIBAVFORMAT_VERSION_MAJOR >= 53
|
|
Packit |
bc1512 |
case AVERROR(EINVAL):
|
|
Packit |
bc1512 |
#else
|
|
Packit |
bc1512 |
case AVERROR_NUMEXPECTED:
|
|
Packit |
bc1512 |
#endif
|
|
Packit |
bc1512 |
g_warning ("%s: Incorrect image filename syntax.\n"
|
|
Packit |
bc1512 |
"Use '%%d' to specify the image number:\n"
|
|
Packit |
bc1512 |
" for img1.jpg, img2.jpg, ..., use 'img%%d.jpg';\n"
|
|
Packit |
bc1512 |
" for img001.jpg, img002.jpg, ..., use 'img%%03d.jpg'.\n",
|
|
Packit |
bc1512 |
filename);
|
|
Packit |
bc1512 |
break;
|
|
Packit |
bc1512 |
case AVERROR_INVALIDDATA:
|
|
Packit |
bc1512 |
#if LIBAVFORMAT_VERSION_MAJOR >= 53
|
|
Packit |
bc1512 |
g_warning ("%s: Error while parsing header or unknown format\n", filename);
|
|
Packit |
bc1512 |
#else
|
|
Packit |
bc1512 |
g_warning ("%s: Error while parsing header\n", filename);
|
|
Packit |
bc1512 |
break;
|
|
Packit |
bc1512 |
case AVERROR_NOFMT:
|
|
Packit |
bc1512 |
g_warning ("%s: Unknown format\n", filename);
|
|
Packit |
bc1512 |
#endif
|
|
Packit |
bc1512 |
break;
|
|
Packit |
bc1512 |
default:
|
|
Packit |
bc1512 |
g_warning ("%s: Error while opening file\n", filename);
|
|
Packit |
bc1512 |
break;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
init (GeglChantO *o)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
static gint inited = 0; /*< this is actually meant to be static, only to be done once */
|
|
Packit |
bc1512 |
Priv *p = (Priv*)o->chant_data;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (p==NULL)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
p = g_new0 (Priv, 1);
|
|
Packit |
bc1512 |
o->chant_data = (void*) p;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
p->width = 320;
|
|
Packit |
bc1512 |
p->height = 200;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (!inited)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
av_register_all ();
|
|
Packit |
bc1512 |
avcodec_register_all ();
|
|
Packit |
bc1512 |
inited = 1;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
p->loadedfilename = g_strdup ("");
|
|
Packit |
bc1512 |
p->fourcc = g_strdup ("");
|
|
Packit |
bc1512 |
p->codec_name = g_strdup ("");
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* FIXME: probably some more stuff to free here */
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
ff_cleanup (GeglChantO *o)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
Priv *p = (Priv*)o->chant_data;
|
|
Packit |
bc1512 |
if (p)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (p->codec_name)
|
|
Packit |
bc1512 |
g_free (p->codec_name);
|
|
Packit |
bc1512 |
if (p->loadedfilename)
|
|
Packit |
bc1512 |
g_free (p->loadedfilename);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (p->enc)
|
|
Packit |
bc1512 |
avcodec_close (p->enc);
|
|
Packit |
bc1512 |
if (p->ic)
|
|
Packit |
bc1512 |
av_close_input_file (p->ic);
|
|
Packit |
bc1512 |
if (p->lavc_frame)
|
|
Packit |
bc1512 |
av_free (p->lavc_frame);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
p->enc = NULL;
|
|
Packit |
bc1512 |
p->ic = NULL;
|
|
Packit |
bc1512 |
p->lavc_frame = NULL;
|
|
Packit |
bc1512 |
p->codec_name = NULL;
|
|
Packit |
bc1512 |
p->loadedfilename = NULL;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static glong
|
|
Packit |
bc1512 |
prev_keyframe (Priv *priv, glong frame)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
/* no way to detect previous keyframe at the moment for ffmpeg,
|
|
Packit |
bc1512 |
so we'll just return 0, the first, and a forced reload happens
|
|
Packit |
bc1512 |
if needed
|
|
Packit |
bc1512 |
*/
|
|
Packit |
bc1512 |
return 0;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static int
|
|
Packit |
bc1512 |
decode_frame (GeglOperation *operation,
|
|
Packit |
bc1512 |
glong frame)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
|
|
Packit |
bc1512 |
Priv *p = (Priv*)o->chant_data;
|
|
Packit |
bc1512 |
glong prevframe = p->prevframe;
|
|
Packit |
bc1512 |
glong decodeframe; /*< frame to be requested decoded */
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (frame >= p->frames)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
frame = p->frames - 1;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (frame < 0)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
frame = 0;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (frame == prevframe)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
return 0;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* figure out which frame we should start decoding at */
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (frame == prevframe + 1)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
decodeframe = prevframe + 1;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
decodeframe = prev_keyframe (p, frame);
|
|
Packit |
bc1512 |
if (prevframe > decodeframe && prevframe < frame)
|
|
Packit |
bc1512 |
decodeframe = prevframe + 1;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (decodeframe < prevframe)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
/* seeking backwards, since it ffmpeg doesn't allow us,. we'll reload the file */
|
|
Packit |
bc1512 |
g_free (p->loadedfilename);
|
|
Packit |
bc1512 |
p->loadedfilename = NULL;
|
|
Packit |
bc1512 |
init (o);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
while (decodeframe <= frame)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
int got_picture = 0;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
do
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
int decoded_bytes;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (p->coded_bytes <= 0)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
do
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (av_read_packet (p->ic, &p->pkt) < 0)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
fprintf (stderr, "av_read_packet failed for %s\n",
|
|
Packit |
bc1512 |
o->path);
|
|
Packit |
bc1512 |
return -1;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
while (p->pkt.stream_index != p->video_stream);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
p->coded_bytes = p->pkt.size;
|
|
Packit |
bc1512 |
p->coded_buf = p->pkt.data;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
decoded_bytes =
|
|
Packit |
bc1512 |
avcodec_decode_video2 (p->video_st->codec, p->lavc_frame,
|
|
Packit |
bc1512 |
&got_picture, &p->pkt);
|
|
Packit |
bc1512 |
if (decoded_bytes < 0)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
fprintf (stderr, "avcodec_decode_video failed for %s\n",
|
|
Packit |
bc1512 |
o->path);
|
|
Packit |
bc1512 |
return -1;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
p->coded_buf += decoded_bytes;
|
|
Packit |
bc1512 |
p->coded_bytes -= decoded_bytes;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
while (!got_picture);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
decodeframe++;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
p->prevframe = frame;
|
|
Packit |
bc1512 |
return 0;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
prepare (GeglOperation *operation)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
|
|
Packit |
bc1512 |
Priv *p = (Priv*)o->chant_data;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (p == NULL)
|
|
Packit |
bc1512 |
init (o);
|
|
Packit |
bc1512 |
p = (Priv*)o->chant_data;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_assert (o->chant_data != NULL);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl_operation_set_format (operation, "output", babl_format ("R'G'B'A u8"));
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (!p->loadedfilename ||
|
|
Packit |
bc1512 |
strcmp (p->loadedfilename, o->path))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gint i;
|
|
Packit |
bc1512 |
gint err;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
ff_cleanup (o);
|
|
Packit |
bc1512 |
err = av_open_input_file (&p->ic, o->path, NULL, 0, NULL);
|
|
Packit |
bc1512 |
if (err < 0)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
print_error (o->path, err);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
err = av_find_stream_info (p->ic);
|
|
Packit |
bc1512 |
if (err < 0)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_warning ("ff-load: error finding stream info for %s", o->path);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
return;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
for (i = 0; i< p->ic->nb_streams; i++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
AVCodecContext *c = p->ic->streams[i]->codec;
|
|
Packit |
bc1512 |
#if LIBAVFORMAT_VERSION_MAJOR >= 53
|
|
Packit |
bc1512 |
if (c->codec_type == AVMEDIA_TYPE_VIDEO)
|
|
Packit |
bc1512 |
#else
|
|
Packit |
bc1512 |
if (c->codec_type == CODEC_TYPE_VIDEO)
|
|
Packit |
bc1512 |
#endif
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
p->video_st = p->ic->streams[i];
|
|
Packit |
bc1512 |
p->video_stream = i;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
p->enc = p->video_st->codec;
|
|
Packit |
bc1512 |
p->codec = avcodec_find_decoder (p->enc->codec_id);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* p->enc->error_resilience = 2; */
|
|
Packit |
bc1512 |
p->enc->error_concealment = 3;
|
|
Packit |
bc1512 |
p->enc->workaround_bugs = FF_BUG_AUTODETECT;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (p->codec == NULL)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_warning ("codec not found");
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (p->codec->capabilities & CODEC_CAP_TRUNCATED)
|
|
Packit |
bc1512 |
p->enc->flags |= CODEC_FLAG_TRUNCATED;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (avcodec_open (p->enc, p->codec) < 0)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_warning ("error opening codec %s", p->enc->codec->name);
|
|
Packit |
bc1512 |
return;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
p->width = p->enc->width;
|
|
Packit |
bc1512 |
p->height = p->enc->height;
|
|
Packit |
bc1512 |
p->frames = 10000000;
|
|
Packit |
bc1512 |
p->lavc_frame = avcodec_alloc_frame ();
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (p->fourcc)
|
|
Packit |
bc1512 |
g_free (p->fourcc);
|
|
Packit |
bc1512 |
p->fourcc = g_strdup ("none");
|
|
Packit |
bc1512 |
p->fourcc[0] = (p->enc->codec_tag) & 0xff;
|
|
Packit |
bc1512 |
p->fourcc[1] = (p->enc->codec_tag >> 8) & 0xff;
|
|
Packit |
bc1512 |
p->fourcc[2] = (p->enc->codec_tag >> 16) & 0xff;
|
|
Packit |
bc1512 |
p->fourcc[3] = (p->enc->codec_tag >> 24) & 0xff;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (p->codec_name)
|
|
Packit |
bc1512 |
g_free (p->codec_name);
|
|
Packit |
bc1512 |
if (p->codec->name)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
p->codec_name = g_strdup (p->codec->name);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
p->codec_name = g_strdup ("");
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (p->loadedfilename)
|
|
Packit |
bc1512 |
g_free (p->loadedfilename);
|
|
Packit |
bc1512 |
p->loadedfilename = g_strdup (o->path);
|
|
Packit |
bc1512 |
p->prevframe = -1;
|
|
Packit |
bc1512 |
p->coded_bytes = 0;
|
|
Packit |
bc1512 |
p->coded_buf = NULL;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static GeglRectangle
|
|
Packit |
bc1512 |
get_bounding_box (GeglOperation *operation)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglRectangle result = {0,0,320,200};
|
|
Packit |
bc1512 |
Priv *p = (Priv*)GEGL_CHANT_PROPERTIES (operation)->chant_data;
|
|
Packit |
bc1512 |
result.width = p->width;
|
|
Packit |
bc1512 |
result.height = p->height;
|
|
Packit |
bc1512 |
return result;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static gboolean
|
|
Packit |
bc1512 |
process (GeglOperation *operation,
|
|
Packit |
bc1512 |
GeglBuffer *output,
|
|
Packit |
bc1512 |
const GeglRectangle *result,
|
|
Packit |
bc1512 |
gint level)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
|
|
Packit |
bc1512 |
Priv *p = (Priv*)o->chant_data;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (p->ic && !decode_frame (operation, o->frame))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
guchar *buf;
|
|
Packit |
bc1512 |
gint pxsize;
|
|
Packit |
bc1512 |
gint x,y;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_object_get (output, "px-size", &pxsize, NULL);
|
|
Packit |
bc1512 |
buf = g_new (guchar, p->width * p->height * pxsize);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
for (y=0; y < p->height; y++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
guchar *dst = buf + y * p->width * 4;
|
|
Packit |
bc1512 |
const guchar *ysrc = p->lavc_frame->data[0] + y * p->lavc_frame->linesize[0];
|
|
Packit |
bc1512 |
const guchar *usrc = p->lavc_frame->data[1] + y/2 * p->lavc_frame->linesize[1];
|
|
Packit |
bc1512 |
const guchar *vsrc = p->lavc_frame->data[2] + y/2 * p->lavc_frame->linesize[2];
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
for (x=0;x < p->width; x++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gint R,G,B;
|
|
Packit |
bc1512 |
#ifndef byteclamp
|
|
Packit |
bc1512 |
#define byteclamp(j) do{if(j<0)j=0; else if(j>255)j=255;}while(0)
|
|
Packit |
bc1512 |
#endif
|
|
Packit |
bc1512 |
#define YUV82RGB8(Y,U,V,R,G,B)do{\
|
|
Packit |
bc1512 |
R= ((Y<<15) + 37355*(V-128))>>15;\
|
|
Packit |
bc1512 |
G= ((Y<<15) -12911* (U-128) - 19038*(V-128))>>15;\
|
|
Packit |
bc1512 |
B= ((Y<<15) +66454* (U-128) )>>15;\
|
|
Packit |
bc1512 |
byteclamp(R);\
|
|
Packit |
bc1512 |
byteclamp(G);\
|
|
Packit |
bc1512 |
byteclamp(B);\
|
|
Packit |
bc1512 |
} while(0)
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
YUV82RGB8 (*ysrc, *usrc, *vsrc, R, G, B);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
*(unsigned int *) dst = R + G * 256 + B * 256 * 256 + 0xff000000;
|
|
Packit |
bc1512 |
dst += 4;
|
|
Packit |
bc1512 |
ysrc ++;
|
|
Packit |
bc1512 |
if (x % 2)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
usrc++;
|
|
Packit |
bc1512 |
vsrc++;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
gegl_buffer_set (output, NULL, 0, NULL, buf, GEGL_AUTO_ROWSTRIDE);
|
|
Packit |
bc1512 |
g_free (buf);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
return TRUE;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
finalize (GObject *object)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglChantO *o = GEGL_CHANT_PROPERTIES (object);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (o->chant_data)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
Priv *p = (Priv*)o->chant_data;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_free (p->loadedfilename);
|
|
Packit |
bc1512 |
g_free (p->fourcc);
|
|
Packit |
bc1512 |
g_free (p->codec_name);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_free (o->chant_data);
|
|
Packit |
bc1512 |
o->chant_data = NULL;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
G_OBJECT_CLASS (gegl_chant_parent_class)->finalize (object);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static GeglRectangle
|
|
Packit |
bc1512 |
get_cached_region (GeglOperation *operation,
|
|
Packit |
bc1512 |
const GeglRectangle *roi)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
return get_bounding_box (operation);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
gegl_chant_class_init (GeglChantClass *klass)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglOperationClass *operation_class;
|
|
Packit |
bc1512 |
GeglOperationSourceClass *source_class;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
G_OBJECT_CLASS (klass)->finalize = finalize;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
operation_class = GEGL_OPERATION_CLASS (klass);
|
|
Packit |
bc1512 |
source_class = GEGL_OPERATION_SOURCE_CLASS (klass);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
source_class->process = process;
|
|
Packit |
bc1512 |
operation_class->get_bounding_box = get_bounding_box;
|
|
Packit |
bc1512 |
operation_class->get_cached_region = get_cached_region;
|
|
Packit |
bc1512 |
operation_class->prepare = prepare;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl_operation_class_set_keys (operation_class,
|
|
Packit |
bc1512 |
"name" , "gegl:ff-load",
|
|
Packit |
bc1512 |
"categories" , "input:video",
|
|
Packit |
bc1512 |
"description" , _("FFmpeg video frame importer"),
|
|
Packit |
bc1512 |
NULL);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#endif
|