linux下avi文件解析

本文转载自: http://blog.csdn.net/jwybobo2007/article/details/7662653


linux下avi文件解析(附源码)

前段时间由于项目需要,要解avi文件,当时我第一时间想到用ffmpeg来处理,但想想觉得太大了,又是放到arm上跑的,感觉没必要。然后,搜索引擎上稍微搜了一下,没找到有用的示例,大部分都是利用windows的api进行读写,很明显linux下用不了。结果花了2-3天时间研究并写了一个avi文件的解封装代码,但是后来因某些原因没有去使用AVI了,所以代码也没进行后续的完善优化。这里贴出来供记录以及需要的人作参考。

头文件:

  1. /*! 
  2. @brief avi文件分析提取器 
  3. @author jwybobo2007 
  4. @file avifileparser.h 
  5. @note 代码在使用时,请标明作者,保留出处:http://blog.csdn.net/jwybobo2007 
  6. */  
  7. #include <stdio.h>  
  8. #include <stdlib.h>  
  9.   
  10. #include <string>  
  11. #include <vector>  
  12. #include <map>  
  13.   
  14. //  
  15. #define AVIIF_KEYFRAME  0x00000010L     // 索引里面的关键帧标志  
  16. #define AVIIF_LIST  0x00000001L  
  17.   
  18. // Flags for dwFlags|AVI头中的标志位  
  19. #define AVIFILEINFO_HASINDEX        0x00000010  // 是否有索引  
  20. #define AVIFILEINFO_MUSTUSEINDEX    0x00000020  
  21. #define AVIFILEINFO_ISINTERLEAVED   0x00000100  
  22. #define AVIFILEINFO_WASCAPTUREFILE  0x00010000  
  23. #define AVIFILEINFO_COPYRIGHTED     0x00020000  
  24.   
  25. // 最大允许的AVI头大小  
  26. #define MAX_ALLOWED_AVI_HEADER_SIZE 131072  
  27.   
  28. // 打不开文件  
  29. #define ERROR_OPEN_AVI              0  
  30. // 不是有效AVI  
  31. #define ERROR_INVALID_AVI           1  
  32.   
  33. // 由于编译器c,c++标准过低,没有包含stdint.h头文件,并且现在也没有使用boost库,因此定义一些类型,来兼容以前的代码  
  34. #ifdef NO_STDINT  
  35. typedef char int8_t;  
  36. typedef unsigned char uint8_t;  
  37. typedef short int16_t;  
  38. typedef unsigned short uint16_t;  
  39. typedef int int32_t;  
  40. typedef unsigned int uint32_t;  
  41. typedef long long int64_t;  
  42. typedef unsigned long long uint64_t;  
  43. #endif  
  44.   
  45. // 双字  
  46. typedef uint32_t DWORD;  
  47. // 单字  
  48. typedef uint16_t WORD;  
  49. // 定义长整型  
  50. typedef DWORD LONG;  
  51. // 字节  
  52. typedef uint8_t BYTE;  
  53. // 定义four cc;  
  54. typedef DWORD FourCC;  
  55.   
  56. // 定义fourcc对应的整数值,avi文件中保存的是小端  
  57. const DWORD FOURCC_RIFF = 0x46464952;  
  58. const DWORD FOURCC_AVI = 0x20495641;  
  59. const DWORD FOURCC_LIST = 0x5453494C;  
  60. const DWORD FOURCC_hdrl = 0x6C726468;  
  61. const DWORD FOURCC_avih = 0x68697661;  
  62. const DWORD FOURCC_strl = 0x6C727473;  
  63. const DWORD FOURCC_strh = 0x68727473;  
  64. const DWORD FOURCC_strf = 0x66727473;  
  65. const DWORD FOURCC_STRD = 0x64727473;  
  66. const DWORD FOURCC_vids = 0x73646976;  
  67. const DWORD FOURCC_auds = 0x73647561;  
  68. const DWORD FOURCC_INFO = 0x4F464E49;  
  69. const DWORD FOURCC_ISFT = 0x54465349;  
  70. const DWORD FOURCC_idx1 = 0x31786469;  
  71. const DWORD FOURCC_movi = 0x69766F6D;  
  72. const DWORD FOURCC_JUNK = 0x4B4E554A;  
  73. const DWORD FOURCC_vprp = 0x70727076;  
  74. const DWORD FOURCC_PAD = 0x20444150;  
  75. const DWORD FOURCC_DIV3 = 861292868;  
  76. const DWORD FOURCC_DIVX = 1482049860;  
  77. const DWORD FOURCC_XVID = 1145656920;  
  78. const DWORD FOURCC_DX50 = 808802372;  
  79.   
  80. const DWORD FOURCC_fmt = 0x20746D66;    // for WAVE files  
  81. const DWORD FOURCC_data = 0x61746164;   // for WAVE files  
  82. const DWORD FOURCC_WAVE = 0x45564157;   // for WAVE files  
  83.   
  84. // 调色板  
  85. typedef struct  
  86. {  
  87.     BYTE rgbBlue;                       // 蓝  
  88.     BYTE rgbGreen;                      // 绿  
  89.     BYTE rgbRed;                        // 红  
  90.     BYTE rgbReserved;                   // 保留  
  91. } RGBQUAD;  
  92.   
  93. // AVI主头部  
  94. typedef struct  
  95. {  
  96.     FourCC fcc;                         // 必须为 avih  
  97.     DWORD cb;                           // 本数据结构的大小,不包括最初的8个字节(fcc和cb两个域)  
  98.     DWORD dwMicroSecPerFrame;           // 视频帧间隔时间(以毫秒为单位)  
  99.     DWORD dwMaxBytesPerSec;             // 这个AVI文件的最大数据率  
  100.     DWORD dwPaddingGranularity;         // 数据填充的粒度  
  101.     DWORD dwFlags;                      // AVI文件的全局标记,比如是否含有索引块等  
  102.     DWORD dwTotalFrames;                // 总帧数  
  103.     DWORD dwInitialFrames;              // 为交互格式指定初始帧数(非交互格式应该指定为0)  
  104.     DWORD dwStreams;                    // 本文件包含的流的个数  
  105.     DWORD dwSuggestedBufferSize;        // 建议读取本文件的缓存大小(应能容纳最大的块)  
  106.     DWORD dwWidth;                      // 视频图像的宽(以像素为单位)  
  107.     DWORD dwHeight;                     // 视频图像的高(以像素为单位)  
  108.     DWORD dwReserved[4];                // 保留  
  109. } AVIMainHeader;  
  110.   
  111. // 定义矩形区域  
  112. typedef struct  
  113. {  
  114.     short int left;                     // 总边距  
  115.     short int top;                      // 顶边距  
  116.     short int right;                    // 右边距  
  117.     short int bottom;                   // 底边距  
  118. }RECT;  
  119.   
  120. // AVI流头部  
  121. typedef struct  
  122. {  
  123.     FourCC fcc;                         // 必须为 strh  
  124.     DWORD cb;                           // 本数据结构的大小,不包括最初的8个字节(fcc和cb两个域)  
  125.     FourCC fccType;                     // 流的类型: auds(音频流) vids(视频流) mids(MIDI流) txts(文字流)  
  126.     FourCC fccHandler;                  // 指定流的处理者,对于音视频来说就是解码器  
  127.     DWORD dwFlags;                      // 标记:是否允许这个流输出?调色板是否变化?  
  128.     WORD wPriority;                     // 流的优先级(当有多个相同类型的流时优先级最高的为默认流)  
  129.     WORD wLanguage;                     // 语言  
  130.     DWORD dwInitialFrames;              // 为交互格式指定初始帧数  
  131.     DWORD dwScale;                      // 每帧视频大小或者音频采样大小  
  132.     DWORD dwRate;                       // dwScale/dwRate,每秒采样率  
  133.     DWORD dwStart;                      // 流的开始时间  
  134.     DWORD dwLength;                     // 流的长度(单位与dwScale和dwRate的定义有关)  
  135.     DWORD dwSuggestedBufferSize;        // 读取这个流数据建议使用的缓存大小  
  136.     DWORD dwQuality;                    // 流数据的质量指标(0 ~ 10,000)  
  137.     DWORD dwSampleSize;                 // Sample的大小  
  138.     RECT rcFrame;                       // 指定这个流(视频流或文字流)在视频主窗口中的显示位置,视频主窗口由AVIMAINHEADER结构中的dwWidth和dwHeight决定  
  139. } AVIStreamHeader;  
  140.   
  141. // 位图头  
  142. typedef struct  
  143. {  
  144.     DWORD  biSize;  
  145.     LONG   biWidth;  
  146.     LONG   biHeight;  
  147.     WORD   biPlanes;  
  148.     WORD   biBitCount;  
  149.     DWORD  biCompression;  
  150.     DWORD  biSizeImage;  
  151.     LONG   biXPelsPerMeter;  
  152.     LONG   biYPelsPerMeter;  
  153.     DWORD  biClrUsed;  
  154.     DWORD  biClrImportant;  
  155. } BitmapInfoHeader;  
  156.   
  157. // 位图信息  
  158. typedef struct  
  159. {  
  160.     BitmapInfoHeader bmiHeader;         // 位图头  
  161.     RGBQUAD bmiColors[1];               // 调色板  
  162. } BitmapInfo;  
  163.   
  164. // 音频波形信息  
  165. typedef struct  
  166. {  
  167.     WORD wFormatTag;  
  168.     WORD nChannels;                     // 声道数  
  169.     DWORD nSamplesPerSec;               // 采样率  
  170.     DWORD nAvgBytesPerSec;              // 每秒的数据量  
  171.     WORD nBlockAlign;                   // 数据块对齐标志  
  172.     WORD wBitsPerSample;                // 每次采样的数据量  
  173.     WORD cbSize;                        // 大小  
  174. } WaveFormatEx;  
  175.   
  176. // 索引节点信息  
  177. typedef struct  
  178. {  
  179.     DWORD dwChunkId;                    // 本数据块的四字符码(00dc 01wb)  
  180.     DWORD dwFlags;                      // 说明本数据块是不是关键帧、是不是‘rec ’列表等信息  
  181.     DWORD dwOffset;                     // 本数据块在文件中的偏移量  
  182.     DWORD dwSize;                       // 本数据块的大小  
  183. } AVIIndexEntry;  
  184.   
  185. // 索引信息  
  186. typedef struct  
  187. {  
  188.     FourCC fcc;                                                         // 必须为‘idx1’  
  189.     DWORD cb;                                                           // 本数据结构的大小,不包括最初的8个字节(fcc和cb两个域)  
  190.     uint32_t position;                                                  // 数据起始位置偏移  
  191.     std::map<uint32_t, std::vector<AVIIndexEntry> > videoIndexMap;      // 视频索引表,00dc等转换成整形表示  
  192.     std::map<uint32_t, std::vector<AVIIndexEntry> > audioIndexMap;      // 音频索引表,00wb等转换成整形表示  
  193. } AVIIndex;  
  194.   
  195. /*! 
  196. @brief avi文件分析提取器 
  197. */  
  198. class AVIFileParser  
  199. {  
  200. public:  
  201.     AVIFileParser();  
  202.     AVIFileParser(const char* file);  
  203.     ~AVIFileParser(void);  
  204. public:  
  205.     /*! 
  206.     @brief 打开AVI文件 
  207.     */  
  208.     void openAVI(const char* file);  
  209.     /*! 
  210.     @brief 是否是有效avi 
  211.     */  
  212.     bool isValid(){return _isValid;}  
  213.     /*! 
  214.     @brief 是否有音频 
  215.     */  
  216.     bool hasAudio(){return _hasAudio;}  
  217.     /*! 
  218.     @brief 是否有视频 
  219.     */  
  220.     bool hasVideo(){return _hasVideo;}  
  221.     /*! 
  222.     @brief 返回avi头 
  223.     */  
  224.     const AVIMainHeader* aviMainHeader(){return &_aviMainHeader;}  
  225.     /*! 
  226.     @brief 返回avi视频流头 
  227.     */  
  228.     const AVIStreamHeader* aviVideoStreamHeader(){return &_aviVideoStreamHeader;}  
  229.     /*! 
  230.     @brief 返回avi音频流头 
  231.     */  
  232.     const AVIStreamHeader* aviAudioStreamHeader(){return &_aviAudioStreamHeader;}  
  233.     /*! 
  234.     @brief 返回位图信息 
  235.     */  
  236.     const BitmapInfo* bitmapInfo(){return &_bitmapInfo;}  
  237.     /*! 
  238.     @brief 返回音频信息 
  239.     */  
  240.     const WaveFormatEx* waveFormatEx(){return &_waveInfo;}  
  241.     /*! 
  242.     @brief 最大视频帧大小 
  243.     */  
  244.     uint32_t maxFrameSize(){return _maxFrameSize;}  
  245.     /*! 
  246.     @brief 获取视频帧 
  247.     @param buf 视频帧存储缓冲 
  248.     @param index 帧索引,默认-1,表示从当前的索引继续往下读取 
  249.     @return 视频帧大小 
  250.     */  
  251.     int32_t getVideoFrame(char* buf, int32_t index = -1);  
  252.     /*! 
  253.     @brief 偏移视频帧从指定位置开始 
  254.     @param index 指定索引 
  255.     */  
  256.     bool seekVideoFrame(int32_t index);  
  257.     /*! 
  258.     @brief 获取音频帧 
  259.     */  
  260.   
  261. private:  
  262.     /// 解析AVI  
  263.     void _parseFile();  
  264.     /// 从文件读指定长度的数据,出错自动抛出异常  
  265.     bool readFile(char* buf, uint32_t len);  
  266.     /// 从文件读12个字节并分析  
  267.     bool readFileTagSize(DWORD& fourcc, uint32_t& size, DWORD& fourcc2);  
  268.     /// 从文件读4字节  
  269.     uint32_t readFileDW();  
  270.     /// 从文件读2字节  
  271.     uint16_t readFileW();  
  272.     //  
  273.     // 重载  
  274.     /// 从文件读4字节  
  275.     bool readFileDW(uint32_t& dw);  
  276.     /// 从文件读2字节  
  277.     bool readFileW(uint16_t& w);  
  278. private:  
  279.     // 文件句柄  
  280.     FILE* _aviFd;  
  281.     // 是否有音频  
  282.     bool _hasAudio;  
  283.     // 是否有视频  
  284.     bool _hasVideo;  
  285.     // 是否有效  
  286.     bool _isValid;  
  287.     // 文件长度  
  288.     uint32_t _fLen;  
  289.     // avi主头  
  290.     AVIMainHeader _aviMainHeader;  
  291.     // avi视频流头部  
  292.     AVIStreamHeader _aviVideoStreamHeader;  
  293.     // avi音频流头部  
  294.     AVIStreamHeader _aviAudioStreamHeader;  
  295.     // 位图信息  
  296.     BitmapInfo _bitmapInfo;  
  297.     // 音频信息  
  298.     WaveFormatEx _waveInfo;  
  299.     // 编码程序  
  300.     std::string _soft;  
  301.     // 索引信息  
  302.     AVIIndex _aviIndex;  
  303.     // movi的开始位置偏移  
  304.     uint32_t _moviOff;  
  305.     // 最大帧大小  
  306.     uint32_t _maxFrameSize;  
  307.     // 当前视频位置索引(数组中的位置,下标)  
  308.     int32_t _currVideoIndex;  
  309. };  

源文件:
  1. #include <assert.h>  
  2. #include <errno.h>  
  3.   
  4. #include "avifileparser.h"  
  5. #include "byte_write.h"  
  6.   
  7. AVIFileParser::AVIFileParser(void)  
  8.     :_aviFd(NULL),  
  9.     _hasAudio(false),  
  10.     _hasVideo(false),  
  11.     _isValid(false),  
  12.     _fLen(0),  
  13.     _moviOff(0),  
  14.     _maxFrameSize(0),  
  15.     _currVideoIndex(0)  
  16. {  
  17. }  
  18.   
  19. AVIFileParser::AVIFileParser( const char* file )  
  20.     :_hasAudio(false),  
  21.     _hasVideo(false),  
  22.     _isValid(false),  
  23.     _fLen(0),  
  24.     _moviOff(0),  
  25.     _maxFrameSize(0),  
  26.     _currVideoIndex(0)  
  27. {  
  28.     openAVI(file);  
  29. }  
  30.   
  31.   
  32. AVIFileParser::~AVIFileParser(void)  
  33. {  
  34.     if (_aviFd != NULL)  
  35.         fclose(_aviFd);  
  36. }  
  37.   
  38. void AVIFileParser::openAVI( const char* file )  
  39. {  
  40.     _aviFd = fopen(file, "rb");  
  41.     if (_aviFd == NULL)  
  42.     {  
  43. #ifndef NPRINT  
  44.         printf("open avi error: %d [%s]\n", errno, strerror(errno));  
  45. #endif  
  46.         // 抛出错误号  
  47.         throw ERROR_OPEN_AVI;  
  48.     }  
  49.   
  50.     // 开始解析  
  51.     _parseFile();  
  52.   
  53.     _isValid = true;  
  54. }  
  55.   
  56. void AVIFileParser::_parseFile()  
  57. {  
  58.     // 第一次读12个字节  
  59.     DWORD fourcc = 0;  
  60.     DWORD fourcc2 = 0;  
  61.     bool flag = true;  
  62.     bool hasIndex = false;  
  63.   
  64.     readFileTagSize(fourcc, _fLen, fourcc2);  
  65.     if (fourcc != FOURCC_RIFF || fourcc2 != FOURCC_AVI)  
  66.         throw ERROR_INVALID_AVI;  
  67.   
  68.     while (flag)  
  69.     {  
  70.         uint32_t size = 0;  
  71.         bool isEof = readFileDW(fourcc);  
  72.         if (isEof)  
  73.             return;  
  74.         isEof = readFileDW(size);  
  75.         if (isEof)  
  76.             return;  
  77.   
  78.         if (fourcc == FOURCC_LIST)  
  79.         {  
  80.             fourcc2 = readFileDW();  
  81.             switch (fourcc2)  
  82.             {  
  83.             case FOURCC_hdrl:  
  84.                 {  
  85.                     if (size > MAX_ALLOWED_AVI_HEADER_SIZE)  
  86.                         throw ERROR_INVALID_AVI;  
  87.   
  88.                     // 跳过hdrl  
  89.                     uint32_t off = 4;  
  90.                     while (off < size)  
  91.                     {  
  92.                         fourcc = readFileDW();  
  93.                         switch (fourcc)  
  94.                         {  
  95.                         case FOURCC_avih:  
  96.                             {  
  97.                                 _aviMainHeader.fcc = FOURCC_avih;  
  98.                                 _aviMainHeader.cb = readFileDW();  
  99.                                 _aviMainHeader.dwMicroSecPerFrame = readFileDW();  
  100.                                 _aviMainHeader.dwMaxBytesPerSec = readFileDW();  
  101.                                 _aviMainHeader.dwPaddingGranularity = readFileDW();  
  102.                                 _aviMainHeader.dwFlags = readFileDW();  
  103.                                 _aviMainHeader.dwTotalFrames = readFileDW();  
  104.                                 _aviMainHeader.dwInitialFrames = readFileDW();  
  105.                                 _aviMainHeader.dwStreams = readFileDW();  
  106.                                 _aviMainHeader.dwSuggestedBufferSize = readFileDW();  
  107.                                 _aviMainHeader.dwWidth = readFileDW();  
  108.                                 _aviMainHeader.dwHeight = readFileDW();  
  109.   
  110.                                 if ((AVIFILEINFO_HASINDEX & _aviMainHeader.dwFlags) == AVIFILEINFO_HASINDEX)  
  111.                                     hasIndex = true;  
  112.   
  113.                                 // 跳过保留字段  
  114.                                 fseek(_aviFd, 16, SEEK_CUR);  
  115.                                 // 跳过avih以及长度各四个字节  
  116.                                 off += _aviMainHeader.cb + 8;  
  117.                             }  
  118.                             break;  
  119.                         case FOURCC_LIST:  
  120.                             {  
  121.                                 int avListLen = readFileDW();  
  122.                                 if (readFileDW() != FOURCC_strl)  
  123.                                     throw ERROR_INVALID_AVI;  
  124.   
  125.                                 // 跳过strl  
  126.                                 int tmpOff = 4;  
  127.                                 AVIStreamHeader aviStreamHeader = {0};  
  128.                                 while (tmpOff < avListLen)  
  129.                                 {  
  130.                                     fourcc = readFileDW();  
  131.                                     tmpOff += 4;  
  132.                                     if (fourcc == FOURCC_strh)  
  133.                                     {  
  134.                                         aviStreamHeader.fcc = FOURCC_strh;  
  135.                                         aviStreamHeader.cb = readFileDW();  
  136.                                         aviStreamHeader.fccType = readFileDW();  
  137.                                         aviStreamHeader.fccHandler = readFileDW();  
  138.                                         aviStreamHeader.dwFlags = readFileDW();  
  139.                                         aviStreamHeader.wPriority = readFileW();  
  140.                                         aviStreamHeader.wLanguage = readFileW();  
  141.                                         aviStreamHeader.dwInitialFrames = readFileDW();  
  142.                                         aviStreamHeader.dwScale = readFileDW();  
  143.                                         aviStreamHeader.dwRate = readFileDW();  
  144.                                         aviStreamHeader.dwStart = readFileDW();  
  145.                                         aviStreamHeader.dwLength = readFileDW();  
  146.                                         aviStreamHeader.dwSuggestedBufferSize = readFileDW();  
  147.                                         aviStreamHeader.dwQuality = readFileDW();  
  148.                                         aviStreamHeader.dwSampleSize = readFileDW();  
  149.                                         aviStreamHeader.rcFrame.left = readFileW();  
  150.                                         aviStreamHeader.rcFrame.top = readFileW();  
  151.                                         aviStreamHeader.rcFrame.right = readFileW();  
  152.                                         aviStreamHeader.rcFrame.bottom = readFileW();  
  153.   
  154.                                         // 跳过长度  
  155.                                         tmpOff += 4;  
  156.                                         tmpOff += aviStreamHeader.cb;  
  157.                                     }  
  158.                                     else if (fourcc == FOURCC_strf)  
  159.                                     {  
  160.                                         int tmpLen = readFileDW();  
  161.                                         if (aviStreamHeader.fccType == FOURCC_vids)  
  162.                                         {  
  163.                                             _hasVideo = true;  
  164.                                             _aviVideoStreamHeader = aviStreamHeader;  
  165.                                             _bitmapInfo.bmiHeader.biSize = readFileDW();  
  166.                                             _bitmapInfo.bmiHeader.biWidth = readFileDW();  
  167.                                             _bitmapInfo.bmiHeader.biHeight = readFileDW();  
  168.                                             _bitmapInfo.bmiHeader.biPlanes = readFileW();  
  169.                                             _bitmapInfo.bmiHeader.biBitCount = readFileW();  
  170.                                             _bitmapInfo.bmiHeader.biCompression = readFileDW();  
  171.                                             _bitmapInfo.bmiHeader.biSizeImage = readFileDW();  
  172.                                             _bitmapInfo.bmiHeader.biXPelsPerMeter = readFileDW();  
  173.                                             _bitmapInfo.bmiHeader.biYPelsPerMeter = readFileDW();  
  174.                                             _bitmapInfo.bmiHeader.biClrUsed = readFileDW();  
  175.                                             _bitmapInfo.bmiHeader.biClrImportant = readFileDW();  
  176.                                             if (tmpLen > _bitmapInfo.bmiHeader.biSize)  
  177.                                                 fseek(_aviFd, tmpLen - _bitmapInfo.bmiHeader.biSize, SEEK_CUR);  
  178.                                         }  
  179.                                         else if (aviStreamHeader.fccType == FOURCC_auds)  
  180.                                         {  
  181.                                             _hasAudio = true;  
  182.                                             _aviAudioStreamHeader = aviStreamHeader;  
  183.                                             _waveInfo.wFormatTag = readFileW();  
  184.                                             _waveInfo.nChannels = readFileW();  
  185.                                             _waveInfo.nSamplesPerSec = readFileDW();  
  186.                                             _waveInfo.nAvgBytesPerSec = readFileDW();  
  187.                                             _waveInfo.nBlockAlign = readFileW();  
  188.                                             _waveInfo.wBitsPerSample = readFileW();  
  189.                                             _waveInfo.cbSize = readFileW();  
  190.                                             fseek(_aviFd, _waveInfo.cbSize, SEEK_CUR);  
  191.   
  192.                                             /* 
  193.                                             #include <mmreg.h> 
  194.                                             WAVE_FORMAT_PCM 
  195.                                             WAVE_FORMAT_ALAW 
  196.                                             */  
  197.                                         }  
  198.   
  199.                                         // 跳过长度  
  200.                                         tmpOff += 4;  
  201.                                         tmpOff += tmpLen;  
  202.                                     }  
  203.                                     else if (fourcc == FOURCC_JUNK)  
  204.                                     {  
  205.                                         int tmpLen = readFileDW();  
  206.                                         fseek(_aviFd, tmpLen, SEEK_CUR);  
  207.   
  208.                                         // 跳过长度  
  209.                                         tmpOff += 4;  
  210.                                         tmpOff += tmpLen;  
  211.                                     }  
  212.                                     else if (fourcc == FOURCC_vprp)  
  213.                                     {  
  214.                                         int tmpLen = readFileDW();  
  215.                                         fseek(_aviFd, tmpLen, SEEK_CUR);  
  216.   
  217.                                         // 跳过长度  
  218.                                         tmpOff += 4;  
  219.                                         tmpOff += tmpLen;  
  220.                                     }  
  221.                                 }  
  222.   
  223.                                 off += avListLen + 8;  
  224.                             }  
  225.                             break;  
  226.                         case FOURCC_JUNK:  
  227.                             {  
  228.                                 // 跳过JUNK  
  229.                                 off += 4;  
  230.                                 int tmpLen = readFileDW();  
  231.                                 fseek(_aviFd, tmpLen, SEEK_CUR);  
  232.   
  233.                                 // 跳过长度  
  234.                                 off += 4;  
  235.                                 off += tmpLen;  
  236.                             }  
  237.                             break;  
  238.                         }  
  239.                     }  
  240.                 }  
  241.                 break;  
  242.             case FOURCC_INFO:  
  243.                 {  
  244.                     fourcc = readFileDW();  
  245.                     if (fourcc == FOURCC_ISFT)  
  246.                     {  
  247.                         int tmpLen = readFileDW();  
  248.                         _soft.resize(tmpLen);  
  249.                         readFile(&_soft[0], tmpLen);  
  250.                     }  
  251.                 }  
  252.                 break;  
  253.             case FOURCC_movi:  
  254.                 {  
  255.                     _moviOff = ftell(_aviFd);  
  256.                     if (hasIndex)  
  257.                     {  
  258.                         // 跳过movi,直接到idx处  
  259.                         fseek(_aviFd, size - 4, SEEK_CUR);  
  260.                     }  
  261.                 }  
  262.                 break;  
  263.             }  
  264.         }  
  265.         else if (fourcc == FOURCC_idx1)  
  266.         {  
  267.             _aviIndex.fcc = FOURCC_idx1;  
  268.             _aviIndex.cb = size;  
  269.   
  270.             int tmpOff = 0;  
  271.             while (tmpOff < _aviIndex.cb)  
  272.             {  
  273.                 char tmpBuf[4] = {0};  
  274.                 readFile(tmpBuf, 4);  
  275.                 int index = read_le_dw(tmpBuf);  
  276.                 AVIIndexEntry tmpEntry;  
  277.                 tmpEntry.dwFlags = readFileDW();  
  278.                 tmpEntry.dwOffset = readFileDW();  
  279.                 tmpEntry.dwSize = readFileDW();  
  280.                 if (tmpEntry.dwSize > _maxFrameSize)  
  281.                     _maxFrameSize = tmpEntry.dwSize;  
  282.                 // 视频数据  
  283.                 if (tmpBuf[2] == 'd')  
  284.                 {  
  285.                     _aviIndex.videoIndexMap[index].push_back(tmpEntry);  
  286.                 }  
  287.                 else if (tmpBuf[2] == 'w')  
  288.                 {  
  289.                     _aviIndex.audioIndexMap[index].push_back(tmpEntry);  
  290.                 }  
  291.                 // 一个索引信息的长度  
  292.                 tmpOff += 16;  
  293.             }  
  294.         }  
  295.         else if (fourcc ==  FOURCC_JUNK)  
  296.         {  
  297.             // 跳过  
  298.             fseek(_aviFd, size, SEEK_CUR);  
  299.         }  
  300.     }  
  301.   
  302. }  
  303.   
  304. bool AVIFileParser::readFile( char* buf, uint32_t len )  
  305. {  
  306.     uint32_t ret = fread(buf, 1, len, _aviFd);  
  307.     if (ret != len)  
  308.     {  
  309.         if (feof(_aviFd) != 0)  
  310.             return true;  
  311.   
  312. #ifndef NPRINT  
  313.         printf("fread avi error: %d [%s]\n", errno, strerror(errno));  
  314. #endif  
  315.         throw ERROR_INVALID_AVI;  
  316.     }  
  317.   
  318.     return false;  
  319. }  
  320.   
  321. bool AVIFileParser::readFileTagSize( DWORD& fourcc, uint32_t& size, DWORD& fourcc2 )  
  322. {  
  323.     char tmpBuf[12] = {0};  
  324.     bool ret = readFile(tmpBuf, 12);  
  325.     fourcc = read_le_dw(tmpBuf);  
  326.     size = read_le_dw(tmpBuf + 4);  
  327.     fourcc2 = read_le_dw(tmpBuf + 8);  
  328.     return ret;  
  329. }  
  330.   
  331. uint32_t AVIFileParser::readFileDW()  
  332. {  
  333.     char tmpBuf[4] = {0};  
  334.     readFile(tmpBuf, 4);  
  335.     return read_le_dw(tmpBuf);  
  336. }  
  337.   
  338. bool AVIFileParser::readFileDW( uint32_t& dw )  
  339. {  
  340.     char tmpBuf[4] = {0};  
  341.     bool ret = readFile(tmpBuf, 4);  
  342.     dw = read_le_dw(tmpBuf);  
  343.     return ret;  
  344. }  
  345.   
  346. uint16_t AVIFileParser::readFileW()  
  347. {  
  348.     char tmpBuf[2] = {0};  
  349.     readFile(tmpBuf, 2);  
  350.     return read_le_w(tmpBuf);  
  351. }  
  352.   
  353. bool AVIFileParser::readFileW( uint16_t& w )  
  354. {  
  355.     char tmpBuf[2] = {0};  
  356.     bool ret = readFile(tmpBuf, 2);  
  357.     w = read_le_w(tmpBuf);  
  358.     return ret;  
  359. }  
  360.   
  361. int32_t AVIFileParser::getVideoFrame( char* buf, int32_t index /*= -1*/ )  
  362. {  
  363.     if (!_hasVideo)  
  364.         return -1;  
  365.   
  366.     // 只取第一个  
  367.     std::vector<AVIIndexEntry>& videoVec = _aviIndex.videoIndexMap.begin()->second;  
  368.     int32_t tmpIndex = 0;  
  369.     if (index == -1)  
  370.     {  
  371.         if (_currVideoIndex < videoVec.size())  
  372.             tmpIndex = _currVideoIndex++;  
  373.         else  
  374.             return 0;  
  375.     }  
  376.     else  
  377.         tmpIndex = index;  
  378.   
  379.     AVIIndexEntry& videoEntry = videoVec[tmpIndex];  
  380.     // 从movi结尾加上偏移后是dc db的数据,然后再跳过4字节的一个长度值  
  381.     fseek(_aviFd, _moviOff + videoEntry.dwOffset + 4, SEEK_SET);  
  382.     int32_t ret = fread(buf, 1, videoEntry.dwSize, _aviFd);  
  383.     assert(ret == videoEntry.dwSize);  
  384.     return ret;  
  385. }  
  386.   
  387. bool AVIFileParser::seekVideoFrame( int32_t index )  
  388. {  
  389.     std::vector<AVIIndexEntry>& videoVec = _aviIndex.videoIndexMap.begin()->second;  
  390.     if (index < videoVec.size())  
  391.     {  
  392.         _currVideoIndex = index;  
  393.         return true;  
  394.     }  
  395.   
  396.     return false;  
  397. }  

转载请标明出处: http://blog.csdn.net/jwybobo2007/article/details/7662653
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值