Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 984|回复: 0

[实例教程]libavi - parse and demux AVI(2)

[复制链接]

该用户从未签到

发表于 2011-10-22 13:40:19 | 显示全部楼层 |阅读模式
接上一篇
  8
  9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <strings.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <fcntl.h>
15 #include "libavi.h"
16
17 // 18 // compare two indices' offset 19 //    returns: 20 //         1 if elem1's offset large than elem2's 21 //         0 if equal 22 //         -1 if less 23 // 24 int avi_idx_cmp(const void * elem1, const void * elem2)
25 {
26     AVIIDX1ENTRY * e1 = (AVIIDX1ENTRY *)elem1;
27     AVIIDX1ENTRY * e2 = (AVIIDX1ENTRY *)elem2;
28     DWORD a = e1->dwOffset;
29     DWORD b = e2->dwOffset;
30     return (a > b) - (b > a);
31 }
32
33 // 34 // initializae: return 0 35 // 36 int
37 avi_init(AVI * avi)
38 {
39     // clear aviheader 40     memset(&avi->aviheader, 0, sizeof(AVIHEADER));
41
42     return (0);
43 }
44
45 // 46 // parse: 47 // parse the AVI file 48 // returns: 49 //    0 if success, otherwise following error code returned. 50 //    AVI_ERR_READ        if read error 51 //    AVI_ERR_NOT_RIFF    if not RIFF chunk 52 //    AVI_ERR_NOT_AVI    if not AVI file 53 //    AVI_ERR_MEM        if memory error 54 //    AVI_ERR_BROKEN    if AVI file is damaged 55 // 56 int
57 avi_parse(AVI * avi)
58 {
59     AVISTREAMHEADER    avi_streamheader;
60     AVISUPERINDEX * s;
61     char data[256];
62     int len;
63     int    file_len;
64     AVI_FOURCC_TYPE fourcc_type = FOURCC_UNDEF;
65     AVI_TWOCC_TYPE twocc_type = TWOCC_UNDEF;
66   
67     // get file's total length 68     file_len = lseek(avi->fd, 0, SEEK_END);
69   
70     // reset input stream to beginning 71     lseek(avi->fd, 0, SEEK_SET);
72
73     // validate that the file is a RIFF AVI format file 74     if ( read(avi->fd, data, 12) != 12 )
75         return (AVI_ERR_READ);
76     if ( !(strncasecmp(data, "RIFF", 4) == 0 ) )
77         return (AVI_ERR_NOT_RIFF);
78 if ( !(strncasecmp(data+8, "AVI ", 4) == 0) )
79         return (AVI_ERR_NOT_AVI);
80   
81     do {
82         // clear data and read 83         len = 0;
84         memset(data, 0, 256);
85         if ( read(avi->fd, data, 8) != 8 )
86             return (AVI_ERR_READ);
87        
88         fourcc_type = FOURCC_UNDEF;
89         if ( strncasecmp(data, "LIST", 4) == 0 )            // list type 90             fourcc_type = FOURCC_LIST;
91         else if ( strncasecmp(data, "avih", 4) == 0 )    // following are all chunks type 92             fourcc_type = FOURCC_avih;
93         else if ( strncasecmp(data, "strh", 4) == 0 )
94             fourcc_type = FOURCC_strh;
95         else if ( strncasecmp(data, "strf", 4) == 0 )
96             fourcc_type = FOURCC_strf;
97         else if ( strncasecmp(data, "strd", 4) == 0 )
98             fourcc_type = FOURCC_strd;
99         else if ( strncasecmp(data, "strn", 4) == 0 )
100             fourcc_type = FOURCC_strn;
101         else if ( strncasecmp(data, "idx1", 4) == 0 )
102             fourcc_type = FOURCC_idx1;
103         else if ( strncasecmp(data, "indx", 4) == 0 )
104             fourcc_type = FOURCC_indx;
105         else if ( strncasecmp(data, "JUNK", 4) == 0 )
106             fourcc_type = FOURCC_JUNK;
107         else if ( strncasecmp(data, "RIFF", 4) == 0 )    // for OpenDML extension108             fourcc_type = FOURCC_RIFF;
109
110         // main parse place111         switch (fourcc_type) {
112         case FOURCC_LIST:
113             // reserved chunk size, used by movi handler branch114             len = *(int *)(data + 4);
115             ALIGN_EVEN(len);            // align chunk size to even border116            
117             if ( read(avi->fd, data, 4) != 4 )
118                 return (AVI_ERR_READ);
119            
120             if ( strncasecmp(data, "hdrl", 4) == 0 )
121                 avi->aviheader.have_hdrl = 1;
122             if ( strncasecmp(data, "strl", 4) == 0 )
123                 avi->aviheader.have_strl = 1;
124             if ( strncasecmp(data, "rec ", 4) == 0 )
125                 avi->aviheader.have_rec = 1;
126             if ( strncasecmp(data, "movi", 4) == 0 ) {
127                 avi->aviheader.have_movi = 1;
128               
129                 // get movi offset, aligned130                 if(!avi->aviheader.movi_offset){
131                     avi->aviheader.movi_offset = lseek(avi->fd, 0, SEEK_CUR);
132                     ALIGN_EVEN(avi->aviheader.movi_offset);
133                 }
134                 // get movi length135                 avi->aviheader.movi_length = len;
136               
137                 // if there are indicies at file end, just skip movi block138                 if ( avi->aviheader.have_idx1 )
139                     lseek(avi->fd, len - 4, SEEK_CUR);
140             }
141             if (strncasecmp(data, "INFO", 4) == 0) {
142                 lseek(avi->fd, -12, SEEK_CUR);
143                 if ( read(avi->fd, data, 8) != 8 )
144                     return (AVI_ERR_READ);
145                 len = *(int *)(data + 4);
146                 ALIGN_EVEN(len);            // align chunk size to even border147                 lseek(avi->fd, len, SEEK_CUR);
148             }
149             break;
150         case FOURCC_avih:
151             if ( avi->aviheader.have_hdrl ) {
152                 // back trace 8 bytes153                 lseek(avi->fd, -8, SEEK_CUR);
154               
155                 len = sizeof(AVIMAINHEADER);
156                 ALIGN_EVEN(len);            // align chunk size to even border157                 if ( read(avi->fd,
158                     (char *)&avi->aviheader.mainheader,
159                     len) != len )
160                     return (AVI_ERR_READ);
161               
162                 if ( avi->aviheader.mainheader.dwFlags & AMHF_HASINDEX)
163                     avi->aviheader.have_idx1 = 1;
164             }
165             break;
166         case FOURCC_strh:
167             if ( avi->aviheader.have_strl ) {
168                 // back trace 8 bytes169                 lseek(avi->fd, -8, SEEK_CUR);
170               
171                 len = sizeof(AVISTREAMHEADER);
172                 ALIGN_EVEN(len);            // align chunk size to even border173                 if ( read(avi->fd,
174                     (char *)&avi_streamheader, len) != len )
175                     return (AVI_ERR_READ);
176               
177                 if ( strncasecmp(avi_streamheader.fccType, "vids", 4) == 0 )
178                     avi->aviheader.vid_streamheader = avi_streamheader;
179                 else if ( strncasecmp(avi_streamheader.fccType, "auds", 4) == 0 )
180                     avi->aviheader.aud_streamheader = avi_streamheader;
181             }
182             break;
183         case FOURCC_idx1:
184             // read in index185             len = *(int *)(data + 4);
186             ALIGN_EVEN(len);            // align chunk size to even border187             avi->aviheader.idx1_table.idx1_head = (AVIIDX1ENTRY *)malloc(len);
188             if ( avi->aviheader.idx1_table.idx1_head == NULL )
189                 return (AVI_ERR_MEM);
190             if ( read(avi->fd, (char *)avi->aviheader.idx1_table.idx1_head,
191                                     len) != len )
192                 return (AVI_ERR_READ);
193             avi->aviheader.idx1_table.idx1_length = len;
194             avi->aviheader.idx1_table.idx1_count = len / sizeof(AVIIDX1ENTRY);
195             avi->aviheader.have_idx1 = 1;
196             break;
197         case FOURCC_indx:
198             // super index199             len = *(int *)(data + 4);
200             ALIGN_EVEN(len);            // align chunk size to even border201             if (len < 24)
202                 break;
203             avi->aviheader.index_table.index_count++;
204             avi->aviheader.index_table.index_head = realloc(
205                     avi->aviheader.index_table.index_head,
206                     avi->aviheader.index_table.index_count * sizeof(AVISUPERINDEX));
207             if (avi->aviheader.index_table.index_head == NULL)
208                 return (AVI_ERR_MEM);
209             s = avi->aviheader.index_table.index_head + avi->aviheader.index_table.index_count -1;
210             memcpy(s->fcc, "indx", 4);
211             s->cb = len ;
212             if (read(avi->fd, ((char *)s)+8, 24)!=24)
213                 return (AVI_ERR_READ);
214             memset(s->dwReserved, 0, 3 * 4);        // stuff dwReserved[3] of AVISUPERINDEX215             s->aIndex = calloc(s->nEntriesInUse, sizeof(avisuperindex_entry));
216             s->stdidx = calloc(s->nEntriesInUse, sizeof(avistdindex_chunk));
217             if (s->aIndex == NULL)
218                 return (AVI_ERR_MEM);
219             if (read(avi->fd, (char *)s->aIndex,
220                 s->nEntriesInUse * sizeof(avisuperindex_entry))
221                 != s->nEntriesInUse * sizeof(avisuperindex_entry))
222                 return (AVI_ERR_READ);
223             avi->aviheader.have_indx = 1 ;
224             break;
225         case FOURCC_RIFF:
226             // another RIFF List, for OpenDML227             if (read(avi->fd, data, 4) != 4)
228                 return (AVI_ERR_READ);
229             if (strncmp(data, "AVIX", 4))
230                 return (AVI_ERR_NOT_RIFF);
231             else{
232               
235                 if( avi->aviheader.have_indx)
236                     avi->aviheader.isodml = 1 ;
237             }
238             break;
239         case FOURCC_strf:
240         case FOURCC_strd:
241         case FOURCC_strn:
242         case FOURCC_JUNK:   
243         default:
244             // skipped245             len = *(int *)(data + 4);
246             ALIGN_EVEN(len);            // align chunk size to even border247             lseek(avi->fd, len, SEEK_CUR);
248             break;
249         }
250     } while ( lseek(avi->fd, 0, SEEK_CUR) < file_len );
251   
252     // if neither idx1 nor indx, then generate idx1253     if (!avi->aviheader.have_idx1 && !avi->aviheader.have_indx) {
254         //rewind the stream position to the beginning of the file255         lseek(avi->fd, 0, SEEK_SET);
256        
257         //seek to the begining of movi chunk258         lseek(avi->fd, avi->aviheader.movi_offset, SEEK_CUR);
259        
260         AVIIDX1ENTRY * curidx;
261         char id[4];
262         while (read(avi->fd, id, 4) >=0 && lseek(avi->fd, 0, SEEK_CUR) <
263                 avi->aviheader.movi_offset + avi->aviheader.movi_length - 4){
264             if (read(avi->fd, data, 4) != 4)
265                 return (AVI_ERR_READ);
266             len = *(int*)data;
267             avi->aviheader.idx1_table.idx1_head = realloc(
268                     avi->aviheader.idx1_table.idx1_head,
269                     avi->aviheader.idx1_table.idx1_length + sizeof(AVIIDX1ENTRY));
270             if ( avi->aviheader.idx1_table.idx1_head != NULL )
271                 curidx = avi->aviheader.idx1_table.idx1_head + avi->aviheader.idx1_table.idx1_count;
272             else
273                 return (AVI_ERR_MEM);
274             memcpy(&curidx->dwChunkId, id, 4);    // FOURCC275             curidx->dwFlags = AVIIF_KEYFRAME;
276             curidx->dwFlags |= (lseek(avi->fd, 0, SEEK_CUR)) >> 16 & 0xffff0000U;
277             curidx->dwOffset = (unsigned int)(lseek(avi->fd, 0, SEEK_CUR) -
278                             avi->aviheader.movi_offset - 4);    // offset relative to movi279             curidx->dwSize = len;
280             avi->aviheader.idx1_table.idx1_count++;
281             avi->aviheader.idx1_table.idx1_length += sizeof(AVIIDX1ENTRY);
282             ALIGN_EVEN(len);
283             lseek(avi->fd, len, SEEK_CUR);
284         }
285         avi->aviheader.have_idx1 = 1 ;
286     }
287   
288     //deal with super index289     if (avi->aviheader.isodml && avi->aviheader.have_indx) {
290         AVISUPERINDEX * cx;
291     AVIIDX1ENTRY * idx;
292         int i, j;
293        
294         if (avi->aviheader.idx1_table.idx1_head)
295             free(avi->aviheader.idx1_table.idx1_head);
296         avi->aviheader.idx1_table.idx1_count = 0;
297         avi->aviheader.idx1_table.idx1_head = NULL ;
298        
299         // read the standard indices300         for (cx = &avi->aviheader.index_table.index_head[0], i = 0;
301                 i < avi->aviheader.index_table.index_count; cx++, i++) {
302             for (j = 0; j < cx->nEntriesInUse; j++){
303                 int ret1, ret2;
304               
305                 memset(&cx->stdidx[j], 0, 32);
306                 // reset input stream to beginning307                 lseek(avi->fd, 0, SEEK_SET);
308                 ret1 = lseek(avi->fd, (DWORDLONG)cx->aIndex[j].qwOffset, SEEK_CUR);
309                 if ((ret2 = read(avi->fd, (char *)&cx->stdidx[j], 32)) != 32)
310                     return (AVI_ERR_READ);
311                 if (ret1 < 0 || cx->stdidx[j].nEntriesInUse == 0) {
312                     // this is a broken file (probably incomplete)313                     avi->aviheader.isodml = 0;
314                     avi->aviheader.idx1_table.idx1_count = 0 ;
315                     return (AVI_ERR_BROKEN);
316                 }
317                 avi->aviheader.idx1_table.idx1_count += cx->stdidx[j].nEntriesInUse;
318                 cx->stdidx[j].aIndex = malloc(cx->stdidx[j].nEntriesInUse * sizeof(avistdindex_entry));
319                 if (cx->stdidx[j].aIndex == NULL)
320                      return (AVI_ERR_MEM);
321                 if (read(avi->fd, (char *)cx->stdidx[j].aIndex,
322                     cx->stdidx[j].nEntriesInUse * sizeof(avistdindex_entry)) !=
323                     cx->stdidx[j].nEntriesInUse * sizeof(avistdindex_entry))
324                      return (AVI_ERR_READ);
325                 cx->stdidx[j].dwReserved3 = 0;
326             }
327         }
328        
329        
333     avi->aviheader.idx1_table.idx1_head = malloc(
334                 avi->aviheader.idx1_table.idx1_count * sizeof(AVIIDX1ENTRY));
335         idx = avi->aviheader.idx1_table.idx1_head;
336         if (idx == NULL)
337             return (AVI_ERR_MEM);
338         for (cx = avi->aviheader.index_table.index_head;
339             cx != &avi->aviheader.index_table.index_head[avi->aviheader.index_table.index_count]; cx++) {
340             avistdindex_chunk * sic;
341             for (sic = cx->stdidx; sic != &cx->stdidx[cx->nEntriesInUse]; sic++){
342                 avistdindex_entry * sie;
343                 for (sie=sic->aIndex; sie != &sic->aIndex[sic->nEntriesInUse]; sie++){
344                     DWORDLONG offset = sie->dwOffset + sic->qwBaseOffset;
345                     memcpy(idx->dwChunkId, sic->dwChunkId, 4);
346                     idx->dwOffset = offset;
347                     idx->dwFlags = (offset >> 32) << 16;
348                     idx->dwSize = sie->dwSize & 0x7fffffff;
349                     idx->dwFlags |= (sie->dwSize & 0x80000000)?0x0:AVIIF_KEYFRAME;
350                     idx++;
351                 }
352             }
353         }
354        
355         // sorting in offset356         qsort(avi->aviheader.idx1_table.idx1_head, avi->aviheader.idx1_table.idx1_count,
357             sizeof(AVIIDX1ENTRY), avi_idx_cmp);
358     }
359   
360     return (0);
361 }
362
363 //364 // go to first video block365 // return 0 if found, else -1366 //367 int
368 avi_goto_first_video_block(AVI * avi)
369 {
370     AVIIDX1ENTRY    * pIdx1Entry;
371     FOURCC            four_cc;
372   
373     if ( avi->aviheader.have_idx1 || avi->aviheader.have_indx) {
374         pIdx1Entry = avi->aviheader.idx1_table.idx1_head;
375         memcpy(four_cc, &pIdx1Entry->dwChunkId, 4);
376        
377         while ( ! ( (four_cc[2] == 'd' && four_cc[3] == 'b') ||
378                     (four_cc[2] == 'd' && four_cc[3] == 'c') ) ) {
379             if ( pIdx1Entry++ < avi->aviheader.idx1_table.idx1_head + avi->aviheader.idx1_table.idx1_count )
380                 memcpy(four_cc, &pIdx1Entry->dwChunkId, 4);
381         }
382        
383         if ( pIdx1Entry >= avi->aviheader.idx1_table.idx1_head + avi->aviheader.idx1_table.idx1_count ) {
384             avi->aviheader.idx1_table.current_vid_idx = NULL;
385             return (-1);
386         } else {
387             avi->aviheader.idx1_table.current_vid_idx = pIdx1Entry;        // that's it388             return (0);
389         }
390     } else
391         return (AVI_ERR_NOT_AVI);
392   
393     return (-1);
394 }
395
回复

使用道具 举报

该用户从未签到

发表于 2011-10-22 13:40:24 | 显示全部楼层

Re:[实例教程]libavi

Thanks you !~~~~~~~~~~~~
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2025-1-9 07:27 , Processed in 0.348482 second(s), 33 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表