ffmpeg tutorial code

| No Comments | No TrackBacks
I've been doing a lot of ffmpeg programming lately and have been finding it extremely painful. There just isn't much for help out there, certainly no real documentation for using the viatal avcodec library.

'dranger' has about the only comprehensive tutorial around and it's showing its age at this point. There's a few newer notes about updating it, but even those don't cover the latest libavcodec API changes. So I figured I would throw out my version of the first tutorial file, tutorial01.c. The most important change is replacing the long excised img_convert call with the sws_scale call (which also requires creating the SwsContext object). I also just tweaked a couple of the calls to remove any deprecated API calls.

Have at it!

You can build it with the following command:

$     gcc  -o tutorial01 tutorial01.c -lavutil -lavformat -lavcodec -lz -lavutil -lswscale -lz
Download it here: tutorial01.c

// tutorial01.c
// Code based on a tutorial by Martin Bohme (boehme@inb.uni-luebeckREMOVETHIS.de)
// Tested on Gentoo, CVS version 5/01/07 compiled with GCC 4.1.1

// A small sample program that shows how to use libavformat and libavcodec to
// read video from a file.
//
// Use
//
// gcc -o tutorial01 tutorial01.c -lavformat -lavcodec -lz
//
// to build (assuming libavformat and libavcodec are correctly installed
// your system).
//
// Run using
//
// tutorial01 myvideofile.mpg
//
// to write the first five frames from "myvideofile.mpg" to disk in PPM
// format.

#include 
#include 
#include 
#include 

void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame) {
  FILE *pFile;
  char szFilename[32];
  int  y;
  
  // Open file
  sprintf(szFilename, "frame%d.ppm", iFrame);
  pFile=fopen(szFilename, "wb");
  if(pFile==NULL)
    return;
  
  // Write header
  fprintf(pFile, "P6\n%d %d\n255\n", width, height);
  
  // Write pixel data
  for(y=0; ydata[0]+y*pFrame->linesize[0], 1, width*3, pFile);
  
  // Close file
  fclose(pFile);
}

int main(int argc, char *argv[]) {
  AVFormatContext *pFormatCtx=NULL;
  int             i, videoStream;
  AVCodecContext  *pCodecCtx;
  AVCodec         *pCodec;
  AVFrame         *pFrame; 
  AVFrame         *pFrameRGB;
  AVPacket        packet;
  int             frameFinished;
  int             numBytes;
  uint8_t         *buffer;
  struct SwsContext *img_convert_ctx;
  int frameCount=0;
  
  if(argc < 2) {
    printf("Please provide a movie file\n");
    return -1;
  }
  // Register all formats and codecs
  av_register_all();
  
  // Open video file
  if(avformat_open_input(&pFormatCtx, argv[1], NULL, NULL)!=0)
    return -1; // Couldn't open file
  
  // Retrieve stream information
  if(av_find_stream_info(pFormatCtx)<0)
    return -1; // Couldn't find stream information
  
  // Dump information about file onto standard error
  av_dump_format(pFormatCtx, 0, argv[1], 0);
  
  // Find the first video stream
  videoStream=-1;
  for(i=0; inb_streams; i++)
    if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) {
      videoStream=i;
      break;
    }
  if(videoStream==-1)
    return -1; // Didn't find a video stream
  
  // Get a pointer to the codec context for the video stream
  pCodecCtx=pFormatCtx->streams[videoStream]->codec;
  
  // Find the decoder for the video stream
  pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
  if(pCodec==NULL) {
    fprintf(stderr, "Unsupported codec!\n");
    return -1; // Codec not found
  }
  // Open codec
  if(avcodec_open(pCodecCtx, pCodec)<0)
    return -1; // Could not open codec
  
  // Allocate video frame
  pFrame=avcodec_alloc_frame();
  
  // Allocate an AVFrame structure
  pFrameRGB=avcodec_alloc_frame();
  if(pFrameRGB==NULL)
    return -1;
  
  // Determine required buffer size and allocate buffer
  numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,
                              pCodecCtx->height);
  buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
  
  // Assign appropriate parts of buffer to image planes in pFrameRGB
  // Note that pFrameRGB is an AVFrame, but AVFrame is a superset
  // of AVPicture
  avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,
                 pCodecCtx->width, pCodecCtx->height);
  
  int w = pCodecCtx->width;
  int h = pCodecCtx->height;
  img_convert_ctx = sws_getContext(
    w, 
    h, 
    pCodecCtx->pix_fmt, 
    w, 
    h, 
    PIX_FMT_RGB24, 
    SWS_BICUBIC,
    NULL, 
    NULL, 
    NULL);

  // Read frames and save first five frames to disk
  i=0;
  while(av_read_frame(pFormatCtx, &packet)>=0) {
    // Is this a packet from the video stream?
    if(packet.stream_index==videoStream) {
      // Decode video frame
      int len = avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
      if ( len < 0 )
      {
        fprintf(stderr, "Problems decoding frame\n");
        return 1;
      }

      fprintf(stderr, "len = %d\n", len );
      
        
      
      // Did we get a video frame?
      if(frameFinished) {
        ++frameCount;
        
        fprintf(stderr, "Saving frame %d\n", frameCount);
        
#if 0 // this is the old code
        img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24, 
                    (AVPicture*)pFrame, pCodecCtx->pix_fmt, 
                    pCodecCtx->width, pCodecCtx->height);
#else
        sws_scale(
          img_convert_ctx, 
          (const uint8_t* const*)pFrame->data, 
          pFrame->linesize, 
          0, 
          pCodecCtx->height, 
          pFrameRGB->data,
          pFrameRGB->linesize);
#endif
        
        // Save the frame to disk
        if(++i<=5)
          SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, 
                    i);
      }
    }
    
    // Free the packet that was allocated by av_read_frame
    av_free_packet(&packet);
  }
  
  // Free the RGB image
  av_free(buffer);
  av_free(pFrameRGB);
  
  // Free the YUV frame
  av_free(pFrame);
  
  // Close the codec
  avcodec_close(pCodecCtx);
  
  // Close the video file
  av_close_input_file(pFormatCtx);
  
  return 0;
}
Enhanced by Zemanta

My Little Menu

| No Comments | No TrackBacks

One of the main reasons I was looking for a launch bar was that I created a menu for all my DOS games, using mygtkmenu. Once you create this menu, it just cries out for somewhere to attach it, and wbar fits the bill perfectly.

I have a bunch of old DOS (redundant much?) games that I decided to install. In addition to the ones I own (including the priceless Definitive Wargame Collection), the wonderful Good Old Games site ships several of theirs using DOSBox and even Steam uses it for classics like "X-COM : UFO".

First I would create a short script file to run the game. Due to a bug in the X.org driver, it required a work around; namely, telling SDL (the library used by DOSBox) to not "DGA" mouse (or draw directly to video memory). It seems to be fixed so i took it out.

#! /bin/bash
#export SDL_VIDEO_X11_DGAMOUSE=0
cd /mediax/games/MAGIC
dosbox -conf dosbox.conf

Then I would either grab a screenshot from the game (using Ctrl-F5) or search the web for an icon. And then edit my gamemenu.xml file and add an entry like this:

item = Master of Magic
cmd = "/home/jdarnold/bin/mom"
icon = /home/jdarnold/icons/masterofmagic.jpg
dosboxmenu1.pngFor my Definitive Wargame Collection, I created a slightly more generic batch file:

#! /bin/bash
cd /mediax/games/WARGAMES
dosbox -conf dosbox.conf $1/$2 -c "cd $1" -exit

Here I cd into the WARGAMES folder and it gets passed a directory and an executable, so mygtkmenu entry looks like this:

SUBMENU = Definitive Wargame Collection #1
icon = /home/jdarnold/icons/CompleteWargameCollection.jpg

item = Complete Games Menu
cmd = "/home/jdarnold/bin/wargames"
icon = /home/jdarnold/icons/CompleteWargameCollection.jpg

item = Decisive Battles of the Civil War
cmd = /home/jdarnold/bin/wargame1 ACW DB.EXE
icon = /home/jdarnold/icons/DecisiveBattles.png

So I've created a sub-menu off the main menu and I pass in the sub-directory and the executable for the app. In a later installment, I'll talk a little more about DOSBox, which is a really nice program. Here's a couple of shots of the final product:

dosboxmenu2.png

Enhanced by Zemanta

Arch Linux promo video

| No Comments | No TrackBacks
Love this short Arch Linux promo video!


Enhanced by Zemanta

Openbox Time

| No Comments | 1 TrackBack
Ooops - I forgot to mention in my Blue Period post what Window Manager I have been using. I had the post about 90% done and started playing with some of the cool new buttons in the MovableType post editor and things went haywire and I lost most of it :( I guess I forgot to add the window manager back in.

In keeping with the The Arch Way, I decided to stay away from big heavy "Desktop Environments" like KDE or GNOME and explored some of the lesser known and more lightweight Window Managers. I settled on Openbox. Not sure why exactly, as there are a plethora of choices, but Openbox seemed nicely compact and pretty popular with the Arch Linux crowd. And I haven't looked back really. It's pretty easily configurable, with a couple of XML files being the most prominent config files - rc.xml for most of the config and menu.xml for the right click menu. One particularly cool thing to use is a "pipe menu", where the results of a command build a menu on the fly. The very prolific Arch user Xyne has created obfilebrowser, which creates a menu based upon the folder you point it at, so you can use it like a little file browser. Another useful menu generation tool is menumaker, which you run once and it creates a menu.xml file for you. It scans all the "usual" places for apps, as well as having a few custom algorithms for finding those out of the way apps. Unfortunately, it seems to be abandoned, as I don't see any updates to it in several years, although it does seem to work okay.

Add the fairly lightweight and equally configurable tint2 & wbar and you've got yourself a very workable X Window environment.

Enhanced by Zemanta

My Blue Period

| No Comments | 1 TrackBack
After getting tired of the green desktop on my Arch Linux box, I played a bit with some backgrounds and colors and came up with my Blue Period desktop:

Screenshot Blue.png(click for larger image)

So this is my new desktop, devoid of (almost) any windows. There's plenty of screen real estate, as I have 24" & 21" monitors running in Twinview mode, for a whopping 3600x1050 pixels. Here's what I'm showing, from left to right:
  • A wbar launch menu. It has some nice OSX-type animations. Funny, I was just thinking I wanted a launcher for a couple programs. I usually use Launchy but some of them I'd rather not. And then someone mentioned wbar in the addicting Screenshots topic in the Arch Linux forums. So I checked it out and despite the total lack of documentation, I figured out how to use it. Be sure to get wbarconf too, to help set up the menu.
  • The background is from the Desktopography 2009 exhibition. I was thinking I wanted an outerspace picture and this really fit in with that idea and going blue. And it came in a nice big size too. My "wallpapers" Delcious bookmarks can be found here.
  • The dropdown window is a Yakuake terminal window, my favorite terminal emulator. It hides away nicely.
  • At the bottom is a tint2 task manager. I used to have it go across both sreens but it made the sys tray apps too hard to get to, so I just have it go across one desktop now. I use tintwizard to tame the multiple config options.
  • Top right is my fairly simple conky display. I need to get back to hacking on it again.
And here's a more "busy" display of my desktop:

Screenshot Blue Busy.pngClick for full display
Here I'm running a few of my standard apps:

Edited to add: I forgot to add what Window Manager I was using - I go into more details of my Openbox install here.

Related articles
Enhanced by Zemanta

Am I Back?

| No Comments | No TrackBacks
Just spent the morning moving my MovableType blogs (like Daemon Dancing) from MT 3.2 to MT 5.031. It's a bit of a pain, as you have to move one step at a time from one update to the next, so it took 4 (!) upgrades, but I think it is working. At least, if you see this it is working :) Now I hope to get back to more regular posting on my Linux adventures.

Anyway, here's a pretty funny video I came across. It has a special resonance, not just because I love writing code in C & C++, but also because I am reading the wonderful Bob Spitz biography on The Beatles.

Write in C - Let It Be Cover

Enhanced by Zemanta

Do It Sudo

| No Comments | No TrackBacks

I've come across a couple sudo tricks during the past few days and thought I would pass them along.

The first thing you need to know before using sudo is that you should use the visudo command to edit the sudo config file. This script does a number of useful things, like creating a lock to prevent mulitple editing, and doing some sanity check. But if you have the problem that setting $EDITOR and $VISUAL is ignored when running something with sudo (like sudo visudo or sudo crontab -e), that's a sudo config issue. Add the following in your /etc/sudoers file:

Defaults env_keep += "EDITOR VISUAL"

And you can use sudo from within your normal Emacs window by using the Emacs' Tramp Mode, which allows all kinds of editing, even remote editing. Just use the sudo "protocol" when editing a system file, like /etc/fstab:

Find file: /sudo::/etc/fstab

This will prompt you for your password (not the root password - remember, we're doing this via sudo, which wants your password, not root's). Type it in and you can edit the file in place, rather than running a special Emacs process as root. Very nice!

December 2011

Sun Mon Tue Wed Thu Fri Sat
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

Recent Comments

  • redsolelouboutin2u: A lot of women would do make up. But read more
  • redsolelouboutin2u: Babyliss Curling Wand red is great!It leave your hair really read more
  • naveennishad: To enable login as root in KDE open /etc/kde4/kdm/kdmrc and read more
  • Saviq: It's best to use './bootstrap' instead of autoconf itself. read more
  • Jonathan: I'd rather depend on a Linux module like ntfs-3g working read more
  • gormux: sorry but i think you did wrong : first never read more
  • Jonathan: Not sure why it would say it won't work, as read more
  • Jens Andreasen: Hi, I have exactly this problem, and have been trying read more
  • oes tsetnoc: well when i tried to configure smba - everything went read more
  • oes tsetnoc: Fantastic, straight to the point and very usable ... wish read more

A Few Random Entries

Portsnap Magic flag
(Apr 26, 2006)
We've Got Another Live One!
(Jan 12, 2007)
PC-BSD stuff
(May 12, 2006)
Tuning your FreeBSD installation
(Apr 5, 2005)
Text mode browsers
(Jan 22, 2004)

Recent Assets

  • dosboxmenu2.png
  • dosboxmenu1.png
  • Screenshot Blue Busy.png
  • Screenshot Blue.png