new video recording system using ffmpeg + named pipes

Post Reply
spacy51
Senior Member
Posts: 371
Joined: Tue Mar 18, 2008 4:59 pm

new video recording system using ffmpeg + named pipes

Post by spacy51 »

I managed to write some very ugly code to test wether it is possible for VBA-M to encode with with an ffmpeg executable.

 

The answer is: YES, it is possible

 

I have to create a named pipe with the windows API and write the raw rgb24 image data to it while playing. ffmpeg.exe can then be started and the named pipe can be set as the input file.

 

The command line for ffmpeg looked as follows:

ffmpeg -r 60 -pix_fmt rgb24 -s 240x160 -f rawvideo -i \\.\pipe\vbam -f mp4 -b 1000000 -y vbam.mp4

 

This approach has many good points about it:

  • All encoding functionality resides in ffmpeg.exe (VBA-M.exe will not get bloated)
  • ffmpeg supports almost every video format/codec you can imagine.
  • No intermediate file necessary for encoding in any format

 

 

Here's a sample video file:

http://www.mediafire.com/file/i5j1znbjwnl/vbam.mp4

currently no sound implemented.

Last edited by spacy51 on Fri Nov 27, 2009 5:03 pm, edited 1 time in total.
mudlord
Senior Member
Posts: 306
Joined: Sun Feb 08, 2009 7:16 am

new video recording system using ffmpeg + named pipes

Post by mudlord »

Nach, any thoughts?

spacy51
Senior Member
Posts: 371
Joined: Tue Mar 18, 2008 4:59 pm

new video recording system using ffmpeg + named pipes

Post by spacy51 »

Hm, I am not sure wether I should record at 60 Hz or at 59.737 Hz. GBATEK states that 59.737 Hz is the time needed to refresh every display line once. Does VBA-M emulate it that way? How long is one frame of audio?

spacy51
Senior Member
Posts: 371
Joined: Tue Mar 18, 2008 4:59 pm

new video recording system using ffmpeg + named pipes

Post by spacy51 »

Hm, AVIWrite seems to be fine when using it with ffdshow.

Well, if anyone is interested in perfecting this, here's the code:

 

HANDLE hPipe

 

// create named pipe
hPipe = CreateNamedPipe(

Code: Select all

  _T( "\\\\.\\pipe\\vbam" ),


  PIPE_ACCESS_OUTBOUND,


  PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, // PIPE_NOWAIT needed ?


  1,


  240 * 160 * 3,


  240 * 160 * 3,


  0,


  NULL );

ASSERT( hPipe != INVALID_HANDLE_VALUE );

 

Code: Select all

BOOL retConnect = ConnectNamedPipe( hPipe, NULL );


ASSERT( retConnect != 0 );

 

inline void cpyImg32raw( unsigned char *dst, unsigned char *src, unsigned int srcPitch, unsigned short width, unsigned short height )

{

Code: Select all

unsigned char r, g, b;


unsigned short x = width;


const unsigned int garbage = srcPitch - ( width * 4 );

 

Code: Select all

while( height-- ) {


	while( x-- ) {


        r = *src++;


        g = *src++;


        b = *src++;


        src++; // unused 8 bit


        *dst++ = b;


        *dst++ = g;


        *dst++ = r;


	}


    x = width;


    src += garbage;


}

}

 

 

// prepare source image
unsigned char *bmp;

Code: Select all

	  unsigned short srcPitch = theApp.sizeX * ( systemColorDepth >> 3 ) + 4;


	  switch( systemColorDepth )


	  {

// case 16:

// bmp = new unsigned char[ theApp.sizeX * theApp.sizeY * 2 ];

// cpyImg16bmp( bmp, pix + srcPitch, srcPitch, theApp.sizeX, theApp.sizeY );

// break;

Code: Select all

	  case 32:


		  // use 24 bit colors to reduce video size


		  bmp = new unsigned char[ theApp.sizeX * theApp.sizeY * 3 ];


          cpyImg32raw bmp, pix + srcPitch, srcPitch, theApp.sizeX, theApp.sizeY );


		  break;


	  }

 

 

Code: Select all

  // send source image through pipe


  DWORD written = 0;


  BOOL ret = WriteFile( hPipe, bmp, theApp.sizeX * theApp.sizeY * 3, &written, NULL );


  DWORD err = GetLastError();


  ASSERT( ret == TRUE );

 

 

Code: Select all

	  delete bmp;

 

 

FlushFileBuffers( hPipe );
DisconnectNamedPipe( hPipe );

CloseHandle( hPipe );

 

 

ffmpeg.exe -r 59.7275 -pix_fmt bgr24 -s 240x160 -f rawvideo -i \\.\pipe\vbam -f mp4 -y vbam.mp4

Last edited by spacy51 on Sat Aug 29, 2009 5:59 am, edited 1 time in total.
spacy51
Senior Member
Posts: 371
Joined: Tue Mar 18, 2008 4:59 pm

new video recording system using ffmpeg + named pipes

Post by spacy51 »

And here's an example to get the audio part running as well: http://kylecordes.com/2007/07/05/pipe-ffmpeg/

Nach
Junior Member
Posts: 31
Joined: Tue Mar 18, 2008 10:02 am

new video recording system using ffmpeg + named pipes

Post by Nach »

Nach, any thoughts?

 

Yes, several actually.

 

I believe a method along these lines is the best way to encode.

1) It eliminates any platform specific video encoding libraries.

2) It eliminates needing to write any code to interface with those libraries which can get messy quickly.

3) It's easy to make cross platform.

4) It allows a user to easily set his own encoding options, and save them as a preset.

5) Programs can be swapped at any time to use whichever works best (MEncoder, FFMPEG, or anything else).

6) We get free support of any of the newest encoding methods without any reprogramming done on our part.

7) The code is rather easy, and the programmer doesn't need to learn any API beyond standard C if done correctly.

 

However, I don't necessarily agree with using a named piped (FIFO file). How to create a named pipe changes per OS, and some OSs have whacked out restrictions on named pipes like only on particular file systems or other nonsense.

 

Most of these command line operated encoding programs don't just works with files, but would accept input via stdin. So I prefer launching them via popen() which is standard C, and writing to them in a normal method, which gives maximum portability.

 

That's what I did in ZSNES. However I wrote specialized versions of popen() for Windows and Linux which returns a null pointer if it could not launch the executable.

 

The method should be user configurable to specify which program to use, how many passes to run, which commands to pass the program for each pass, and commands at the end to clean up the binary (such as running mkvmerge, or hexedit into an AVI new timecodes).

 

ZSNES begin of dump code: https://zsnes.bountysource.com/svn/!source/5224/trunk/src/zmovie.c#1984

 

Begin Dump: https://zsnes.bountysource.com/svn/!source/5224/trunk/src/zmovie.c#2263

 

Write Frame: https://zsnes.bountysource.com/svn/!source/5224/trunk/src/zmovie.c#236

 

Finish Dump: https://zsnes.bountysource.com/svn/!source/5224/trunk/src/zmovie.c#2203

 

Embed logo in video prior to dumping the video (see http://tasvideos.org for use of this) https://zsnes.bountysource.com/svn/!source/5224/trunk/src/zmovie.c#2173

 

Modified popen() for Windows: https://zsnes.bountysource.com/svn/!source/5224/trunk/src/win/safelib.c

 

Modified popen() for Linux (and other UNIXs): https://zsnes.bountysource.com/svn/!source/5224/trunk/src/linux/safelib.c#262

 

Creating user config file from developer's end: https://zsnes.bountysource.com/svn/!source/5224/trunk/src/md.psr

What user sees when editing config file: http://nach.pastebin.com/m3b752734

Custom config for FLV: http://ia340931.us.archive.org/0/items/Zsnes_zmv2flv_cfg_file/zmovie.cfg

 

Some guy who tweaked his own settings: http://www.mortenblog.net/2009/02/23/recording-snes-game-videoes-with-zsnes-and-mencoder/

 

Since I want to include encoding like this in other projects, I was thinking of making a completely emulator independent C++ class which handled dumping like this, with support for user settings, begin dump, write frames, finish up dump.

 

Hm, I am not sure wether I should record at 60 Hz or at 59.737 Hz. GBATEK states that 59.737 Hz is the time needed to refresh every display line once. Does VBA-M emulate it that way? How long is one frame of audio?

 

You should write it at whatever speed VBA-M goes at. In the case of audio, if need be, resample it as I do in ZSNES.

Last edited by Nach on Sun Nov 22, 2009 10:00 am, edited 1 time in total.
Squall Leonhart
Posting Freak
Posts: 1223
Joined: Tue Mar 18, 2008 9:21 am

new video recording system using ffmpeg + named pipes

Post by Squall Leonhart »

Suggestion.

 

Before we go about fkin with other parts of the emulator that don't need to be fked with just yet. Maybe addressing the issues we already have would be good.

 

The DirectInput bug is positively a show stopper for players wanting to use their gamepads, especially the thumbsticks, as these can make fighting games perform smoother.

mudlord
Senior Member
Posts: 306
Joined: Sun Feb 08, 2009 7:16 am

new video recording system using ffmpeg + named pipes

Post by mudlord »

Since I want to include encoding like this in other projects, I was thinking of making a completely emulator independent C++ class which handled dumping like this, with support for user settings, begin dump, write frames, finish up dump.

 

Awesome idea. I think this will be the best. For both our sakes. :heh:

 

The DirectInput bug is positively a show stopper for players wanting to use their gamepads, especially the thumbsticks, as these can make fighting games perform smoother.

 

Right, get me into a full blown VBA-M coding mood and then I'll see.

Last edited by mudlord on Mon Nov 23, 2009 4:51 pm, edited 1 time in total.
Squall Leonhart
Posting Freak
Posts: 1223
Joined: Tue Mar 18, 2008 9:21 am

new video recording system using ffmpeg + named pipes

Post by Squall Leonhart »

So i need you put you in your happy place... hmmmmm

 

[img]<fileStore.core_Emoticons>/emoticons/tongue.png[/img]/emoticons/tongue@2x.png 2x" width="20" height="20" /> i suppose getting your gf to bake you a cake wouldn't hurt D:

Post Reply