How To: Simply Convert A Directory of FLAC files to MP3 with FFMPEG in Linux

Stick the following in a file called flac2mp3 or such, chmod +x it, then put it in somewhere like /usr/local/bin

for a in *.flac; do
  ffmpeg -i "$a" -qscale:a 0 "${a[@]/%flac/mp3}"
done

To use it, simply go to your folder of .flac files and run flac2mp3, then perhaps rm *.flac to get rid of the (massive) flac files you don’t want anymore.

How to: Convert an OpenCV cv::Mat to an OpenGL texture

I’m working on using OpenCV to get Kinect sensor data via OpenNI, and needed a way to get a matrix (cv::Mat) into an OpenGL texture – so I wrote a function to do just that – woo! Apologies in advance for the terrible juggling ;-)

The function used to perform the sensor data to texture conversion is:

// Function turn a cv::Mat into a texture, and return the texture ID as a GLuint for use
GLuint matToTexture(cv::Mat &mat, GLenum minFilter, GLenum magFilter, GLenum wrapFilter)
{
	// Generate a number for our textureID's unique handle
	GLuint textureID;
	glGenTextures(1, &textureID);
 
	// Bind to our texture handle
	glBindTexture(GL_TEXTURE_2D, textureID);
 
	// Catch silly-mistake texture interpolation method for magnification
	if (magFilter == GL_LINEAR_MIPMAP_LINEAR  ||
	    magFilter == GL_LINEAR_MIPMAP_NEAREST ||
	    magFilter == GL_NEAREST_MIPMAP_LINEAR ||
	    magFilter == GL_NEAREST_MIPMAP_NEAREST)
	{
		cout << "You can't use MIPMAPs for magnification - setting filter to GL_LINEAR" << endl;
		magFilter = GL_LINEAR;
	}
 
	// Set texture interpolation methods for minification and magnification
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
 
	// Set texture clamping method
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapFilter);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapFilter);
 
	// Set incoming texture format to:
	// GL_BGR       for CV_CAP_OPENNI_BGR_IMAGE,
	// GL_LUMINANCE for CV_CAP_OPENNI_DISPARITY_MAP,
	// Work out other mappings as required ( there's a list in comments in main() )
	GLenum inputColourFormat = GL_BGR;
	if (mat.channels() == 1)
	{
		inputColourFormat = GL_LUMINANCE;
	}
 
	// Create the texture
	glTexImage2D(GL_TEXTURE_2D,     // Type of texture
	             0,                 // Pyramid level (for mip-mapping) - 0 is the top level
	             GL_RGB,            // Internal colour format to convert to
	             mat.cols,          // Image width  i.e. 640 for Kinect in standard mode
	             mat.rows,          // Image height i.e. 480 for Kinect in standard mode
	             0,                 // Border width in pixels (can either be 1 or 0)
	             inputColourFormat, // Input image format (i.e. GL_RGB, GL_RGBA, GL_BGR etc.)
	             GL_UNSIGNED_BYTE,  // Image data type
	             mat.ptr());        // The actual image data itself
 
	// If we're using mipmaps then generate them. Note: This requires OpenGL 3.0 or higher
	if (minFilter == GL_LINEAR_MIPMAP_LINEAR  ||
	    minFilter == GL_LINEAR_MIPMAP_NEAREST ||
	    minFilter == GL_NEAREST_MIPMAP_LINEAR ||
	    minFilter == GL_NEAREST_MIPMAP_NEAREST)
	{
		glGenerateMipmap(GL_TEXTURE_2D);
	}
 
	return textureID;
}

You can then use the above function like this:

// Create our capture object
cv::VideoCapture capture( CV_CAP_OPENNI );
 
// Check that we have actually opened a connection to the sensor
if( !capture.isOpened() )
{
	cout << "Cannot open capture object." << endl;
	exit(-1);
}
 
// Create our cv::Mat object
cv::Mat camFrame;
 
	// *** loop ***
 
	// Grab the device
	capture.grab();
 
	// Retrieve desired sensor data (in this case the standard camera image)
	capture.retrieve(camFrame, CV_CAP_OPENNI_BGR_IMAGE);
 
	// Convert to texture
	GLuint tex = matToTexture(camFrame, GL_NEAREST, GL_NEAREST, GL_CLAMP);
 
	// Bind texture
	glBindTexture(GL_TEXTURE_2D, tex);
 
	// Do whatever you want with the texture here...
 
	// Free the texture memory
	glDeleteTextures(1, &tex);
 
	// *** End of loop ***
 
// Release the device
capture.release();

There’s one very important issue to watch out for when using OpenCV and OpenNI together which I’ve commented in the code, but I’ll place here as well as it can be a real deal breaker:

There appears to be a threading issue with the OpenCV grab() function where if you try to grab the device before it’s ready to provide the next frame it takes up to 2 seconds to provide the frame, which it might do for a little while before crashing the XnSensorServer process & then you can’t get any more frames without restarting the application. This results in horrible, stuttery framerates and garbled sensor data.

I’ve found that this can be worked around by playing an mp3 in the background. No, really. I’m guessing the threading of the mp3 player introduces some kind of latency which prevents the grab() function being called too soon. Try it if you don’t believe me!

So just be aware that if you’re using a Kinect you have to be careful with the grab() function… The source code used to create the above video is provided in full after the jump, if you’re interested.

Cheers!

Continue reading How to: Convert an OpenCV cv::Mat to an OpenGL texture

How to: Create an ISO image of directories in Linux

I ripped some DVDs I own the other day as I wanted to create a back-up for the kids travel DVD players (so the originals don’t get scratched and trashed on the road), only the DVDs themselves were DVD-9’s (so single-sided dual-layer with a capacity of up to 8.54GB) while I can only write DVD-5’s (single-sided single layer with a capacity of up to 4.7GB) – this isn’t a big problem as I compressed them down to fit using Handbrake and elements of Shetboy’s meticulously crafted AVI to DVD technique. However, both Brasero and GnomeBaker would flat out refuse to burn Video projects – they’d just choke on the folder containing the AUDIO_TS and VIDEO_TS folders – so why not covert the directory including the *_TS folders to an ISO and burn that? No reason why not! Let’s get it done! =P

Making the ISO

Once you’ve got a folder structure containing the AUDIO_TS folder (which is empty) and the VIDEO_TS folder (which contains your .BUP, .IFO and .VOB files), just run the following command to generate your ISO:

mkisofs -o ISO_FILENAME -V LABEL -r SOURCE_DIRECTORY

So, for example, you might use the following command to create an ISO of the directory containing the *_TS folders for the film Avatar:

mkisofs -o ~/AvatarDVD.iso -V Avatar -r ~/dvdprep/Avatar/

Once you hit return, you’ll see something like the following output:

I: -input-charset not specified, using utf-8 (detected in locale settings)
  0.22% done, estimate finish Wed Jul 27 12:30:27 2011
 
..... all the rest ......
 
 99.96% done, estimate finish Wed Jul 27 12:27:58 2011
Total translation table size: 0
Total rockridge attributes bytes: 1353
Total directory bytes: 4096
Path table size(bytes): 42
Max brk space used 21000
2275896 extents written (4445 MB)

Measure Twice, Cut Once

If you wanted to make sure you got it right, as in, you ONLY have the *_TS folders in the iso, not the top level folder containing those two folders also, then just open the created iso file with Archive Manager and take a look, or mount it to a folder with:

mkdir test
sudo mount -o loop -t iso9660 ./AvatarDVD.iso ./test
ls test
 
[ which should show "AUDIO_TS  VIDEO_TS" ]
 
sudo umount ./test

When you’re happy with the iso, burn it with your burning software of choice and you’re all sorted!

Cheers!

How To: Convert VirtualPC .vhd hard drives to VirtualBox .vdi hard drives (or vice-versa)

Don’t bother – VirtualBox now natively supports .vhd drives – how handy is that? =D

But if you really wanted to, just use:

VBoxManage clonehd source.vhd target.vdi --format vdi

This will place the .vdi version of your drive in your current users VirtualBox folder, which is: ~/.VirtualBox

Relatedly, to go the other way (.vdi to .vhd) you could use:

VBoxManage clonehd source.vdi target.vhd --format vhd

Note: For this to work, you must not have the drive attached to any virtual machine, so if you already have it connected to a virtual machine, detach it first, mkay?

How To: Convert .WBFS Image Files to .ISO Images

Update: You can convert compressed ISO images (.ciso files) using this method, too…

If you need to translate a Wii DVD image from the newer .WBFS format (which has lovely sparce-file support) to an old-school .ISO image, well you can jolly well do so with Wii Backup Manager! Now, WBM is a really useful program so congrats to the author (xzxero) – but it uses non-standard GUI elements in that it uses what looks like the category list as a second main-menu, and this makes it a little non-intuitive to use. But in fairness to the author, the download page has a tutorial (which I didn’t find until after completing this post!). Still, it’s easy enough once you’ve figured that out. The entire conversion process goes like this:

1.) Grab yourself a copy of Wii Backup Manager. Version v0.3.5 beta 1 is the most recent version available at the time of writing, and although it’s Win32 only, it works fine in VirtualBox…

2.) Extract and launch it

Wii Backup Manager

3.) From the Files tab, click on what looks like the Add category title, select Files and go pick a .WBFS image from the navigation dialogue box

Wii Backup Manager - Add Files

4.) Still in the Files tab, tick the checkbox to the left of your .wbfs image, and then click on what looks like the Transfer category title and select ISO..

Wii Backup Manager - Transfer Files

5.) Pick where you want the converted .ISO file to be created and click the [OK] button

Wii Backup Manager - Place ISO

That’s it – job done! Transfer your ISO to your WBFS formatted USB drive and launch it as you normally would via USBLoaderGX or whatever your poison is… :)
Flattr this