mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-31 11:32:38 +00:00
more fixes to the pixbuf loader. I can use it for thumbnailing nicely now
Original commit message from CVS: more fixes to the pixbuf loader. I can use it for thumbnailing nicely now
This commit is contained in:
parent
d8f78ea4a8
commit
dddf7c2b3e
2 changed files with 104 additions and 50 deletions
|
@ -179,9 +179,34 @@ gst_loader_load_animation (FILE *f, GError **error)
|
|||
GST_LOG_OBJECT (ani, "load_animation succeeded");
|
||||
return GDK_PIXBUF_ANIMATION (ani);
|
||||
}
|
||||
static GdkPixbuf *
|
||||
gst_loader_load (FILE *f, GError **error)
|
||||
{
|
||||
GdkPixbufAnimation *ani;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
ani = gst_loader_load_animation (f, error);
|
||||
if (ani == NULL)
|
||||
return NULL;
|
||||
|
||||
pixbuf = gdk_pixbuf_animation_get_static_image (ani);
|
||||
if (!pixbuf) {
|
||||
GST_ERROR_OBJECT (ani, "Could not get an image in _pixbuf_load");
|
||||
g_object_unref (ani);
|
||||
g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
|
||||
"Could not get an image from file.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_object_ref (pixbuf);
|
||||
g_object_unref (ani);
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
void
|
||||
fill_vtable (GdkPixbufModule *module)
|
||||
{
|
||||
module->load = gst_loader_load;
|
||||
module->begin_load = gst_loader_begin_load;
|
||||
module->load_increment = gst_loader_load_increment;
|
||||
module->stop_load = gst_loader_stop_load;
|
||||
|
@ -206,8 +231,9 @@ fill_info (GdkPixbufFormat *info)
|
|||
};
|
||||
|
||||
static gchar *mime_types[] = {
|
||||
"video/avi", "video/x-avi",
|
||||
"video/avi", "video/x-avi", "video/x-msvideo",
|
||||
"video/mpeg",
|
||||
"video/quicktime",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
@ -124,45 +124,6 @@ gst_gdk_animation_is_static_image (GdkPixbufAnimation *animation)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static GdkPixbuf*
|
||||
gst_gdk_animation_get_static_image (GdkPixbufAnimation *animation)
|
||||
{
|
||||
GstGdkAnimation *ani = GST_GDK_ANIMATION (animation);
|
||||
GTimeVal tv;
|
||||
|
||||
if (!ani->pixbuf) {
|
||||
GST_LOG_OBJECT (ani, "trying to create pixbuf");
|
||||
g_get_current_time (&tv);
|
||||
GdkPixbufAnimationIter *iter = gdk_pixbuf_animation_get_iter (animation, &tv);
|
||||
if (iter) {
|
||||
guint64 length;
|
||||
GstFormat time = GST_FORMAT_TIME;
|
||||
|
||||
if (!gst_element_query (gst_bin_get_by_name (GST_BIN (
|
||||
GST_GDK_ANIMATION_ITER (iter)->pipeline), "sink"),
|
||||
GST_QUERY_TOTAL, &time, &length)) {
|
||||
length = 0;
|
||||
}
|
||||
if (length > 120 * GST_SECOND) {
|
||||
length = 120 * GST_SECOND;
|
||||
} else if (length < 120 * GST_SECOND && length >= 10 * GST_SECOND) {
|
||||
length = length / 2;
|
||||
}
|
||||
g_assert (time == GST_FORMAT_TIME);
|
||||
if (length > 0)
|
||||
g_time_val_add (&tv, length * 1000 / GST_SECOND);
|
||||
GST_LOG_OBJECT (ani, "using time offset %"G_GUINT64_FORMAT" for creating static image",
|
||||
length);
|
||||
gdk_pixbuf_animation_iter_advance (GDK_PIXBUF_ANIMATION_ITER (iter), &tv);
|
||||
ani->pixbuf = gdk_pixbuf_animation_iter_get_pixbuf (iter);
|
||||
g_object_ref (ani->pixbuf);
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (ani, "Could not get an iterator. No pixbuf available");
|
||||
}
|
||||
}
|
||||
return ani->pixbuf;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_gdk_animation_get_size (GdkPixbufAnimation *anim, gint *width, int *height)
|
||||
{
|
||||
|
@ -238,8 +199,6 @@ gst_gdk_animation_iter_init (GTypeInstance *instance, gpointer g_class)
|
|||
|
||||
iter->buffers = g_queue_new ();
|
||||
iter->eos = FALSE;
|
||||
/* workaround for loads of demuxers that don't handle seeks before initializing... */
|
||||
iter->just_seeked = TRUE;
|
||||
}
|
||||
static void
|
||||
gst_gdk_animation_iter_finalize (GObject *object)
|
||||
|
@ -275,7 +234,7 @@ got_handoff (GstElement *fakesink, GstBuffer *buffer, GstPad *pad, GstGdkAnimati
|
|||
static gboolean
|
||||
gst_gdk_animation_iter_create_pipeline (GstGdkAnimationIter *iter)
|
||||
{
|
||||
GstElement *src, *autoplugger, *sink, *colorspace;
|
||||
GstElement *src, *typefind, *autoplugger, *sink, *colorspace;
|
||||
GstCaps *caps = GST_CAPS_NEW ("pixbuf_filter",
|
||||
"video/x-raw-rgb",
|
||||
"endianness", GST_PROPS_INT (G_BIG_ENDIAN),
|
||||
|
@ -304,10 +263,17 @@ gst_gdk_animation_iter_create_pipeline (GstGdkAnimationIter *iter)
|
|||
g_free (filename);
|
||||
}
|
||||
|
||||
/* add typefind for correct typefinding */
|
||||
if ((typefind = gst_element_factory_make ("typefind", "typefind"))) {
|
||||
gst_bin_add (GST_BIN (iter->pipeline), typefind);
|
||||
if (!gst_element_link (src, typefind))
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!(autoplugger = gst_element_factory_make ("spider", "autoplugger")))
|
||||
goto error;
|
||||
gst_bin_add (GST_BIN (iter->pipeline), autoplugger);
|
||||
if (!gst_element_link (src, autoplugger))
|
||||
if (!gst_element_link (typefind, autoplugger))
|
||||
goto error;
|
||||
|
||||
/* add ffcolorspace if available so we get svq1, too */
|
||||
|
@ -317,7 +283,6 @@ gst_gdk_animation_iter_create_pipeline (GstGdkAnimationIter *iter)
|
|||
goto error;
|
||||
autoplugger = colorspace;
|
||||
}
|
||||
|
||||
|
||||
if (!(colorspace = gst_element_factory_make ("colorspace", "colorspace")))
|
||||
goto error;
|
||||
|
@ -468,23 +433,23 @@ gst_gdk_animation_iter_advance (GdkPixbufAnimationIter *anim_iter, const GTimeVa
|
|||
GstGdkAnimationIter *iter = GST_GDK_ANIMATION_ITER (anim_iter);
|
||||
|
||||
/* compute timestamp that next buffer must match */
|
||||
GST_DEBUG_OBJECT (iter, "advancing to %ld:%ld (started at %ld:%ld)",
|
||||
current_time->tv_sec, current_time->tv_usec, iter->start.tv_sec, iter->start.tv_usec);
|
||||
offset = ((GstClockTime) current_time->tv_sec - iter->start.tv_sec) * GST_SECOND;
|
||||
if (iter->start.tv_usec > current_time->tv_usec) {
|
||||
offset -= ((GstClockTime) iter->start.tv_usec - current_time->tv_usec) * GST_SECOND / G_USEC_PER_SEC;
|
||||
} else {
|
||||
offset += ((GstClockTime) current_time->tv_usec - iter->start.tv_usec) * GST_SECOND / G_USEC_PER_SEC;
|
||||
}
|
||||
GST_DEBUG_OBJECT (iter, "advancing to %ld:%ld (started at %ld:%ld) need offset %"G_GUINT64_FORMAT,
|
||||
current_time->tv_sec, current_time->tv_usec, iter->start.tv_sec, iter->start.tv_usec, offset);
|
||||
if (!iter->just_seeked &&
|
||||
offset - iter->last_timestamp > GST_GDK_MAX_DELAY_TO_SEEK) {
|
||||
GST_INFO_OBJECT (iter, "current pipeline timestamp is too old (%"G_GUINT64_FORMAT
|
||||
" vs %"G_GUINT64_FORMAT"), seeking", iter->last_timestamp, offset);
|
||||
" vs %"G_GUINT64_FORMAT"), seeking there", iter->last_timestamp, offset);
|
||||
if (gst_element_send_event (gst_bin_get_by_name (GST_BIN (iter->pipeline), "sink"),
|
||||
gst_event_new_seek (GST_FORMAT_TIME | GST_SEEK_METHOD_SET |
|
||||
GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE,
|
||||
offset - GST_SECOND / 10))) {
|
||||
iter->last_timestamp = offset - GST_SECOND / 10;
|
||||
offset))) {
|
||||
iter->last_timestamp = offset;
|
||||
iter->just_seeked = TRUE;
|
||||
} else {
|
||||
GST_WARNING_OBJECT (iter, "seek to %"G_GUINT64_FORMAT" didn't work. Iterating there...",
|
||||
|
@ -567,3 +532,66 @@ gst_gdk_animation_iter_on_currently_loading_frame (GdkPixbufAnimationIter *anim_
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
static GdkPixbuf*
|
||||
gst_gdk_animation_get_static_image (GdkPixbufAnimation *animation)
|
||||
{
|
||||
GstGdkAnimation *ani = GST_GDK_ANIMATION (animation);
|
||||
GTimeVal tv;
|
||||
|
||||
if (!ani->pixbuf) {
|
||||
GST_LOG_OBJECT (ani, "trying to create pixbuf");
|
||||
g_get_current_time (&tv);
|
||||
GstGdkAnimationIter *iter = GST_GDK_ANIMATION_ITER (
|
||||
gdk_pixbuf_animation_get_iter (animation, &tv));
|
||||
if (iter) {
|
||||
guint64 offset;
|
||||
GstBuffer *buf;
|
||||
GstFormat time = GST_FORMAT_TIME;
|
||||
|
||||
if (!gst_element_query (gst_bin_get_by_name (GST_BIN (
|
||||
iter->pipeline), "sink"),
|
||||
GST_QUERY_TOTAL, &time, &offset)) {
|
||||
offset = 0;
|
||||
}
|
||||
if (offset > 120 * GST_SECOND) {
|
||||
offset = 120 * GST_SECOND;
|
||||
} else if (offset < 120 * GST_SECOND && offset >= 10 * GST_SECOND) {
|
||||
offset = offset / 2;
|
||||
}
|
||||
g_assert (time == GST_FORMAT_TIME);
|
||||
GST_LOG_OBJECT (ani, "using time offset %"G_GUINT64_FORMAT" for creating static image",
|
||||
offset);
|
||||
while ((buf = g_queue_pop_head (iter->buffers)) != NULL) {
|
||||
gst_data_unref (GST_DATA (buf));
|
||||
}
|
||||
/* now we do evil stuff, be sure to get rid of the iterator afterwards */
|
||||
if (!gst_element_send_event (gst_bin_get_by_name (GST_BIN (iter->pipeline), "sink"),
|
||||
gst_event_new_seek (GST_FORMAT_TIME | GST_SEEK_METHOD_SET |
|
||||
GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, offset))) {
|
||||
GST_INFO_OBJECT (ani, "seeking didn't work. Using next image");
|
||||
}
|
||||
|
||||
do {
|
||||
if (g_queue_is_empty (iter->buffers)) {
|
||||
if (iter->eos)
|
||||
return FALSE;
|
||||
if (gst_gdk_animation_get_more_buffers (iter))
|
||||
continue;
|
||||
}
|
||||
} while (FALSE);
|
||||
if (!g_queue_is_empty (iter->buffers)) {
|
||||
gst_gdk_animation_iter_create_pixbuf (iter);
|
||||
ani->pixbuf = gst_gdk_animation_iter_get_pixbuf (GDK_PIXBUF_ANIMATION_ITER (iter));
|
||||
g_object_ref (ani->pixbuf);
|
||||
} else {
|
||||
g_assert (ani->pixbuf == NULL);
|
||||
}
|
||||
/* DiE iterator, DiE */
|
||||
g_object_unref (iter);
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (ani, "Could not get an iterator. No pixbuf available");
|
||||
}
|
||||
}
|
||||
GST_LOG_OBJECT (ani, "Returning pixbuf %p\n", ani->pixbuf);
|
||||
return ani->pixbuf;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue