jjstuff n stuff
Well i've mostly been busy with work for the last couple of weeks. I more or less ended up taking a couple of weeks off around Easter and ANZAC Day so I had to do some more hours. There's no deadlines at the moment and I was waiting for some resources to become available so there wasn't much else to do anyway, and between all the hacking I did I managed to get a little of the waning sun before winter really hit a week ago.
I did a little bit on jjmpeg over the weekend. Partly as I was using it to prototype some ideas I was evaluating for work; I will probably end up doing it in C but its an easy platform to experiment in.
I did a fair bit of cleanup around JJMediaWriter, although it still needs work. Video works well but audio is probably broken.
The VideoPlay demo is a little nicer and I moved to the java.time stuff for date formatting. Fixed a bug with error handling.
Another bug I fixed was with the initialisation of native methods for functions which don't derive from AVObject. AVObject contains the code which loads the native library so if you don't use it first you don't get any native linkage. I hacked a simple mechanism using a NOP function that seems to work properly. You can't just load it in another class.
JNI Callbacks
I spent a bit too much time working on filling out AVIOContext to
make it more 'complete'. AVIOContext is used to read/write files
and network connections and allows for user-supplied callbacks to
implement custom i/o. jjmpeg supports both ffmpeg and custom i/o
but there was an updated open2() api for the former which takes an
interrupt-check callback when opening a context. This posed a
problem because for the custom i/o case I had a free
pointer opaque
I use to track a hard reference to the
Java side callbacks but for the ffmpeg i/o case it is used by
ffmpeg.
jjmpeg relies on the object pointers being the actual objects so I can't easily put this through a proxy object that contains both pointers. Actually there is only one place it is used but even then it would be very messy to make it work sanely.
The solution I came up with was to have the Java object retain a reference via another NativeZ managed object which retains any number of JNI side references which gets freed JNI side when it gets cleaned up. I then just poke an instance of this onto the AVIOContext so it lasts at least as long as the AVIOContext itself. I put this manager object into NativeZ because it might be useful elsewhere.
While it should work, it does seem like a bit messier than it
might be. Just now I thought perhaps I could just store the Java
listener in the Java object, but the C callback still needs a
reference to this
to retrieve the listener and it
can't hold a hard reference otherwise the object will leak. But I
just looked up the JNI docs and found a WeakGlobalRef API so that
should probably work. I will try it and if so I will use that
instead and roll back the code I added to NativeZ as well.
Documentation & The Rest
I also started a longer term and possibly pointless exercise of cleaning up the accessor methods and documentation. The accessor methods just access the struct fields directly but most fields are also accessible via the pretty messy libavutil/opt.h interface which is mirrored in part in AVOptions. Originally I went through the structures and just inserted the ones that looked like they might be useful but there's a lot of cruft in there and AVOption covers all the important onces. So I went throuhg AVCodecContext and retained the useful looking ones and cleared out the rest. I also cross-referenced the options table and documented the corresponding names if they exist.
After that I got the javadocs to build. I had to fix a bunch of badly formatted comments before I read the javadoc manual and a bunch of broken comments that get imported by the constant extractors. It all looks pretty bare though. It will take a lot of work to make them something worth using. Will see, will see.
I even did a little OpenCL today. Just a tiny bit of code to run a random fern inferencer. It's been so long since i've written any it took a few iterations to get things going. Didn't need to make any changes to zcl though, so that's a plus. But even with all the niceties of zcl it's still a bit, well, messy. The CLTask is a good kernel of an idea (pun intended) but there might be ways to build on that to be something a little more convenient. How deep I look into this will depend on how much OpenCL I end up writing but that probably wont be much.
Tutorial
Oh another thing I did over the weekend was some Java tutoring for a mate. He's doing JavaFX, so yeah it wasn't much effort even with the hangover I had acquired from the night* before.
I was somewhat surprised at how bad the assignment was though. For a first assignment the scope wasn't so bad but right from the start things were a bit strange.
Must be Eclipse, must be JavaFX11. Why JavaFX11? Who knows, it's not really that different as a toolkit compared to JavaFX8 apart from being a much bigger pain to install not to mention the complication with the module stuff. Just what you want for an introductory course. Eclipse is pretty much total pants too if you ask me.
There is a page for an eclipse module or plugin or whatever it is but the 'for the lazy' page is so short it seems to be missing all the details. And the screenshots are so low resolution you can't read any of the text. The only remotely likely looking available option didn't match the description and looked wrong - and it didn't work when you installed it regardless. We did get it running but I had to put in JVM arguments and frob around a bit. Admittedly I need to do that in netbeans too but at least it supports modules and you don't need to use explicit --add-module JVM args.
(Being an apple machine i wasn't familair with it's weird filesystem heirarchy and the funky mess of a thing 'Finder' has turned into so that didn't help either).
Back to the assignment itself. Rather than a list the requirements, it stepped you through the parts that needed to be done. This is after first insisting that it wasn't a guideline of the steps to follow - even though you couldn't do the assignment without following them. In the addition to this odd idea, the formatting was completely miserable, like an email where carriage returns have been inserted randomly between sentences. What text there was was also often contradictory, and when it wasn't it offered questionable solutions to common problems.
For example one paragraph would talk about placing code in a constructor then the next sentence would say the same thing needed to go in some other method. In one case this was talking about the root Application where you pretty much never use the constructor and you put this stuff in start() so it was just wrong. In another case it talked about creating a 'XYStage' and then the code suggested for the constructor is 'stage = new Stage()'. It even mentioned deriving from Stage although not consistently! For the rest of the assignment it kept talking about this stage variable which shouldn't exist. I really don't like using the word wrong for software since so many ways will work - poor, snot, junk, totally shithouse, sure all of those, but there really was a lot of utter wrong here!
Even strange stylistic choices that indicate the author doesn't write or read any code of any language. Who creates any rectilinear object like a Window using (sizex,sizey,x,y) syntax rather than (x,y,width,height)? And lets start out teaching bad ideas like using undecorated windows so you can implement your own buggy and non-accessible window manipulation features yourself. Garish colour suggestions, check! No namespaces. Variables which change names or types from paragraph to paragraph, go you covered there too.
Bit bored tonight. I almost did some more work-related stuff but decided I needed a break from it. Not much else to do though which is why I posted this. Well it looks like i'm now playing with jjmpeg for a little while at least.