Click here to Skip to main content
Click here to Skip to main content

Extracting AVI Frames

By , , 5 Nov 2004
 

Introduction

In the last project that I worked on, the project required to extract frames of an AVI movie and save them as bitmaps files. Here I want to share my experiences in this project with you.

AVIFile Functions

The best way to obtain information about AVI format and learn more about the internal behavior of the file, is going directly to MSDN as I did. The AVI related functions are inside vfw.h header file. This means you must include this header and add vfw32.lib library file to your project.

Here is the list of functions that I used in the project and a brief information about them (taken from MSDN):

void AVIFileInit(void); The AVIFileInit function initializes the AVIFile library.
void AVIFileOpen(PAVIFILE* ppfile, LPCTSTR szFile, UINT mode, CLSID pclsidHandler); The AVIFileOpen function opens an AVI file and returns the address of a file interface used to access it.
void AVIFileInfo(PAVIFILE pfile, AVIFILEINFO* pfi, LONG lSize); The AVIFileInfo function obtains information about an AVI file.
void AVIFileGetStream(PAVIFILE pfile, PAVISTREAM* ppavi, DWORD fccType, LONG lParam); The AVIFileGetStream function returns the address of a stream interface that is associated with a specified AVI file.
LONG AVIStreamStart(PAVISTREAM pavi); The AVIStreamStart function returns the starting sample number for the stream.
LONG AVIStreamLength(PAVISTREAM pavi); The AVIStreamLength function returns the length of the stream.
PGETFRAME AVIStreamGetFrameOpen(PAVISTREAM pavi, LPBITMAPINFOHEADER lpbiWanted); The AVIStreamGetFrameOpen function prepares to decompress video frames from the specified video stream.
LPVOID AVIStreamGetFrame(PGETFRAME pgf, LONG lPos); The AVIStreamGetFrame function returns the address of a decompressed video frame.
void AVIStreamGetFrameClose(PGETFRAME pget); The AVIStreamGetFrameClose function releases resources used to decompress video frames.
LONG AVIStreamRelease(PAVISTREAM pavi); The AVIStreamRelease function decrements the reference count of an AVI stream interface handle, and closes the stream if the count reaches zero.
void AVIFileExit(void); The AVIFileExit function exits the AVIFile library and decrements the reference count for the library.

Now it's time to write some code:

BOOL ExtractAVIFrames(CString szFileName)
{
    AVIFileInit();

    PAVIFILE avi;
    int res=AVIFileOpen(&avi, szFileName, OF_READ, NULL);

    if (res!=AVIERR_OK)
    {
        //an error occures
        if (avi!=NULL)
            AVIFileRelease(avi);
        
        return FALSE;
    }

    AVIFILEINFO avi_info;
    AVIFileInfo(avi, &avi_info, sizeof(AVIFILEINFO));

    CString szFileInfo;
    szFileInfo.Format("Dimention: %dx%d\n"
                      "Length: %d frames\n"
                      "Max bytes per second: %d\n"
                      "Samples per second: %d\n"
                      "Streams: %d\n"
                      "File Type: %d", avi_info.dwWidth,
                            avi_info.dwHeight,
                            avi_info.dwLength,
                            avi_info.dwMaxBytesPerSec,
                            (DWORD) (avi_info.dwRate / avi_info.dwScale),
                            avi_info.dwStreams,
                            avi_info.szFileType);

    AfxMessageBox(szFileInfo, MB_ICONINFORMATION | MB_OK);

    PAVISTREAM pStream;
    res=AVIFileGetStream(avi, &pStream, streamtypeVIDEO /*video stream*/, 
                                               0 /*first stream*/);

    if (res!=AVIERR_OK)
    {
        if (pStream!=NULL)
            AVIStreamRelease(pStream);

        AVIFileExit();
        return FALSE;
    }

    //do some task with the stream
    int iNumFrames;
    int iFirstFrame;

    iFirstFrame=AVIStreamStart(pStream);
    if (iFirstFrame==-1)
    {
        //Error getteing the frame inside the stream

        if (pStream!=NULL)
            AVIStreamRelease(pStream);

        AVIFileExit();
        return FALSE;
    }

    iNumFrames=AVIStreamLength(pStream);
    if (iNumFrames==-1)
    {
        //Error getteing the number of frames inside the stream
        
        if (pStream!=NULL)
            AVIStreamRelease(pStream);
        
        AVIFileExit();
        return FALSE;
    }

    //getting bitmap from frame
    BITMAPINFOHEADER bih;
    ZeroMemory(&bih, sizeof(BITMAPINFOHEADER));

    bih.biBitCount=24;    //24 bit per pixel
    bih.biClrImportant=0;
    bih.biClrUsed = 0;
    bih.biCompression = BI_RGB;
    bih.biPlanes = 1;
    bih.biSize = 40;
    bih.biXPelsPerMeter = 0;
    bih.biYPelsPerMeter = 0;
    //calculate total size of RGBQUAD scanlines (DWORD aligned)
    bih.biSizeImage = (((bih.biWidth * 3) + 3) & 0xFFFC) * bih.biHeight ;

    PGETFRAME pFrame;
    pFrame=AVIStreamGetFrameOpen(pStream, 
           NULL/*(BITMAPINFOHEADER*) AVIGETFRAMEF_BESTDISPLAYFMT*/ /*&bih*/);
    
    //Get the first frame
    int index=0;
    for (int i=iFirstFrame; i<iNumFrames; i++)
    {
        index= i-iFirstFrame;

        BYTE* pDIB = (BYTE*) AVIStreamGetFrame(pFrame, index);
        
        CreateFromPackedDIBPointer(pDIB, index);
    }

    AVIStreamGetFrameClose(pFrame);

    //close the stream after finishing the task
    if (pStream!=NULL)
        AVIStreamRelease(pStream);

    AVIFileExit();

    return TRUE;
}

The only one function that I must describe more about is: CreateFromPackedDIBPointer(). This function takes a pointer returned from AVIStreamGetFrame() function and creates a bitmap from it. As you know, the AVIStreamGetFrame() returns a pointer to DIB information about the frame. We take this pointer and create a bitmap from it.

BOOL CreateFromPackedDIBPointer(LPBYTE pDIB, int iFrame)
{
    ASSERT(pDIB!=NULL);

    //Creates a full-color (no palette) DIB from a pointer to a
    //full-color memory DIB

    //get the BitmapInfoHeader
    BITMAPINFOHEADER bih;
    RtlMoveMemory(&bih.biSize, pDIB, sizeof(BITMAPINFOHEADER));

    //now get the bitmap bits
    if (bih.biSizeImage < 1)
    {
        return FALSE;
    }

    BYTE* Bits=new BYTE[bih.biSizeImage];

    RtlMoveMemory(Bits, pDIB + sizeof(BITMAPINFOHEADER), bih.biSizeImage);

    //and BitmapInfo variable-length UDT
    BYTE memBitmapInfo[40];
    RtlMoveMemory(memBitmapInfo, &bih, sizeof(bih));

    BITMAPFILEHEADER bfh;
    bfh.bfType=19778;    //BM header
    bfh.bfSize=55 + bih.biSizeImage;
    bfh.bfReserved1=0;
    bfh.bfReserved2=0;
    bfh.bfOffBits=sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER); //54
    
    CString FileName;
    FileName.Format("Frame-%05d.bmp", iFrame);
    
    FILE* fp=fopen(FileName, "wb");
    if (fp!=NULL)
    {
        fwrite(&bfh, sizeof(bfh), 1, fp);
        fwrite(&memBitmapInfo, sizeof(memBitmapInfo), 1, fp);
        fwrite(Bits, bih.biSizeImage, 1, fp);
        fclose(fp);
    }
    else
    {
        TRACE0(_T("Error writing the bitmap file"));
        return FALSE;
    }

    delete [] Bits;
    return TRUE;
}

Enjoy!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Authors

A. Riazi
Iran (Islamic Republic Of) Iran (Islamic Republic Of)
Member
I was born in Shiraz, a very beautiful famous city in Iran. I started programming when I was 12 years old with GWBASIC. Since now, I worked with various programming languages from Basic, Foxpro, C/C++, Visual Basic, Pascal to MATLAB and now Visual C++.
I graduated from Iran University of Science & Technology in Communication Eng., and now work as a system programmer for a telecommunication industry.
I wrote several programs and drivers for Synthesizers, Power Amplifiers, GPIB, GPS devices, Radio cards, Data Acqusition cards and so many related devices.
I'm author of several books like Learning C (primary and advanced), Learning Visual Basic, API application for VB, Teach Yourself Object Oriented Programming (OOP) and etc.
I'm winner of January, May, August 2003 and April 2005 best article of month competetion, my articles are:

You can see list of my articles, by clicking here


Shafiee
Web Developer
Iran (Islamic Republic Of) Iran (Islamic Republic Of)
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Questiondata to display the picturememberRoman Tarasov13 Mar '13 - 4:07 
Hi
 
This article is very short and helpful.
 
My question will be very short too. What data structures do I need to display the frame from AVI file via GDI? Is it enough to thansfer just BITMAPINFOHEADER and picture bits?
 
Best regards,
Roman
 
romantarasov1107@gmail.com
GeneralMy vote of 5membermanoj kumar choubey26 Feb '12 - 19:50 
Nice
Questionbad pointer..PLEASE HELP!memberMember 866456721 Feb '12 - 1:08 
the code was not running properly, so i ran "watch" on pFrame. Even after the function AVIStreamGetFrameOpen is called pFrame is not assigned and message comes
__vfptr = CXX0030: Error: expression cannot be evaluated.
And hence later BYTE * pDIB shows bad ptr. please help.
 
PS - I'm new to windows programming and my project requires conversion of one frame to unsigned char * (or BYTE). so if there is an easier method pls suggest.
GeneralBMP2AVI [modified]membermmssrr25 Jan '12 - 9:32 
سلام
اگه امکان داره به من ایمیل بزنید
برای تبدیل چند عکس به فیلم مشکل دارم
mohammad60002000@yahoo.com
ممنون

modified 29 Jan '12 - 16:08.

QuestionVery useful code...memberDestiny77723 Aug '11 - 13:48 
This was helpful in extracting the First Video Frame of the AVI File to create a thumbnail.
 
Was also useful in extracting each AVI Video Frame then writing each AVI Video Frame into a New AVI File using a different Video Compression Codec using the same frame rate as the original AVI Video File.
- Do NOT ask me for the code to do this as it was used to recreate the AVI for a specific customer using their compression.
* There are some sample programs that will help you do this same thing on your own.
 
Thanks for a nice sample to extract AVI Video Frames.
 
Smile | :)
Generali need source code for matlabmemberNareshKrishna4 Oct '09 - 18:52 
HI,
I need source code for how to apply quantization to video frames to extract the features from it???
Generalcreate a grayscale 8bit bitmapmembertavale17 Sep '09 - 4:40 
thank you for the code
 
I want tell you can I create a 8bit grayscale bitmap from the frame that I extract from the video..thanks
QuestionBitmap variablememberryan11725 Jun '09 - 3:03 
Riazi;
Your code is very nice. Could you tell me how do I create a bitmap variable instead to write it into a file, please?
Thank You.
GeneralVery good!memberMember 34022796 Feb '09 - 16:00 
Thank U!
Your article is usefull!I like it!
QuestionQuery frame index?memberSwinefeaster2 Feb '09 - 9:16 
Thanks for the great article. Would you know how to query which frame index the avi is currently on while it is playing?
 
Thanks!

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 5 Nov 2004
Article Copyright 2004 by A. Riazi, Shafiee
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid