mplayer and matroska metadata

I’ve been playing with Matroska in general a lot more, seeing what I can do, and in the past week and a half, I’ve found some really cool things. I’m completely braindead after staring at the mplayer code all day, so if I come across a little confusing, now you know why. It’s one of those instances where I wanna get this documented though, if nothing else than for a small marker of a pretty big milestone for me. 🙂

I’m too tired to lay this down in story format, so I’m just gonna dump it out best I can.

The other week, I noticed that a new version of mkvtoolnix had come out (the tool to mux audio/video files into the Matroska container), and it totally flew under my radar. I started playing with it, and noticed some real improvements in speed, with regards to parsing MPEG-2 video. After playing around a bit, I started reading some more of the documentation, and found out about this excellent tagging system that the specification declares.

You can read all the gory details about it here, but basically, when building a Matroska file, you can create an XML file that has global tags that can store pretty much every metadata tag I could ever dream of possibly wanting.

I never really had the itch to pack much metadata into the container up until this time, when I realized just how much factual data I could stuff in there and not depend on the database for. Pretty much the only thing I really cared about was the title. In fact, all I wanted originally was to be able to get MPlayer to display the metadata title that was in the file.

Going off on a tangent here, I poked an open bug I have on MPlayer’s bugzilla, and Reimar, an mplayer dev, was kind enough to oblige me once more and updated the code so that I could pull it out. If you’re using a recent snapshot (for Gentoo, the 20090530 one has it), you can pull it out using “get_property metadata/title” in slave mode. If you wanted to display it on-screen, you would map a keypress event or LIRC event to this: osd_show_property_text “${metadata/title}”. Quotes and all.

Anyway, Reimar added that in for me (thanks, man), so I started poking around with mplayer’s features to see what else it could pull out for me. Now that I was going to be storing lots more data in the container, I wanted to be able to pull it out, too.

Jump forward a bit to today, where I woke up this morning and was determined to get it out somehow. My original plan that I had decided on was, since I can’t really hack on C code, to just work around the limitation by using a fifo for mplayer. I’ll spare you the ugly details, but basically I was going to have an event send a command to an external script that would query the .mkv file for the metadata tag I requested, and send a command back through the pipe to print that out to the screen. Quite a run around.

Well, I’ve tried before to grep the code of mplayer a bit to see if I could wrap my head around the stuff and see if I could figure it out for myself, but it hasn’t worked out real well. I decided to give it another whirl today, though. This time, however, my approach was a little bit different. Normally I would just search for keywords where I *think* mplayer would be doing what I would think it was doing, tinker with the code, recompile it, run it, and see what it does. A really slow process, but sometimes it works. And I really don’t mind spending the time on it, either.

This time, I did things a little bit differently. I found a file where I was sure that it was accessing matroska metadata, and I read the entire thing, and took copious notes, explaining to myself the whole time, basically what I thought the purpose of each major element was, trying to figure out the pattern to this. Now, bear in mind, that I’m still learning some C++ myself, and the C syntax is pretty similar (in fact … I still can hardly tell the difference, myself), so a lot of times I have a vague understanding of what it *might* be doing, but never enough to be sure … so there is still a lot of guesswork involved.

Anyway, after about 10 hours of going back and forth, making notes, testing code, printing out functions and variables and metadata, I got it figured out. And the final patch is something like 2 lines long, heh. All I did was add one if statement. But, that was enough to get me going, and it solved a nagging issue for me. But, what is far more valuable, is the fact that I’ve learned how I can go into this code and figure out how to fix things myself. That’s gonna really come in handy. I’m sure I won’t be submitting patches upstream anytime soon, but if I can get what I want hacked in there, and working, I’ll be happy as a clam.

For the record, the problem with the metadata was this: MPlayer has a single key=value pair that it assigns to metadata values with it is parsing it with the libavformat demuxer. That is normally well and good, except in the case of Matroska, the tags can be nested with similar names.

So, for example, say you have two target tags in your matroska container: Collection and Episode. If it were a TV show, let’s say it’s CHiPs. Great show, btw. Now, in the tagging specification, both of them can have a title. The title for the collection would be CHiPs. If you had a Matroska A/V file that was just one episode, then the title for that would be “Ponch Delivers A Baby on the Disco Floor” or whatever (which really does happen, I kid you not). They key for both of those would be “title”, but the values would be different. The LAVF demuxer just overwrites the old value and assigns it to whatever comes last. Kind of a problem.

So all I did was told the demuxer to prefix the key names with whatever the name of the target tag was (Collection, Season, Episode, etc.). That way you can have distinct key value pairs, but they are just more verbose. The metadata property names now are metadata/collection/title instead of metadata/title. Pretty simple, really.

That was the easy part. The second part, I haven’t figured out yet — how to get it out. The metadata is all in a separate object created by the LAVF demuxer, which I don’t know enough C to figure out how to access that outside of that class. So, I just hacked it to add it to the metadata myself in a rather ugly, but working fashion. Upstream probably wouldn’t be interested in that patch.

Another hard day’s work, and I’m still not done. And I’ve got a lot more to write about it, so I’ll just stop here for now. I’m gonna go port the patches to my frontends. 🙂

Edit: For reference, the clean version of the patch, a sample XML file of what I would mux in with an episode, and the ugly hack I personally am using to get it all out where my lack of C knowledge is very much publicly exposed.  Note that you have to use -demuxer lavf with mplayer for it to work.

4 comments on “mplayer and matroska metadata

  1. Till

    Has this patch been implemented in the latest svn?
    I can’t seem to make it work.

    Will it even patch against the latest svn?

    Thanks for your hard work, I’d love to get this happening on my own media center 🙂

    Reply
    1. Steve

      SVN has support now natively for the demuxer, so you don’t need my hacks anymore. Just use -demuxer lavf and you’ll see all the metadata posted on the console. 🙂

      Reply

Leave a Reply