GdkPixbuf woes

For the last four days I’ve been trying to implement cover art support for iPods in Amarok 2.1. I’ve reached desperate measures here, appealing to the wider public for any hints that might be available.

Here’s the problem. Any returned GdkPixbuf objects from libgpod when called from within Amarok are invalid — they’re either garbled junk, null, glib asserts, or libgpod throws an assertion claiming something or other:

(process:26875): GdkPixbuf-CRITICAL **: gdk_pixbuf_scale_simple: assertion `src != NULL' failed
(process:26875): GLib-GObject-CRITICAL **: g_object_unref: assertion `G_IS_OBJECT (object)' failed

(process:16782): CRITICAL **: unpack_UYVY: assertion `width * height * 2 == bytes_len' failed

The most bizarre part of it is that the exact same code works perfectly when called from within one of libgpod’s unit tests, and artwork retrieval works fine in gtkpod.

A few things I know for sure:

  1. There is only one version of libgpod installed (0.7.0), self compiled with gdkpixbuf support
  2. Gtkpod was also self compiled against libgpod 0.7.0
  3. The libgpod guys have been very involved but can’t provide any answers
  4. Both gtkpod and Amarok link to the same versions of libgpod and gdk:
    $> ldd /usr/lib/kde4/libamarok_collection-ipodcollection.so
    libgdk_pixbuf-2.0.so.0 => /usr/lib/libgdk_pixbuf-2.0.so.0
    libgpod.so.4 => /usr/lib/libgpod.so.4
    $> ldd `which gtkpod`
    libgdk_pixbuf-2.0.so.0 => /usr/lib/libgdk_pixbuf-2.0.so.0
    libgpod.so.4 => /usr/lib/libgpod.so.4
  5. Could it be a race condition somewhere? Perhaps, but as I see it, the code is only ever called from the Qt GUI thread.

Here’s the snippet of code: http://pastie.org/415144

Can anyone provide any insight to this problem? I’m going bananas trying to solve it.

Update: Problem solved folks! Turned out to be a misuse of the libgpod api – calling itdb_device_read_sysinfo() kills the artwork structs which have been already initialised. The blame game lies equally on Amarok (for incorrect usage) and libgpod (for poor documentation and unexpected results). Good news is that the grand folks upstream at libgpod have been notified and they’ll be improving their API and docs.

11 Comments

  1. kinto
    Posted March 13, 2009 at 11:37 pm | Permalink

    Just a poor user here so unfortunately nothing useful for you. I just wanted to say that I love Amarok 2 and I hope you’ll succeed in this to make it even closer to perfection! Thank you, your work is much appreciated!

  2. pfee
    Posted March 13, 2009 at 11:46 pm | Permalink

    I don’t know about the libraries you’re using, but perhaps you have multiple definitions of the same symbols present. This may mean you’re calling some functions from one library and some from others.

    ldd will show immediate dependencies, but libraries loaded via dlopen() won’t be shown. For that, lsof may help.

    Armed with a list of libraries, you could use nm to find the symbols in each library, then look for duplicates.

    Multiple similarly named libraries or duplicate symbols would be suspicious and may be your problem.

    Hope that helps.

  3. Lamarque
    Posted March 14, 2009 at 12:00 am | Permalink

    It can be a define or environment variable defined in Amarok too. Last year I had a problem with a cryptography code that worked when I tested in my computer but when I used it in the production environment it did not. In the end I found out the problem was the _MALLOC_PERTURB environment variable that was set in the production environment. I unset the variable and everything worked.

  4. Posted March 14, 2009 at 12:20 am | Permalink

    If the working code is open-source, can you not look there.

    Does some instance of a class need new-ing, and you are using an uninitialised version of the object.

    Your first error says (to me) you do NOT have a buffer or source file open for the library to use or read.

    Is something initialised and memory allocated in one thread or process, to which another thread or process does not have access to?

    The second error, suggests that some incorrect object (or NULL) has been cast into the object reference, and perhaps does not supply a property or method needed.

    The third error says your image buffer is the wrong size, it seems to suggest that you do not have an image buffer or your image is a different type/size to the one the image buffer was created for. I would expect an RGB image for static artwork.

    On line 28 of your snippet, what if the file was not opened? Would it return NULL? Your seem to be checking pixbuf, but not filename.

  5. Posted March 14, 2009 at 12:53 am | Permalink

    Have you tried running it through Valgrind yet?

  6. Anders Brander
    Posted March 14, 2009 at 12:55 am | Permalink

    Maybe this is a stupid question…

    Did you remember to call the needed “G-initializers”?

    gtk_init(&argc, &argv);

    and maybe

    g_threads_init(NULL);

  7. Anders Brander
    Posted March 14, 2009 at 12:56 am | Permalink

    … and maybe even:
    g_type_init();

  8. Michael
    Posted March 14, 2009 at 1:45 am | Permalink

    Agree with purple-bobby’s ideas. Perhaps you aren’t initializing everything that needs to be initialized.

    > assertion `src != NULL’ failed
    This means that src == NULL. Perhaps src needs to be initialized somewhere.

    > g_object_unref: assertion `G_IS_OBJECT (object)’ failed
    G_IS_OBJECT, if I’m reading this correctly, checks if a certain value is, in fact, a GObject. Perhaps the value is again NULL?

  9. Michael Pyne
    Posted March 14, 2009 at 11:24 am | Permalink

    Seb,

    Do you use a 64-bit setup? If so, make sure that those NULLs are being cast into a pointer type and see if that changes anything. Recent glibcs should automatically use the gcc-extension null pointer instead of 0 which means this shouldn’t be an issue but you never know.

    If it still doesn’t work, try compiling the testcase in C mode instead of using C and see if it crashes. If so, the problem is a difference between C and C compilation.

  10. Posted March 14, 2009 at 1:06 pm | Permalink

    Hey everyone, thanks for all the replies. Here’s the progress:

    a) I know what all of the assertions mean, literally. I can’t figure out what is causing them though.
    b) The test code (which is a c program) works well both when compiled in a plain c prog as well as a Qt wrapper with a GUI thread and all.
    c) Seems like I’m going to have to run through valgrind.
    d) @pfee: I like your suggestion, but this seems like a very arduous task considering the size of an application like Amarok.

  11. Posted March 15, 2009 at 7:27 am | Permalink

    Have you tried running the test program in gdb? If you do it with G_DEBUG=fatal_criticals set, gdb will stop on the critical messages, so you can use bt, and walk up in the frame stack, which may help you figure out what’s going wrong.

    I’m betting some kind of initialization, but do you use multiple threads? You may have to use GDK_THREADS_ENTER()/GDK_THREADS_LEAVE(); note that GTK /GDK are not thread-safe, they’re only thread-aware.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>