Parsing AVI files in Linux (with source code)

Source: Internet
Author: User

Some time ago, because of project requirements, I had to solve the AVI file. At that time, I first wanted to use FFMPEG for processing, but I thought it was too big to run it on the arm. I felt unnecessary. Then, I searched the search engine a little and found no useful examples. Most of them use Windows APIs for reading and writing, which is obviously unavailable in Linux. The results took 2-3 days to study and write the code for decoding and encapsulation of an AVI file. However, Avi was not used for some reason, so the code was not optimized in the future. This post is for record and persons who need it as a reference.

Header file:

/*! @ Brief AVI file analyzer @ author jwybobo2007 @ file avifileparser. h @ Note: Indicate the author when using the code. The source is http://blog.csdn.net/jwybo2007#/#include <stdio. h> # include <stdlib. h> # include <string> # include <vector> # include <map> /////////////////////// //////////////////////////////////////// ////////// # define aviif_keyframe0x00000010l // key frame flag in the index # define aviif_list0x00000001l // flags for dwflags | flag in the AVI Header # define avifileinfo_ha Sindex0x00000010 // check whether there is an index # define sequence // The maximum allowable AVI Header size # define max_allowed_avi_header_size 131072 // the file cannot be opened # define error_open_avi0/valid Avi # define error_invalid_avi1 // due to compiler C, the C ++ standard is too low and does not contain stdint. h header file, and no boost library is used now, so some types are defined to be compatible with previous Code # ifdef no_stdint Typedef char int8_t; typedef unsigned char success; typedef short int16_t; typedef unsigned short success; typedef int int32_t; typedef unsigned int success; typedef long int64_t; typedef unsigned long enough; # endif // double-character typedef uint32_t DWORD; // single-character typedef uint16_t word; // defines long typedef DWORD long; // byte typedef uint8_t byte; // defines four cc; typedef DWORD fourcc; // defines the integer corresponding to fourcc. The AVI file stores the small-end Const. DWORD fourcc_riff = 0x46464952; const DWORD fourcc_avi = 0x20495641; const DWORD fourcc_list = 0x5453494c; const DWORD fourcc_hdrl = primary; const DWORD fourcc_avih = 0x68697661; const DWORD fourcc_strl = limit; const DWORD fourcc_strh = 0x68727473; const DWORD fourcc_strf = 0x66727473; const DWORD fourcc_strd = 0x64727473; const DWORD fourcc_vids = 0x73646976; const DWORD fourcc_auds = 0x73647561; Const DWORD fourcc_info = regular; const DWORD fourcc_isft = 0x54465349; const DWORD fourcc_idx1 = 0x31786469; const DWORD fourcc_movi = 0x69766f6d; const DWORD fourcc_junk = regular; const DWORD fourcc_vgp = 0x70727076; const DWORD fourcc_pad = 0x20444150; const DWORD fourcc_div3 = 861292868; const DWORD fourcc_divx = 1482049860; const DWORD Limit = 1145656920; const DWORD fourcc_dx50 = 808802 372; const DWORD fourcc_fmt = 0x20746d66; // for Wave filesconst DWORD fourcc_data = 0x61746164; // for Wave filesconst DWORD fourcc_wave = 0x45564157; // for wave files // color palette typedef struct {byte rgbblue; // blue byte rgbgreen; // green byte rgbred; // red byte rgbreserved; // reserved} rgbquad; // Avi primary header typedef struct {fourcc FCC; // It Must Be avihdword CB; // size of the data structure, excluding the first 8 bytes (fcc and CB) DWORD dwmicrosecperframe; // video frame interval (in milliseconds) DWORD dwmaxbytespersec; // The maximum data rate of this AVI file DWORD dwpaddinggranularity; // the granularity of Data filling DWORD dwflags; // The Global tag of the AVI file, such as whether or not it contains index blocks and other DWORD dwtotalframes; // total number of frames DWORD dwinitialframes; // specify the initial number of frames for the interactive format (the non-interactive format should be set to 0) DWORD dwstreams; // The number of streams contained in this file DWORD dwsuggestedbuffersize; // It is recommended to read the cache size of this file (which should accommodate the largest block) DWORD dwwidth; // The width of the video image (in pixels) DWORD dwheight; // video image height (in pixels) DWORD dwreserved [4]; // reserved} avimainheader; // defines the rectangular area typedef struct {s Hort int left; // total margin short int top; // top margin short int right; // right margin from short int bottom; // bottom margin} rect; // AVI stream header typedef struct {fourcc FCC; // It Must Be strhdword CB; // size of the data structure, excluding the first 8 bytes (fcc and CB) fourcc fcctype; // stream type: auds (audio stream) VIDS (Video Stream) mids (MIDI stream) txts (Text Stream) fourcc fcchandler; // specifies the stream processor, for audio and video, it is the decoder DWORD dwflags; // MARK: whether to allow this stream output? Does the palette change? Word wpriority; // stream priority (when multiple streams of the same type have the highest priority, the default stream is used) Word wlanguage; // language DWORD dwinitialframes; // specify the initial frame number DWORD dwscale for the interaction format; // The video size or audio sampling size DWORD dwrate per frame; // dwscale/dwrate, sampling rate DWORD dwstart per second; // stream start time DWORD dwlength; // stream length (unit: Related to dwscale and dwrate definitions) DWORD dwsuggestedbuffersize; // The cache size DWORD dwquality recommended for reading the stream data; // The quality indicator of the stream data (0 ~ 10,000) DWORD dwsamplesize; // sample size rect rcframe; // specify the position of the stream (video stream or text stream) in the main video window, the main video window is determined by dwwidth and dwheight in the avimainheader structure} avistreamheader; // Bitmap header typedef struct {DWORD bisize; long biwidth; long biheight; Word biplanes; Word bibitcount; DWORD bicompression; DWORD bisizeimage; long bixpelspermeter; long biypelspermeter; DWORD biclrused; DWORD biclrimportant;} bitmapinfoheader; // bitmap information typedef struct {bitmapinfoh Eader bmiheader; // Bitmap header rgbquad bmicolors [1]; // palette} bitmapinfo; // audio waveform information typedef struct {word wformattag; Word nchannels; // number of audio channels DWORD nsamplespersec; // sampling rate DWORD navgbytespersec; // data volume per second word nblockalign; // data block alignment mark word wbitspersample; // word cbsize of data volume sampled each time; // size} waveformatex; // index node information typedef struct {DWORD dwchunkid; // the four-digit code (00dc 01wb) of the data block DWORD dwflags; // indicates whether the data block is a key frame, whether it is a 'rec 'list, and other information DWORD dwoffset; // This data block Offset DWORD dwsize in the file; // size of the data block} aviindexentry; // index information typedef struct {fourcc FCC; // It Must Be 'idx1' dword cb; // The size of the data structure, excluding the original 8 bytes (fcc and CB) uint32_t position; // The data start position offset STD: Map <uint32_t, STD:: vector <aviindexentry> videoindexmap; // The video index table, such as 00dc, is converted to an integer to indicate STD: Map <uint32_t, STD: vector <aviindexentry> audioindexmap; // convert the audio index table and 00wb to an integer representation} aviindex ;/*! @ Brief AVI file analyzer */class avifileparser {public: avifileparser (); avifileparser (const char * file );~ Avifileparser (void); Public :/*! @ Brief open the AVI file */void openavi (const char * file );/*! @ Brief is a valid Avi */bool isvalid () {return _ isvalid ;}/*! @ Brief whether audio exists */bool hasaudio () {return _ hasaudio ;}/*! @ Brief video */bool hasvideo () {return _ hasvideo ;}/*! @ Brief returns the AVI Header */const avimainheader * avimainheader () {return & _ avimainheader ;}/*! @ Brief returns the AVI Video Stream header */const avistreamheader * avivideostreamheader () {return & _ avivideostreamheader ;}/*! @ Brief returns the AVI audio stream header */const avistreamheader * aviaudiostreamheader () {return & _ aviaudiostreamheader ;}/*! @ Brief returns bitmap information */const bitmapinfo * bitmapinfo () {return & _ bitmapinfo ;}/*! @ Brief returned Audio Information */const waveformatex * waveformatex () {return & _ waveinfo ;}/*! @ Brief maximum video frame size */uint32_t maxframesize () {return _ maxframesize ;}/*! @ Brief: get the video frame @ Param Buf video frame storage buffer @ Param index frame index. The default value is-1, indicates to continue reading from the current index @ return video frame size */int32_t getvideoframe (char * Buf, int32_t Index =-1 );/*! @ Brief offset the video frame starting from the specified position @ Param index specifies the Index */bool seekvideoframe (int32_t index );/*! @ Brief get the audio frame */PRIVATE: // parse avivoid _ parsefile (); // read data of the specified length from the file, error automatically throw exception bool readfile (char * Buf, uint32_t Len); // read 12 bytes from the file and analyze bool readfiletagsize (DWORD & fourcc, uint32_t & size, DWORD & fourcc2); // read 4 bytes of uint32_t readfiledw () from the file; // read 2 bytes of uint16_t readfilew () from the file (); //////////////////////////////////////// /// read 4-byte bool readfiledw (uint32_t & DW) from the file ); /// read two bytes from the file bool readfilew (uint16_t & W); Private: // file handle file * _ avifd; // whether the audio bool _ hasaudio exists; // whether the video bool _ hasvideo is available; // whether the bool _ isvalid is valid; // The file length uint32_t _ FLEN; // avimainheader _ avimainheader Of The AVI master header; // AVI Video Stream header avistreamheader _ avivideostreamheader; // Avi audio stream header avistreamheader _ aviaudiostreamheader; // bitmap information bitmapinfo _ bitmapinfo; // Audio Information waveformatex _ waveinfo; // encode the program STD: String _ soft; // index information aviindex _ aviindex; // the starting position of movi offset uint32_t _ movioff; // The maximum frame size uint32_t _ maxframesize; // The index of the current video position (position in the array, subscript) int32_t _ currvideoindex ;};

Source file:

# Include <assert. h> # include <errno. h> # include "avifileparser. H "# include" byte_write.h "avifileparser: avifileparser (void): _ avifd (null), _ hasaudio (false), _ hasvideo (false), _ isvalid (false ), _ FLEN (0), _ movioff (0), _ maxframesize (0), _ currvideoindex (0) {} avifileparser: avifileparser (const char * file ): _ hasaudio (false), _ hasvideo (false), _ isvalid (false), _ FLEN (0), _ movioff (0), _ maxframesize (0 ), _ currvideoindex (0) {ope Navi (File);} avifileparser ::~ Avifileparser (void) {If (_ avifd! = NULL) fclose (_ avifd);} void avifileparser: openavi (const char * file) {_ avifd = fopen (file, "rb "); if (_ avifd = NULL) {# ifndef nprintprintf ("Open Avi error: % d [% s] \ n", errno, strerror (errno )); # endif // throw error code throw error_open_avi;} // start parsing _ parsefile (); _ isvalid = true;} void avifileparser: _ parsefile () {// The first read 12 bytes DWORD fourcc = 0; DWORD fourcc2 = 0; bool flag = true; bool hasindex = false; readfiletagsize (F Ourcc, _ FLEN, fourcc2); If (fourcc! = Fourcc_riff | fourcc2! = Fourcc_avi) Throw error_invalid_avi; while (FLAG) {uint32_t size = 0; bool iseof = readfiledw (fourcc); If (iseof) return; iseof = readfiledw (size ); if (iseof) return; If (fourcc = fourcc_list) {fourcc2 = readfiledw (); Switch (fourcc2) {Case fourcc_hdrl: {If (size> rows) Throw error_invalid_avi; // skip hdrluint32_t off = 4; while (Off <size) {fourcc = readfiledw (); Switch (fourcc) {Case fourcc _ Avih: {_ avimainheader. FCC = fourcc_avih; _ avimainheader. CB = readfiledw (); _ avimainheader. dwmicrosecperframe = readfiledw (); _ avimainheader. dwmaxbytespersec = readfiledw (); _ avimainheader. dwpaddinggranularity = readfiledw (); _ avimainheader. dwflags = readfiledw (); _ avimainheader. dwtotalframes = readfiledw (); _ avimainheader. dwinitialframes = readfiledw (); _ avimainheader. dwstreams = readfiledw (); _ avimainhead Er. dwsuggestedbuffersize = readfiledw (); _ avimainheader. dwwidth = readfiledw (); _ avimainheader. dwheight = readfiledw (); If (avifileinfo_hasindex & _ avimainheader. dwflags) = avifileinfo_hasindex) hasindex = true; // skip the reserved field fseek (_ avifd, 16, seek_cur); // skip avih and the length of each four bytes off + = _ avimainheader. cb + 8;} break; Case fourcc_list: {int avlistlen = readfiledw (); If (readfiledw ()! = Fourcc_strl) Throw outer; // skip strlint tmpoff = 4; avistreamheader = {0}; while (tmpoff <avlistlen) {fourcc = readfiledw (); tmpoff + = 4; if (fourcc = fourcc_strh) {avistreamheader. FCC = fourcc_strh; avistreamheader. CB = readfiledw (); avistreamheader. fcctype = readfiledw (); avistreamheader. fcchandler = readfiledw (); avistreamheader. dwflags = readfiledw (); avistreamheader. wpriority = Readfilew (); avistreamheader. wlanguage = readfilew (); avistreamheader. dwinitialframes = readfiledw (); avistreamheader. dwscale = readfiledw (); avistreamheader. dwrate = readfiledw (); avistreamheader. dwstart = readfiledw (); avistreamheader. dwlength = readfiledw (); avistreamheader. dwsuggestedbuffersize = readfiledw (); avistreamheader. dwquality = readfiledw (); avistreamheader. dwsamplesize = readfiledw (); AVIS Treamheader. rcframe. left = readfilew (); avistreamheader. rcframe. top = readfilew (); avistreamheader. rcframe. right = readfilew (); avistreamheader. rcframe. bottom = readfilew (); // skip the length tmpoff + = 4; tmpoff + = avistreamheader. CB;} else if (fourcc = fourcc_strf) {int tmplen = readfiledw (); If (avistreamheader. fcctype = fourcc_vids) {_ hasvideo = true; _ avivideostreamheader = avistreamheader; _ bitmapinfo. bmiheader. Bisize = readfiledw (); _ bitmapinfo. bmiheader. biwidth = readfiledw (); _ bitmapinfo. bmiheader. biheight = readfiledw (); _ bitmapinfo. bmiheader. biplanes = readfilew (); _ bitmapinfo. bmiheader. bibitcount = readfilew (); _ bitmapinfo. bmiheader. bicompression = readfiledw (); _ bitmapinfo. bmiheader. bisizeimage = readfiledw (); _ bitmapinfo. bmiheader. bixpelspermeter = readfiledw (); _ bitmapinfo. bmiheader. biypelspermeter = Re Adfiledw (); _ bitmapinfo. bmiheader. biclrused = readfiledw (); _ bitmapinfo. bmiheader. biclrimportant = readfiledw (); If (tmplen> _ bitmapinfo. bmiheader. bisize) fseek (_ avifd, tmplen-_ bitmapinfo. bmiheader. bisize, seek_cur);} else if (avistreamheader. fcctype = fourcc_auds) {_ hasaudio = true; _ aviaudiostreamheader = avistreamheader; _ waveinfo. wformattag = readfilew (); _ waveinfo. nchannels = readfilew (); _ waveinfo. Nsamplespersec = readfiledw (); _ waveinfo. navgbytespersec = readfiledw (); _ waveinfo. nblockalign = readfilew (); _ waveinfo. wbitspersample = readfilew (); _ waveinfo. cbsize = readfilew (); fseek (_ avifd, _ waveinfo. cbsize, seek_cur);/* # include <mmreg. h> wave_format_pcmwave_format_alaw * // skip length tmpoff + = 4; tmpoff + = tmplen;} else if (fourcc = fourcc_junk) {int tmplen = readfiledw (); fseek (_ avifd, tmplen, seek_cur); // Skip length tmpoff + = 4; tmpoff + = tmplen;} else if (fourcc = fourcc_vrp) {int tmplen = readfiledw (); fseek (_ avifd, tmplen, seek_cur); // skip the length tmpoff + = 4; tmpoff + = tmplen;} off + = avlistlen + 8;} break; Case fourcc_junk: {// skip junkoff + = 4; int tmplen = readfiledw (); fseek (_ avifd, tmplen, seek_cur); // skip length off + = 4; off + = tmplen;} break ;}} break; Case fourcc_info: {fourcc = readfiledw (); If (fourcc = fourcc_isft) {Int tmplen = readfiledw (); _ soft. resize (tmplen); readfile (& _ soft [0], tmplen) ;}} break; Case fourcc_movi: {_ movioff = ftell (_ avifd); If (hasindex) {// skip movi and directly go to the idx fseek (_ avifd, size-4, seek_cur) ;}} break ;}} else if (fourcc = fourcc_idx1) {_ aviindex. FCC = fourcc_idx1; _ aviindex. CB = size; int tmpoff = 0; while (tmpoff <_ aviindex. CB) {char tmpbuf [4] = {0}; readfile (tmpbuf, 4); int Index = read_le_dw (tmpbuf); Viindexentry tmpentry; tmpentry. dwflags = readfiledw (); tmpentry. dwoffset = readfiledw (); tmpentry. dwsize = readfiledw (); If (tmpentry. dwsize> _ maxframesize) _ maxframesize = tmpentry. dwsize; // video data if (tmpbuf [2] = 'D') {_ aviindex. videoindexmap [Index]. push_back (tmpentry);} else if (tmpbuf [2] = 'W') {_ aviindex. audioindexmap [Index]. push_back (tmpentry);} // the length of an index message tmpoff + = 16;} else if (fourcc = fourcc_j Unk) {// skip fseek (_ avifd, size, seek_cur) ;}} bool avifileparser: readfile (char * Buf, uint32_t Len) {uint32_t ret = fread (BUF, 1, Len, _ avifd); If (Ret! = Len) {If (feof (_ avifd )! = 0) return true; # ifndef nprintprintf ("fread Avi error: % d [% s] \ n", errno, strerror (errno); # endifthrow error_invalid_avi ;} return false;} bool avifileparser: readfiletagsize (DWORD & fourcc, uint32_t & size, DWORD & fourcc2) {char tmpbuf [12] = {0}; bool ret = readfile (tmpbuf, 12); fourcc = read_le_dw (tmpbuf); size = read_le_dw (tmpbuf + 4); fourcc2 = read_le_dw (tmpbuf + 8); return ret;} uint32_t avifileparser:: Readfiledw () {char tmpbuf [4] = {0}; readfile (tmpbuf, 4); Return read_le_dw (tmpbuf);} bool avifileparser: readfiledw (uint32_t & DW) {char tmpbuf [4] = {0}; bool ret = readfile (tmpbuf, 4); DW = read_le_dw (tmpbuf); return ret;} uint16_t avifileparser: readfilew () {char tmpbuf [2] = {0}; readfile (tmpbuf, 2); Return read_le_w (tmpbuf);} bool avifileparser: readfilew (uint16_t & W) {char tmpbuf [2] = {0}; bool ret = rea Dfile (tmpbuf, 2); W = read_le_w (tmpbuf); return ret;} int32_t avifileparser: getvideoframe (char * Buf, int32_t index/* =-1 */) {If (! _ Hasvideo) Return-1; // only obtain the first STD: vector <aviindexentry> & videovec = _ aviindex. videoindexmap. begin ()-> second; int32_t tmpindex = 0; If (Index =-1) {If (_ currvideoindex <videovec. size () tmpindex = _ currvideoindex ++; elsereturn 0;} elsetmpindex = index; aviindexentry & videoentry = videovec [tmpindex]; // Add the offset from the end of movi to the data of the DC dB, and then skip a 4-byte length value fseek (_ avifd, _ movioff + videoentry. dwoffset + 4, seek_set); int32_t ret = fread (BUF, 1, videoentry. dwsize, _ avifd); Assert (ret = videoentry. dwsize); return ret;} bool avifileparser: seekvideoframe (int32_t index) {STD: vector <aviindexentry> & videovec = _ aviindex. videoindexmap. begin ()-> second; If (index <videovec. size () {_ currvideoindex = index; return true;} return false ;}

Reprinted please indicate the source: http://blog.csdn.net/jwybobo2007/article/details/7662653

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.