Thursday, October 29, 2009

Creating Cisco ring tone files with GStreamer & GNonLin

Cisco IP phones have the ability to customize their ring tones. Unfortunately, many people have difficulty creating ring tones because the file format that the Cisco phones expect can be difficult to produce using your average audio application. The phone is expecting a raw format audio file (raw files do not have any sort of header that identifies the encoding of the contents) with one channel, 8000 samples per second, eight bits per sample, and encoded with the μ-law encoding.

GStreamer can create files with this format easily with a command that looks like this:

gst-launch filesrc location=file.wav ! decodebin2 ! audioconvert ! audioresample ! mulawenc ! audio/x-mulaw,rate=8000,channels=1 ! filesink location=file.raw

However, ring tone files have one other twist - they cannot be more than 16080 bytes long, which is about 2.01 seconds of audio! Fortunately GStreamer has GNonLin. GNonLin is a set of plugins for GStreamer that add non-linear editing functions to GStreamer. Unfortunately, they can't be used from the gst-launch command line. Fortunately, the GStreamer Python bindings allow us to create a short
script that will solve our problem.

The code can be found in a Git repository or you can get the script directly here.

Let's take a look at the section of the code that deals with GNonLin:

self.gnlcomposition = gst.element_factory_make('gnlcomposition')
self.gnlcomposition.connect('pad-added', self.on_pad_added)
self.pipeline.add(self.gnlcomposition)

The gnlcomposition element is the toplevel GNonLin element that brings together a number of GNonLin source elements.

self.gnlfilesource = gst.element_factory_make('gnlfilesource')

Create the source element.

self.gnlfilesource.set_property('caps', gst.caps_from_string('audio/x-raw-int; audio/x-raw-float'))

The caps property tells the gnlfilesource that we want audio data out of the file. This is in case we feed the script a video file and we need to ignore the video data.

self.gnlfilesource.set_property('location', source)

Tell the gnlfilesource element where the original file is.

self.gnlfilesource.set_property('start', 0 * gst.SECOND)
self.gnlfilesource.set_property('duration', int(duration * gst.SECOND))

The start and duration properties tell the gnlcomposition element where in the destination audio stream to place the audio we extract from the source audio. If we were writing an application that manipulated multiple audio streams we could rearrange and/or overlap the audio in the destination.

GStreamer uses nanoseconds internally to communicate times, which is why we multiply the duration in seconds by gst.SECOND, a constant that will convert seconds to nanoseconds (there are 1,000,000,000 nanoseconds in a second).

self.gnlfilesource.set_property('media-start', int(start * gst.SECOND))
self.gnlfilesource.set_property('media-duration', int(duration * gst.SECOND))

The media-start and media-duration properties tell the gnlfilesource what part of the source audio stream to extract.

self.gnlcomposition.add(self.gnlfilesource)

Add the gnlfilesource to the gnlcomposition.

The script that I came up with started out as tutorial code originally posted by Jono Bacon on his blog.

Sunday, October 25, 2009

Fedora Talk FAD Day 3

This was mostly a travel day, though I managed to update the F-12 Asterisk package to fix some of the issues that we found during the weekend during breakfast.  The flights back home went very smoothly, in fact I think that each leg landed several minutes early.  Thanks to Paul Frields for setting up the FAD and thanks to his wife for the tasty treats and the fabulous meal on Saturday night!

Saturday, October 24, 2009

A Couple of Fails

While at Paul's house, he didn't to notice that I had gotten the chair of doom out from where it had been tucked away.  It held out for a while but it finally failed in what could have been a scene from a Charlie Chapman film or a Chevy Chase Saturday Night Live skit.  Other than the chair, only egos were hurt and I guess I have a good story to tell at future Fedora gatherings.

On a more serious note the Hulu Desktop client doesn't work in Fedora 12.  They had released a couple of updates and the 9.04 version had been working pretty well in Fedora 11.  I guess that's what you get for playing with closed-source software.

Fedora Talk FAD Day 2

Sleep, breakfast, and then back to BusinessPlayce for the 2nd day of the Fedora Talk FAD.   We all kicked some serious butt and have things at least 70-80% "there".  Jared and I would probably have made more progress on the backend but we ran into some bugs (some introduced by Fedora-specific patches which I'll be backing out and issuing new Asterisk packages) in Asterisk that slowed some things down.  I think we'll have these fixed soon and we hope to keep the momentum by getting together regularly on IRC and by Fedora Talk itself.  After the serious hacking was done we headed over to Paul's house and his wife cooked us an extremely awesome meal of roast beef, garlic roasted green beans, white sweet potatoes, biscuits, and bread sticks.  She topped that off with an awesome coffee cake.  Now we're in Paul's basement and Paul, Ian, and John Poelstra are playing Rock Band.  Since I hope to remain friends with them I'll refrain from critiquing their faux musical abilities...

Fedora Talk FAD Day 1

After a fairly decent night's sleep at the Hilton Garden Inn in Fredericksburg, VA the FTF crew met up for breakfast at the Cracker Barrel.  Managed to avoid the lure of the kitsch and headed over to BusinessPlayce, a local co-working site in Fredericksburg.  The owner set us up with a very nice conference room, which we proceeded to clutter up with more phones, laptops, and cables than was probably prudent.  Jared Smith and I worked on getting some of the backend working while the rest worked mostly on end-user documentation, including some really good stuff on troubleshooting issues that users might run into with configuring soft phones.  Dinner was at the Capital Ale House, where I had the excellent "Brat & Knack" plate.  After a short walking tour of the historic downtown area we headed back to the hotel for a short late-night hacking session.

Fedora Talk FAD Day 0

Fairly easy travel day, except that getting from Des Moines to Fredericksburg means flying regional jets which aren't exactly known for their spaciousness.  Iowa Attorney General Tom Miller was aboard the leg from Des Moines to O'Hare.  The leg from O'Hare to Richmond was nice because the plane wasn't full so I had a row of seats to myself.  The flight crew also entertained us before we left the jetway by playing Enya over the intercom system.  Paul Frields and Jon Stanley met me at the airport in Richmond.  Despite some minor delays on my flights I managed to arrive before Ian Weller and John Poelstra.  Some minor luggage snafus later we were on the road to Fredericksburg.

Wednesday, October 21, 2009

Fire Non-Drill

Had a little excitement this morning... Fire alarms went off around 11:00 this morning. Everyone dutifully (if a little slowly) filed their way outside. Fortunately it's a pretty nice Fall day today. Didn't see or smell any obvious signs on fire on the way out, but once outside we heard through the grapevine that a scissor lift that was being used to replace light bulbs in another part of the building had caught fire. No one was hurt and nothing other than the scissor lift was damaged, although a pot of coffee was spilled by the forklift that was trying to get the scissor lift out of the building. Around 40 minutes later the fire department let us back into the building. There's a slight smoky smell in the building and the areas where the scissor lift was in will need some cleaning up from all of the dry chemical fire extinguisher dust.

Note to self, grab the laptop next time...

Tuesday, October 20, 2009

Gnome Shell

I recently switched my secondary laptop to Fedora 12/Rawhide. Since the laptop uses an ATI chip, modesetting and 3D are working pretty well. I've seen some of the Gnome Shell buzz so I decided to give it a try. So far I like it. The "wobbly windows" effects and transparent terminal windows were cool, but not cool enough for me to switch permanently to a compositing window manager. But the Gnome Shell "Activities" screen finally seems like a useful thing to do with that 3D hardware. I'm in the process of upgrading my main laptop to Fedora 12/Rawhide as well. Assuming 3D works (doubtful since it's a nVidia chip) I'll be switching the primary laptop to Gnome Shell to see if it'll meet my day-to-day needs.

Wednesday, October 14, 2009

Panasonic Network Camera vs. Flumotion

At work we have an old Panasonic network camera, model KX-HCM280A, that mainly gets used during the Iowa State Fair to put a "live webcam" of our booth up on our website. And by "live" I mean that the camera uses FTP to upload a JPEG to our website every few seconds. I've always thought that it would be cooler to have a real video stream from the camera. The camera is capable of producing a 640x480 MJPEG video stream, however it's not powerful enough to serve more than one or two streams at a time, not to mention that I'd prefer that people didn't connect directly to the camera anyway.

This afternoon I decided to see what I could do with Flumotion to get a video stream out of the camera. Earlier this week I set up Flumotion to stream the video from a USB webcam so I had a little familiarity with Flumotion and I've been writing moderately complex GStreamer pipelines for a while so this didn't turn out to be too difficult. Here's what I ended up with:

    <component name="panasonic-producer-video"
type="pipeline-producer"
label="panasonic-producer-video"
worker="localhost"
project="flumotion"
version="0.6.1">

<property name="pipeline">
souphttpsrc user-id=userid user-pw=password location=http://cameraipaddr/nphMotionJpeg?Resolution=640x480&amp;Quality=Clarity is-live=true do-timestamp=true ! multipartdemux ! image/jpeg,width=640,height=480,framerate=(fraction)0 ! jpegdec ! videoscale ! videorate ! ffmpegcolorspace ! video/x-raw-yuv,width=320,height=240,framerate=(fraction)15/1
</property>

<clock-master>true</clock-master>
</component>

If you're not familiar with Flumotion this is the XML that describes one "component" in the processing pipeline that Flumotion sets up. (Flumotion splits up the GStreamer pipelines into multiple components so that the work can potentially be spread across multiple physical systems). This component uses HTTP to get the MJPEG stream from the camera, decodes the multipart stream into individual JPEG images, decodes the JPEG images into raw video, scales the images to 320x240, ensures a constant frame rate, and transforms the color space if necessary.

It took a little experimenting to get all the pieces of the pipeline figured out using the gst-launch command line, and then another bit of experimenting to figure out how to rewrite the pipeline from the syntax that suited the shell to the syntax needed in the XML but it seems to be working well.

Another nice surprise is the native video support in Firefox 3.5. The stream "just works" using the HTML5 video tag. As a fallback I'm using the Cortado Java applet. I have some tweaking to do on the applet HTML, as I'm trying to get it to work in the most browsers possible.

The next time the opportunity arises I'll have to see if they want to use the full-motion video rather than the still images.

Friday, October 9, 2009

Hulu Desktop for Linux

Hulu has released a version of it's desktop client for Linux. It's compiled for both Ubuntu and Fedora and is available in 32-bit and 64-bit flavors. It too bad that it's closed source, but it requires Adobe Flash anyway so there's no way it would end up in Fedora anyway. I'll keep hoping for an open source way to watch Hulu's content but for now the new desktop client means that it'll be easier for me to get the mindless entertainment that I need every now and then.

Nobel Peace Prize

Congratulations to President Obama on receiving the Nobel Peace Prize! It's amazing that he's received such an honor so early in his career, but I think it's well deserved nonetheless.

Thursday, October 8, 2009

Google Wave!!!

Wooo!!! My Google wave invite finally showed up. Many thanks to Jared Smith for the invite. Now I just need to figure out what to do with the darn thing....

Friday, October 2, 2009

Google Wave Invite On The Way?

Thanks to Jared Smith, I should have an invite to Google Wave on the way. Unfortunately, it might take a while to get here. I suppose they must be limiting the rate at which invites are sent out to keep the service from being overloaded...

Thursday, October 1, 2009

Google Wave?

Seems that Google is opening up Google Wave to more participants. Unfortunately I do not appear to be one of them. So, if you got invited and have a spare invite to share, I'd appreciate having one tossed my way.