Synthesis and decomposition of AVI files using VC ++

Source: Internet
Author: User
Tags bmp image microsoft video
Abstract: This article analyzes the storage structure of AVI files in detail, introduces a set of Apis provided by Microsoft to operate AVI files, and uses the example code, demonstrate how to synthesize a set of static BMP images into an AVI video file and parse and save an AVI video file as a series of BMP image files. Keywords: AVI file BMP image VC Avi is the abbreviation of audio video interleaved, it is a digital audio and video file format developed by Microsoft to comply with Riff file specifications. It was originally used in Microsoft Video for Windows (VFW for short) environments, it is now directly supported by most operating systems, such as Windows 95/98 and OS/2. The AVI format allows video and audio to be played in parallel and supports 256-color and RLE compression, but the AVI file is not limited to compression standards. Therefore, the AVI file format is only used as the standard on the control interface, non-compatible. AVI files generated using different compression algorithms must be decompressed to play out. Commonly used Avi playback drivers include Microsoft Video for Windows or Windows 95/98 Video 1 and Intel's Indeo video. Before introducing the AVI file, let's take a look at the structure of the riff file. AVI files use the riff file structure. Riff (resource Interchange File Format) is a file format defined by Microsoft to manage multimedia data in windows, waveform audio wave, Midi, and digital video Avi are stored in this format. The basic unit for constructing a riff file is called a chunk. Each data block contains three parts and a 4-byte data block mark (or the ID of the data block) 2. data block size 3. The entire riff file can be regarded as a data block. Its data block ID is Riff, which is called riff block. Only one riff block is allowed in a riff file. A riff block contains a series of sub-blocks. One of the block IDS is "list", which is called list. A list block can contain a series of sub-blocks, however, all sub-blocks except list blocks cannot contain sub-blocks. Riff and list blocks have one more data field called form type and list type than normal data blocks, which are composed of the following: 1 4-byte chunk ID (chunk ID) 2 data block size 3 4-byte format type or list type 4 data below let's look at the structure of the AVI file. AVI files are currently the most complex riff files used. They can simultaneously store audio and video data during synchronization. The format of the AVI riff block is Avi, which contains three sub-blocks, as described below: 1 Information block, a list block with an ID of "hdrl", defining the data format of the AVI file. 2 Data blocks, a list block with the ID of "movi", including the AVI audio and video sequence data 3 index blocks, and the ID is the sub-block with the ID of "idxl, the index data that defines the "movi" list block. It is an optional block. Shows the structure of the AVI file. The following describes the construction of each sub-block of the AVI file. 1. The information block contains two sub-blocks: A sub-block with the ID of avih and a list block with the ID of strl. The content of the "avih" sub-block can be defined by the following structure: typedef struct {DWORD dwmicrosecperframe; // display the time NS required for each shard, define the display rate of avi dword dwmaxbytespersec; // maximum data transmission rate DWORD dwpaddinggranularity; // The length of the record block must be a multiple of this value, usually 2048 DWORD dwflages; // special attribute of the AVI file, for example, whether the index block is included or whether the audio and video data are cross-stored DWORD dwtotalframe; // The total number of audio and video data in the file DWORD dwinitialframes; // The number of audio and video data streams required before playback; // The data stream type DWORD dwsuggestedbuffersize contained in the file; // The recommended buffer size, // usually the sum of the data required for storing a pair of images and synchronizing Sounds d Word dwwidth; // Image Width DWORD dwheight; // Image Height DWORD dwreserved [4]; // reserved value} mainaviheader; "strl" list block is used to record AVI data streams, each data stream occupies three sub-blocks in the list. Their IDs are "strh", "STRF", and "strd "; the "strh" sub-block is defined by the following structure: typedef struct {fourcc fcctype; // 4 bytes, which indicates the type of data stream vids indicates the video data stream // auds audio data stream fourcc fcchandler; // 4 bytes, which indicates the driver code of data stream decompression DWORD dwflags; // data stream attribute word wpriority; // The playback priority word wlanguage of this data stream; // The audio language code DWORD dwinitalframes; // you need DWORD dwscale; // data volume, video size per region or audio sampling size DWORD dwrate; // dwscale/dwrate = number of samples per second DWORD dwstart; // The position where the data stream starts to play, in dwscale DWORD dwlength; // the data stream data volume, in dwscale DWORD dwsuggestedbuffersize; // The recommended buffer size DWORD dwquality; // extract the quality parameter. The larger the value, the better the quality. DWORD dwsamplesize; // The audio sampling size rect rcframe; // The rectangle occupied by the video image} avistreamheader; the structure of the "STRF" sub-block is determined by the type of the "strh" sub-block after the "strh" sub-block. If the strh sub-block is a video data stream, the content of the STRF sub-block is a bitmap independent of the Windows Device. Bimapinfo structure: typedef struct tagbitmapinfo {bitmapinfoheader bmiheader; rgbquad bmicolors [1]; // color table} bitmapinfo; typedef struct detail {DWORD bisize; long biwidth; long biheight; Word biplanes; word bibitcount; DWORD bicompression; DWORD bisizeimage; long bixpelspermeter; long biypelspermeter; DWORD biclrused; DWORD biclrimportant;} bitmapinfoheader; if the strh sub-block is an audio data stream, the content of the STRF sub-block is a waveform. At structure: typedef struct {word wformattag; Word nchannels; // number of channels DWORD nsamplespersec; // sampling rate DWORD navgbytespersec; // word nblockalign; // The alignment sign of the data block word bisize; // size of this structure} The waveformat "strd" sub-block follows the STRF sub-block and stores the parameters used by the compression driver, not necessarily exist, and there is no fixed structure. The Avi Data Streams defined in the "strl" list block are sequentially linked with the data stream header structure in the "hdrl" list block and the data in the "movi" list block, the first data stream header structure is used for data stream 0, the second is used for data stream 1, and so on. The data block stores video and audio data streams, and the data can be directly stored in the "movi" list block. Audio and video data in data blocks are stored in different word blocks. The structure of the audio block "# WB" wave data stream video sub-blocks is described as follows, we can see the image data streams compressed by "# DB" RGB data streams "# DC". The image data of AVI files can be compressed, non-compressed format. Different encoding formats can also be used for compression. You may have encountered some problems that Avi cannot recognize because of different encoding methods. Without corresponding decoding, you will not be able to recognize video data. There are many Avi encoding methods, such as MPEG2, MPEG4, and DivX. Index block: The index quickly contains the index of the data block in the file, which can improve the read and write speed of AVI files, including a set of aviindexentry structure data. As shown below, this block is not required and may not exist. Typedef struct {DWORD ckid; // record the DWORD dwflags of the neutron block of the data block; // It indicates the attribute DWORD dwchunkoffset of the child block referred to by the chid; // DWORD dwchunklength; // sub-block length}; OK. Now I believe you will be clear about the AVI file structure. After introducing the AVI file structure, let's take a look at how to read and write AVI files. In order to read and write AVI files, Microsoft provides a set of APIs with a total of 50 functions. They are mainly used in two categories, one is the operation of AVI files, and the other is the operation of streaming streams. 1. open and close the file avifileopen, avifileaddref, and avifilerelease2. Read the file information from the file and use avifileinfo to obtain information about the AVI file, this function returns an avifileinfo structure. avifilereaddata can be used to obtain information not obtained by the avifileinfo function. This information may not be contained in the file header, such as the name of the company or individual that owns the file. 3. You can use the avifilewritedata function to write additional information about the file. 4. opening or closing a stream opening a data stream is the same as opening a file. You can use the avifilegetstream function to open a data stream. This function creates a stream interface, then, a handle is saved in the interface. If you want to operate a single stream of a file, you can use the avistreamopenfromfile function, which integrates avifileopen and avifilegetstream functions. If you want to operate multiple data streams in the file, you must first avifileopen and then avifilegetstream. You can use avistreamaddref to add stream interface references. Use the avistreamrelease function to disable data streams. This function is used to reduce the reference count of streams. It is deleted when the count is reduced to 0. 5. The avistreaminfo function reads data and information from the stream to obtain some data information. This function returns an avistreaminfo structure, which contains the data type compression method. The recommended buffersize, playback rate and description. If the data stream has additional information, you can use the avistreamreaddata function to obtain it. The application allocates a memory and passes it to this function. Then, this function returns the data stream information through the memory. The additional information may include the data stream compression and decompression methods, you can use the avistreamdatasize macro to return the size of the memory block to be applied. You can use the avistreamreadformat function to obtain the format information of the data stream. This function returns the format information of the data stream through the specified memory. For example, for video streams, this buffer contains a bimapinfo structure. For audio streams, the memory block contains the waveformatex or pcmaveformat structure. You can obtain the buffer size by passing an empty buffer to avistreamreadformat. You can also use the avistreamformatsize macro. You can use the avistreamread function to return multimedia data. This function copies data to the memory provided by the application. For video streams, this function returns the image watermark. For audio streams, this function returns the audio sample data. You can pass a null buffer to avistreamread to obtain the required buffer size. You can also use the avistreamsamplesize macro to obtain the buffer size. Some Avi Data Stream handles may need to be prepared before starting the data stream. At this time, we can call the avistreambeginstreaming function to inform the Avi Data Stream handle to apply for allocating some resources it needs. Call the avistreamendstreamming function to release resources. 6. compress the video data. If you want to demonstrate one or several compression operations on the video image, you can call the avistreamread function to pass the obtained data to the drawdib function to display the image. These functions can display compressed and uncompressed images. Avifile also provides the avistreamgetframeopen function to obtain uncompressed video streams. This function creates a memory to obtain uncompressed data. You can also use the avistreamgetframe function to extract a single video clip. This function can extract an image from a certain region and return the data in a bimapinfoheader structure. After calling the avistreamgetframe function, you must call the avistreamgetframeclose function to release the resources applied by the previous function. 7. To create a file containing multiple data streams based on an existing data stream, you can integrate multiple data streams and write them into a new file. These data streams can be stored in memory or in another file. We can use the avisave function to build a file. This function can create a file and write multiple specified data streams to the file in the specified sequence. You can also use the avisavev function to create a new file, this function has the same function as avisave. The main difference is that avisavev uses an array of data streams, while avisave is a single data stream that is saved multiple times. You can call the avisaveoptions function to display a dialog box that allows you to select the compression mode. You can specify a callback function when calling the avisave and avisavev functions to display the progress of generating an AVI file. This allows you to cancel generating an AVI file at any time. You can call the getsavefilenamepreview function to display the saved dialog box and select the saved file name. Through the avimakefilefromstreams function, we can create a virtual file handle. Other Avi functions can use this virtual file handle to operate on the data stream in the file. After the operation is complete, remember to call avifilerelease for release. 8. Write a data stream to the file. We can use the avifilecreatestream function to create a data stream in a new file or an existing file. This function defines a new data stream based on the avistreaminfo structure and creates an interface for the new data stream to return the pointer to the interface. Before writing new data, you must specify the stream format information. By using the avistreamsetformat function, you must use the bimapinfo structure to set a video stream, and use waveformat for audio. Then we can write our multimedia data into the data stream through the avistreamwrite function. This function copies the memory data provided by the application to the specified stream. The default Avi handler writes data to the end of the stream. If you have additional information to write to the stream, you can call avifilewritedata or avistreamwritedata. Remember to call avistreamrelease after data writing is completed. 9. Locate the Starting sequence of the sequence in the data stream: You can use the avistreamstart function to obtain the sample number contained in the first sequence. You can also use the avistreaminfo function to obtain this information. The avistreaminfo structure of this function contains dwstart. You can use the avistreamstarttime macro to obtain the first sample. You can use the avistreamlength function to obtain the stream length. This function returns the number of samples in the stream. You can also use the avistreaminfo function to obtain the information. You can use the avistreamlengthtime macro to obtain the stream length in milliseconds. In a video stream, a sample corresponds to a sequence of images. Therefore, sometimes there is no video data in these samples. If you call the avistreamread function for data, null may be returned, you can also use avistreamfindsample to find the specified sample by specifying the find_any flag. Find the key samples and use the avistreamfindsample function to find the sample that matches the search. Then, you can use the following macro to determine whether the key samples are used. The function of switching avistreamsampletotime between time and sample can convert smaple to milliseconds. For a video, this value indicates the start time of the player. After learning about the above knowledge, we can understand the structure of the AVI file and how to operate the AVI file. Now we can start programming. We need to do two things: 1. How to synthesize a static BMP bitmap into an AVI video file, 2. How to parse an uncompressed AVI file into a bitmap. The sample program interface is as follows:
The following function demonstrates how to save all BMP files in a folder as an AVI file. The first parameter of the function is the AVI file name to be generated, the second parameter is the name of the folder where the BMP file is stored. This function will enumerate all BMP files in the folder and synthesize an AVI file. Void cbmp2avidlg: avitobmp (cstring stravifilename, cstring strbmp DIR) {// todo: add the control notification handler code avifileinit (); pavifile Avi; int res = avifileopen (& Avi, stravifilename, of_read, null); int n = getlasterror (); If (res! = Avierr_ OK) {// an error occures if (Avi! = NULL) avifilerelease (AVI); return;} avifileinfo avi_info; avifileinfo (AVI, & avi_info, sizeof (avifileinfo); pavistream pstream; Res = avifilegetstream (AVI, & pstream, streamtypevideo/* video stream */, 0/* first stream */); If (res! = Avierr_ OK) {If (pstream! = NULL) avistreamrelease (pstream); avifileexit (); return;} // do some tasks 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;} inumframes = avistreamlength (pstream); If (inumframes =-1) {// error getteing the number of frames inside the stream if (pstream! = NULL) avistreamrelease (pstream); avifileexit (); return;} // 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 alig Ned) BiH. bisizeimage = (BIH. biwidth * 3) + 3) & 0 xfffc) * BiH. biheight; pgetframe pframe; pframe = bytes (pstream, null); avistreaminfo streaminfo; avistreaminfo (pstream, & streaminfo, sizeof (avistreaminfo); // get the first frame bitmapinfoheader bih2; long lsize = sizeof (bih2); int Index = 0; For (INT I = ifirstframe; I <inumframes; I ++) {Index = I-ifirstframe; byte * pdib = (byte *) AVIS Treamgetframe (pframe, index); // avistreamreadformat (pstream, index, & bih2, & lsize); bitmapfileheader stfilehdr; byte * bits = new byte [bih2.bisizeimage]; avistreamread (pstream, index, 1, bits, bih2.bisizeimage, null, null); // rtlmovememory (bits, pdib + sizeof (bitmapinfoheader), bih2.bisizeimage); bih2.biclru= 0; stfilehdr. bfoffbits = sizeof (bitmapfileheader) + sizeof (bitmapinfoheader); stfilehdr. bfsize = sizeof (Bitmapfileheader); stfilehdr. bftype = 0x4d42; cstring filename; filename. format ("frame-rj05d.bmp", index); cstring strtemp = strbmp dir; strtemp + = "//"; strtemp + = filename; file * fp = _ tfopen (strtemp, _ T ("WB"); fwrite (& stfilehdr, 1, sizeof (bitmapfileheader), FP); fwrite (& bih2, 1, sizeof (bitmapinfoheader), FP ); int FF = fwrite (bits, 1, bih2.bisizeimage, FP); int e = getlasterror (); fclose (FP); // Delete bi TS; // createfrompackeddibpointer (pdib, index);} avistreamgetframeclose (pframe); // close the stream after finishing the task if (pstream! = NULL) avistreamrelease (pstream); avifileexit ();} The following function demonstrates how to extract each image from an AVI file and save it as a BMP file. The first parameter of the function is the AVI file name, and the second parameter is the folder where the BMP file is stored. // Generate avivoid cbmp2avidlg: BMP toavi (cstring szaviname, cstring strbmp DIR) {cfilefind finder; strbmp dir + = _ T ("//*. * "); avifileinit (); avistreaminfo strhdr; pavifile pfile; pavistream pS; int nframes = 0; hresult hr; bool bfind = finder. findfile (strbmp DIR); While (bfind) {bfind = finder. findnextfile (); If (! Finder. isdots ()&&! Finder. isdirectory () {cstring STR = finder. getfilepath (); file * fp = fopen (STR, "rb"); bitmapfileheader BMP filehdr; bitmapinfoheader BMP infohdr; fseek (FP, 0, seek_set); fread (& BMP filehdr, sizeof (bitmapfileheader), 1, FP); fread (& BMP infohdr, sizeof (bitmapinfoheader), 1, FP); byte * tmp_buf = NULL; If (nframes = 0) {avifileopen (& pfile, szaviname, of_write | of_create, null); _ fmemset (& strhdr, 0, sizeof (strh Dr); strhdr. fcctype = streamtypevideo; // stream type strhdr. fcchandler = 0; strhdr. dwscale = 1; strhdr. dwrate = 15; // 15 FPS strhdr. dwsuggestedbuffersize = BMP infohdr. bisizeimage; setrect (& strhdr. rcframe, 0, 0, BMP infohdr. biwidth, BMP infohdr. biheight); // and create the stream; HR = avifilecreatestream (pfile, & PS, & strhdr); // hR = avistreamsetformat (Ps, nframes, & BMP infohdr, sizeof (BMP infohdr ));} Tmp_buf = new byte [BMP infohdr. biwidth * BMP infohdr. biheight * 3]; fread (tmp_buf, 1, BMP infohdr. biwidth * BMP infohdr. biheight * 3, FP); HR = avistreamsetformat (Ps, nframes, & BMP infohdr, sizeof (BMP infohdr); HR = avistreamwrite (Ps, // stream pointer nframes, // time of this frame 1, // number to write (lpbyte) tmp_buf, BMP infohdr. bisizeimage, // size of this frame aviif_keyframe, // flags .... null, n Ull); nframes ++; fclose (FP) ;}} avistreamclose (PS); If (pfile! = NULL) avifilerelease (pfile); avifileexit ();} conclusion: the above Code has been debugged on VC 6.0 and Windows XP. You can use these two functions directly in your program. For more detailed code, see the example source code attached with this article. Here I want to point out that, during the mutual conversion between the AVI file and BMP, the video data in AVI is stored with no compressed data, if you want to decompress an AVI file, such as dvsd and MPEG4, you must first use the corresponding decoder to decode the video data, save the decoded data as a BMP file. Now, the introduction to the AVI file is over.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.