DecapsAVI.cpp
上传用户:tuheem
上传日期:2007-05-01
资源大小:21889k
文件大小:22k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. #include "DecapsAVI.h"
  2. static void long2str(char *dst, int n)
  3. {
  4. dst[0] = (n      ) & 0xff;
  5. dst[1] = (n >>  8) & 0xff;
  6. dst[2] = (n >> 16) & 0xff;
  7. dst[3] = (n >> 24) & 0xff;
  8. }
  9. unsigned long str2ulong(char *str)
  10. {
  11.     unsigned long result;
  12. result = ( ((unsigned long) str[0] & 0xFF) | ( ((unsigned long)str[1] &0xFF) << 8) |
  13.   (((unsigned long) str[2] & 0xFF) << 16) | ( ((unsigned long) str[3] & 0xFF) << 24) );
  14. return result;
  15. }
  16. static unsigned long str2ushort(char *str)
  17. {
  18. return ( str[0] | (str[1]<<8) );
  19. }
  20. media_type_t MediaDecapsAVI::GetType()
  21. {
  22. return MEDIA_TYPE_DECAPS;
  23. }
  24. char *MediaDecapsAVI::GetName()
  25. {
  26. return "AVI Demuxer";
  27. }
  28. MP_RESULT MediaDecapsAVI::Connect(MediaItem *item)
  29. {
  30. if(item->GetType() == MEDIA_TYPE_INPUT) {
  31. this->input = (MediaItemInput *) item;
  32. }
  33. this->video_pos  = 0;
  34. this->audio_posc = 0;
  35. this->audio_posb = 0;
  36. this->idx         = NULL;
  37. this->video_index = NULL;
  38. this->audio_index = NULL;
  39. if(this->IsAVI()) {
  40. if(this->FillHeader(1)) {
  41. return MP_RESULT_OK;
  42. }
  43. else {
  44. this->input->Seek(0, INPUT_SEEK_SET);
  45. this->IsAVI();
  46. if(this->FillHeader(0)) {
  47. return MP_RESULT_OK;
  48. }
  49. }
  50. }
  51. return MP_RESULT_ERROR;
  52. }
  53. MP_RESULT MediaDecapsAVI::ReleaseConnections()
  54. {
  55. this->input = NULL;
  56. if(this->idx != NULL)
  57. free(this->idx);
  58. if(this->video_index != NULL)
  59. free(this->video_index);
  60. if(this->audio_index != NULL)
  61. free(this->audio_index);
  62. this->idx         = NULL;
  63. this->video_index = NULL;
  64. this->audio_index = NULL;
  65. this->audio_strn = 0;
  66. this->video_strn = 0;
  67. memset(&this->waveformatex, 0, sizeof(MPEGLAYER3WAVEFORMAT));
  68. memset(&this->bitmapinfoheader, 0, sizeof(BITMAPINFOHEADER));
  69. return MP_RESULT_OK;
  70. }
  71. DWORD         MediaDecapsAVI::GetCaps()
  72. {
  73. return 0;
  74. }
  75. MP_RESULT     MediaDecapsAVI::Configure(HINSTANCE hInstance, HWND hwnd)
  76. {
  77. return MP_RESULT_ERROR;
  78. }
  79. MediaDecapsAVI::MediaDecapsAVI()
  80. {
  81. this->video_pos  = 0;
  82. this->audio_posc = 0;
  83. this->audio_posb = 0;
  84. this->idx         = NULL;
  85. this->video_index = NULL;
  86. this->audio_index = NULL;
  87. this->hIOMutex = CreateMutex (NULL, FALSE, NULL);
  88. this->input = NULL;
  89. }
  90. MediaDecapsAVI::~MediaDecapsAVI()
  91. {
  92. CloseHandle(this->hIOMutex);
  93. }
  94. int MediaDecapsAVI::IsAVI()
  95. {
  96. MediaBuffer *mb = new MediaBuffer();
  97. mb->Alloc(12);
  98. if(this->input != NULL) {
  99. if( this->input->Read(mb, 12) != 12 ) {
  100. delete mb;
  101. return 0;
  102. }
  103. if( strncmp((char *) mb->GetData(), "RIFF", 4) !=0 || 
  104. strncmp(((char *) mb->GetData()) + 8, "AVI ", 4) !=0 ) {
  105. return 0;
  106. }
  107. delete mb;
  108. return 1;
  109. }
  110. return 0;
  111. }
  112. int MediaDecapsAVI::SampleSize()
  113. {
  114. int s;
  115. s = ((this->a_bits + 7) / 8) * this->a_chans;
  116. if(s == 0)
  117. s = 1;
  118. return s;
  119. }
  120. int MediaDecapsAVI::FillHeader(int getIndex)
  121. {
  122. unsigned long  n, rate; 
  123. long           scale, idx_type;
  124. char          *hdrl_data;
  125. long           i, hdrl_len = 0;
  126. long           nvi, nai, ioff;
  127. long           tot;
  128. int            lasttag = 0;
  129. int            vids_strh_seen = 0;
  130. int            vids_strf_seen = 0;
  131. int            auds_strh_seen = 0;
  132. int            auds_strf_seen = 0;
  133. int            num_stream = 0;
  134. MediaBuffer   *mb = new MediaBuffer();
  135. if(this->input == NULL)
  136. return MP_RESULT_ERROR;
  137. mb->Alloc(256);
  138. hdrl_data = 0;
  139. while(1)
  140.     {
  141. if( this->input->Read(mb, 8) != 8 ) 
  142. break; 
  143. n = str2ulong(((char *) mb->GetData()) + 4);
  144. n = PAD_EVEN(n);
  145. if(strncmp((char *) mb->GetData(), "LIST", 4) == 0)
  146. {
  147. if( this->input->Read(mb, 4) != 4 ) {
  148. mb->Free();
  149. return 0;
  150. }
  151. n -= 4;
  152. if(strncmp((char *) mb->GetData(), "hdrl", 4) == 0)
  153. {
  154. MediaBuffer *mbh;
  155. hdrl_len = n;
  156. char buffer[256];
  157. sprintf(buffer, "size = %d", n);
  158. mbh = new MediaBuffer();
  159. mbh->Alloc(n);
  160. hdrl_data = (char *) new char[n];
  161. if(hdrl_data == NULL) { 
  162. mb->Free();
  163. return 0;
  164. }
  165. if( this->input->Read(mbh, n) != n ) {
  166. mb->Free();
  167. return 0;
  168. }
  169. memcpy(hdrl_data, mbh->GetData(), n);
  170. mbh->Free();
  171. }
  172. else if(strncmp((char *) mb->GetData(), "movi", 4) == 0)
  173. {
  174. this->movi_start = this->input->Seek(0, INPUT_SEEK_CUR);
  175. this->input->Seek(n, INPUT_SEEK_CUR);
  176. }
  177. else
  178. this->input->Seek(n, INPUT_SEEK_CUR);
  179. }
  180. else if(strncmp((char *) mb->GetData(),"idx1",4) == 0)
  181. {
  182. this->n_idx = this->max_idx = n/16;
  183. this->idx = (char((*)[16]) ) new char[n];
  184. if(this->idx == NULL) { 
  185. mb->Free();
  186. return 0;
  187. }
  188. unsigned long read;
  189. MediaBuffer  *mbi = new MediaBuffer();
  190. mbi->Alloc(n);
  191. if( (read = this->input->Read(mbi, n)) != n ) {
  192. break;
  193. }
  194. memcpy(this->idx, mbi->GetData(), n);
  195. mbi->Free();
  196. }
  197. else {
  198.   
  199. this->input->Seek(n, INPUT_SEEK_CUR);
  200. }
  201. }
  202. if(!hdrl_data) {
  203. mb->Free();
  204. return 0;
  205. }
  206. if(!this->movi_start) {
  207. mb->Free();
  208. return 0;
  209. }
  210. for(i=0; i < hdrl_len; )
  211. {
  212. if(strncmp(hdrl_data + i, "LIST", 4)==0) 
  213. i+= 12; 
  214. continue; 
  215. }
  216. n = str2ulong(hdrl_data+i+4);
  217. n = PAD_EVEN(n);
  218. if(strncmp(hdrl_data + i, "strh", 4)==0)
  219. {
  220. i += 8;
  221. if(strncmp(hdrl_data + i, "vids", 4) == 0 && !vids_strh_seen)
  222. {
  223. memcpy(this->compressor,hdrl_data+i+4,4);
  224. this->compressor[4] = 0;
  225. scale = str2ulong(hdrl_data+i+20);
  226. rate  = str2ulong(hdrl_data+i+24);
  227. if(scale!=0) 
  228. this->fps = (double)rate/(double)scale;
  229. this->video_frames = str2ulong(hdrl_data+i+32);
  230. this->video_strn = num_stream;
  231. vids_strh_seen = 1;
  232. lasttag = 1; 
  233. }
  234. else if (strncmp (hdrl_data + i, "auds", 4) == 0 && ! auds_strh_seen)
  235. {
  236. this->audio_bytes = str2ulong(hdrl_data + i + 32)*this->SampleSize();
  237. this->audio_strn = num_stream;
  238. auds_strh_seen = 1;
  239. lasttag = 2; 
  240. }
  241. else
  242. lasttag = 0;
  243. num_stream++;
  244. }
  245. else if(strncmp(hdrl_data + i, "strf", 4)==0)
  246. {
  247. i += 8;
  248. if(lasttag == 1)
  249. {
  250. memcpy(&this->bitmapinfoheader, 
  251. hdrl_data + i,
  252. sizeof(BITMAPINFOHEADER));  
  253. this->width  = str2ulong(hdrl_data+i+4);
  254. this->height = str2ulong(hdrl_data+i+8);
  255. vids_strf_seen = 1;
  256. }
  257. else if(lasttag == 2)
  258. {
  259. memcpy(&this->waveformatex,
  260.    hdrl_data + i,
  261.    sizeof(MPEGLAYER3WAVEFORMAT));
  262. this->a_fmt   = str2ushort(hdrl_data + i  );
  263. this->a_chans = str2ushort(hdrl_data + i + 2);
  264. this->a_rate  = str2ulong (hdrl_data + i + 4);
  265. this->a_bits  = str2ushort(hdrl_data + i + 14) == 0 ? 16 : str2ushort(hdrl_data + i + 14);
  266. auds_strf_seen = 1;
  267. }
  268. lasttag = 0;
  269. }
  270. else
  271. {
  272. i += 8;
  273. lasttag = 0;
  274. }
  275. i += n;
  276. }
  277. free(hdrl_data);
  278. if(!vids_strh_seen || !vids_strf_seen || this->video_frames==0) { 
  279. mb->Free();
  280. return 0;
  281. }
  282. this->video_tag[0] = this->video_strn/10 + '0';
  283. this->video_tag[1] = this->video_strn%10 + '0';
  284. this->video_tag[2] = 'd';
  285. this->video_tag[3] = 'b';
  286. if(!this->a_chans) 
  287. this->audio_strn = 99;
  288. this->audio_tag[0] = this->audio_strn/10 + '0';
  289. this->audio_tag[1] = this->audio_strn%10 + '0';
  290. this->audio_tag[2] = 'w';
  291. this->audio_tag[3] = 'b';
  292. this->input->Seek(this->movi_start, INPUT_SEEK_SET);
  293. if(!getIndex) 
  294. return 1;
  295. idx_type = 0;
  296. if(this->idx)
  297. {
  298. unsigned long pos, len;
  299. for(i = 0; i < this->n_idx; i++) {
  300. if( strncmp(this->idx[i], this->video_tag, 3) == 0 ) 
  301. break;
  302. }
  303. if(i >= this->n_idx) 
  304. return 0;
  305. pos = str2ulong(this->idx[i] + 8);
  306. len = str2ulong(this->idx[i] + 12);
  307. this->input->Seek(pos, INPUT_SEEK_SET);
  308. if(this->input->Read(mb, 8)!=8) 
  309. return 0;
  310. if( strncmp((char *) mb->GetData(), this->idx[i], 4) == 0 && str2ulong((char *) mb->GetData() + 4) == len )
  311. {
  312. idx_type = 1; 
  313. }
  314. else
  315. {
  316. this->input->Seek(pos + this->movi_start - 4,INPUT_SEEK_SET);
  317. if(this->input->Read(mb, 8) != 8) 
  318. return 0;
  319. if( strncmp((char *) mb->GetData(), this->idx[i], 4) == 0 && str2ulong((char *) mb->GetData() + 4) == len )
  320. {
  321. idx_type = 2; 
  322. }
  323. }
  324. }
  325. if(idx_type == 0)
  326. {
  327. this->input->Seek(this->movi_start, INPUT_SEEK_SET);
  328. this->max_idx = 4096;
  329. this->n_idx   = 0;
  330. this->idx = (char((*)[16]) ) new char[this->max_idx];
  331. while(1)
  332. {
  333. if( this->input->Read(mb, 8) != 8 ) 
  334. break;
  335. n = str2ulong((char *) mb->GetData() + 4);
  336. if(strncmp((char *) mb->GetData(), "LIST", 4) == 0)
  337. {
  338. this->input->Seek(4, INPUT_SEEK_CUR);
  339. continue;
  340. }
  341. if( ((((char *) mb->GetData())[2]=='d' || ((char *) mb->GetData())[2]=='D') &&
  342.  (((char *) mb->GetData())[3]=='b' || ((char *) mb->GetData())[3]=='B' || 
  343.   ((char *) mb->GetData())[3]=='c' || ((char *) mb->GetData())[3]=='C') ) || 
  344. ((((char *) mb->GetData())[2]=='w' || ((char *) mb->GetData())[2]=='W') &&
  345.  (((char *) mb->GetData())[3]=='b' || ((char *) mb->GetData())[3]=='B') ) )
  346. {
  347. this->AddIndexEntry(((char *) mb->GetData()),
  348. 0, 
  349. this->input->Seek(0, INPUT_SEEK_CUR) - 8, 
  350. n);
  351. }
  352. this->input->Seek(PAD_EVEN(n), INPUT_SEEK_CUR);
  353. }
  354. idx_type = 1;
  355. }
  356. nvi = 0;
  357. nai = 0;
  358. for(i=0; i < this->n_idx; i++)
  359. {
  360. if(strncmp(this->idx[i], this->video_tag, 3) == 0) 
  361. nvi++;
  362. if(strncmp(this->idx[i], this->audio_tag, 4) == 0) 
  363. nai++;
  364. }
  365. this->video_frames = nvi;
  366. this->audio_chunks = nai;
  367. if(this->video_frames == 0) {
  368. mb->Free();
  369. return 0;
  370. }
  371. this->video_index = (video_index_entry *) new char[(nvi*sizeof(video_index_entry))];
  372. if(this->video_index == 0) { 
  373. mb->Free();
  374. return 0;
  375. }
  376. if(this->audio_chunks)
  377. {
  378. this->audio_index = (audio_index_entry *) new char[(nai*sizeof(audio_index_entry))];
  379. if(this->audio_index == 0) {
  380. mb->Free();
  381. return 0;
  382. }
  383. }
  384. nvi = 0;
  385. nai = 0;
  386. tot = 0;
  387. ioff = idx_type == 1 ? 8 : this->movi_start+4;
  388. for(i=0; i < this->n_idx; i++)
  389. {
  390. if(strncmp(this->idx[i], this->video_tag, 3) == 0)
  391. {
  392. this->video_index[nvi].flags = str2ulong(this->idx[i]+ 4);
  393. this->video_index[nvi].pos   = str2ulong(this->idx[i]+ 8)+ioff;
  394. this->video_index[nvi].len   = str2ulong(this->idx[i]+12);
  395. nvi++;
  396. }
  397. if(strncmp(this->idx[i], this->audio_tag, 4) == 0)
  398. {
  399. this->audio_index[nai].pos = str2ulong(this->idx[i]+ 8)+ioff;
  400. this->audio_index[nai].len = str2ulong(this->idx[i]+12);
  401. this->audio_index[nai].tot = tot;
  402. tot += this->audio_index[nai].len;
  403. nai++;
  404. }
  405. }
  406. this->audio_bytes = tot;
  407. this->input->Seek(this->movi_start, INPUT_SEEK_SET);
  408. this->video_pos = 0;
  409. mb->Free();
  410. return 1;
  411. }
  412. int MediaDecapsAVI::AddIndexEntry(char *tag, 
  413.   long flags, 
  414.   long pos, 
  415.   long len)
  416. {
  417. void *ptr;
  418. if(this->n_idx*16 >= this->max_idx)
  419. {
  420. ptr = realloc((void *)this->idx,
  421. (this->max_idx + 4096) * 16);
  422. if(ptr == 0) {
  423. return -1;
  424. }
  425. this->max_idx += 4096;
  426. this->idx = (char((*)[16]) ) ptr;
  427. }
  428. memcpy(this->idx[this->n_idx], tag, 4);
  429. long2str(this->idx[this->n_idx]+ 4, flags);
  430. long2str(this->idx[this->n_idx]+ 8, pos);
  431. long2str(this->idx[this->n_idx]+12, len);
  432. this->n_idx++;
  433. return 0;
  434. }
  435. int  MediaDecapsAVI::ReFillIndex()
  436. {
  437. unsigned long  n; 
  438. long           idx_type;
  439. long           i;
  440. long           nvi, nai, ioff;
  441. long           tot;
  442. MediaBuffer   *mb = new MediaBuffer();
  443. if(this->input == NULL)
  444. return MP_RESULT_ERROR;
  445. mb->Alloc(256);
  446. this->input->Seek(this->movi_start, INPUT_SEEK_SET);
  447. this->max_idx = 4096;
  448. this->n_idx   = 0;
  449. this->idx = (char((*)[16]) ) realloc(this->idx, this->max_idx*16);
  450. while(1)
  451. {
  452. if( this->input->Read(mb, 8) != 8 ) 
  453. break;
  454. n = str2ulong((char *) mb->GetData() + 4);
  455. if(strncmp((char *) mb->GetData(), "LIST", 4) == 0)
  456. {
  457. this->input->Seek(4, INPUT_SEEK_CUR);
  458. continue;
  459. }
  460. if( ((((char *) mb->GetData())[2]=='d' || ((char *) mb->GetData())[2]=='D') &&
  461.  (((char *) mb->GetData())[3]=='b' || ((char *) mb->GetData())[3]=='B' || 
  462.   ((char *) mb->GetData())[3]=='c' || ((char *) mb->GetData())[3]=='C') ) || 
  463. ((((char *) mb->GetData())[2]=='w' || ((char *) mb->GetData())[2]=='W') &&
  464.  (((char *) mb->GetData())[3]=='b' || ((char *) mb->GetData())[3]=='B') ) )
  465. {
  466. this->AddIndexEntry(((char *) mb->GetData()),
  467. 0, 
  468. this->input->Seek(0, INPUT_SEEK_CUR) - 8, 
  469. n);
  470. }
  471. this->input->Seek(PAD_EVEN(n), INPUT_SEEK_CUR);
  472. }
  473. idx_type = 1;
  474. nvi = 0;
  475. nai = 0;
  476. for(i=0; i < this->n_idx; i++)
  477. {
  478. if(strncmp(this->idx[i], this->video_tag, 3) == 0) 
  479. nvi++;
  480. if(strncmp(this->idx[i], this->audio_tag, 4) == 0) 
  481. nai++;
  482. }
  483. this->video_frames = nvi;
  484. this->audio_chunks = nai;
  485. if(this->video_frames == 0) 
  486. return 0;
  487. this->video_index = (video_index_entry *) realloc(this->video_index, nvi*sizeof(video_index_entry));
  488. if(this->video_index == 0) 
  489. return 0;
  490. if(this->audio_chunks)
  491. {
  492. this->audio_index = (audio_index_entry *) realloc(this->audio_index, nai*sizeof(audio_index_entry));
  493. if(this->audio_index==0) {
  494. mb->Free();
  495. return 0;
  496. }
  497. }
  498. nvi = 0;
  499. nai = 0;
  500. tot = 0;
  501. ioff = idx_type == 1 ? 8 : this->movi_start+4;
  502. for(i=0; i < this->n_idx; i++)
  503. {
  504. if(strncmp(this->idx[i], this->video_tag, 3) == 0)
  505. {
  506. this->video_index[nvi].flags = str2ulong(this->idx[i]+ 4);
  507. this->video_index[nvi].pos   = str2ulong(this->idx[i]+ 8)+ioff;
  508. this->video_index[nvi].len   = str2ulong(this->idx[i]+12);
  509. nvi++;
  510. }
  511. if(strncmp(this->idx[i], this->audio_tag, 4) == 0)
  512. {
  513. this->audio_index[nai].pos = str2ulong(this->idx[i]+ 8)+ioff;
  514. this->audio_index[nai].len = str2ulong(this->idx[i]+12);
  515. this->audio_index[nai].tot = tot;
  516. tot += this->audio_index[nai].len;
  517. nai++;
  518. }
  519. }
  520. this->audio_bytes = tot;
  521. mb->Free();
  522. return 1;
  523. }
  524. BOOL MediaDecapsAVI::isKeyframe(long frame)
  525. {
  526.   if(frame < 0 || frame > this->video_frames)
  527.     frame = 0;
  528.   if(!this->video_index)         
  529.     { 
  530.  
  531.       return 1; 
  532.     }
  533.   return this->video_index[frame].flags & AVIIF_KEYFRAME;
  534. }
  535. unsigned int  MediaDecapsAVI::GetNumberOfVideoStreams()
  536. {
  537. return 1;
  538. }
  539. unsigned int  MediaDecapsAVI::GetNumberOfAudioStreams()
  540. {
  541. if(this->audio_strn == 99)
  542. return 0;
  543. return this->audio_strn;
  544. }
  545. unsigned int  MediaDecapsAVI::GetVideoWidth(unsigned int StreamId)
  546. {
  547. return this->width;
  548. }
  549. unsigned int  MediaDecapsAVI::GetVideoHeight(unsigned int StreamId)
  550. {
  551. return this->height;
  552. }
  553. double        MediaDecapsAVI::GetVideoFrameRate(unsigned int StreamId)
  554. {
  555. if(this->fps == 0)
  556. this->fps = 25;
  557. if(this->fps == 23)
  558. this->fps = 25;
  559. return this->fps;
  560. }
  561. char  *MediaDecapsAVI::GetVideoCompression(unsigned int StreamId)
  562. {
  563. return this->compressor;
  564. }
  565. BITMAPINFOHEADER *MediaDecapsAVI::GetVideoHeader(unsigned int StreamId)
  566. {
  567. return &this->bitmapinfoheader;
  568. }
  569. unsigned long MediaDecapsAVI::GetCurrentVideoFrame(unsigned int StreamId)
  570. {
  571. return this->video_pos;
  572. }
  573. unsigned long MediaDecapsAVI::GetTotalVideoFrames(unsigned int StreamId)
  574. {
  575. return this->video_frames;
  576. }
  577. unsigned long MediaDecapsAVI::GetTotalVideoTime(unsigned int StreamId)
  578. {
  579. if(this->fps == 0) {
  580. return 0;
  581. }
  582. else {
  583. return (unsigned long) (this->video_frames * 1000 / (double) this->fps);
  584. }
  585. }
  586. unsigned int  MediaDecapsAVI::GetAudioBits(unsigned int StreamId)
  587. {
  588. return this->a_bits;
  589. }
  590. unsigned int  MediaDecapsAVI::GetAudioChannels(unsigned int StreamId)
  591. {
  592. return this->a_chans;
  593. }
  594. unsigned int  MediaDecapsAVI::GetAudioFrequency(unsigned int StreamId)
  595. {
  596. return this->a_rate;
  597. }
  598. WAVEFORMATEX *MediaDecapsAVI::GetAudioFormat(unsigned int StreamId)
  599. {
  600. return (WAVEFORMATEX *) &this->waveformatex;
  601. }
  602. unsigned int  MediaDecapsAVI::GetNextVideoFrameSize(unsigned int StreamId)
  603. {
  604. if(!this->video_index) { 
  605. return 0; 
  606. }
  607. return(this->video_index[this->video_pos].len);
  608. }
  609. unsigned int MediaDecapsAVI::ReadVideoFrame(unsigned int StreamId, MediaBuffer *mb)
  610. {
  611. unsigned int m;
  612. unsigned int n;
  613. if(!this->video_index || !mb) {
  614. return MP_RESULT_ERROR; 
  615.     }
  616. if(this->video_pos < 0 || this->video_pos >= this->video_frames - 1) {
  617. return MP_RESULT_ERROR;
  618.     }
  619. WaitForSingleObject(this->hIOMutex, INFINITE);
  620. n = this->video_index[this->video_pos].len;
  621. this->input->Seek(this->video_index[this->video_pos].pos, INPUT_SEEK_SET);
  622. if(mb->GetSize() < n) {
  623. mb->ReAlloc(n);
  624. }
  625. if ((m = this->input->Read(mb, n)) != n) {
  626. this->video_pos++;
  627.     ReleaseMutex(this->hIOMutex);
  628. char msg[256];
  629. sprintf(msg, "index %u and %u at %u", this->video_index[this->video_pos].len, this->video_index[this->video_pos].pos, this->video_pos);
  630. MessageBox(NULL, msg, "", MB_OK);
  631. sprintf(msg, "read %d on %u at %d on %d", m, n, this->video_pos, this->video_frames);
  632. MessageBox(NULL, msg, "", MB_OK);
  633. return n;
  634.     }
  635.     this->video_pos++;
  636.  
  637.     ReleaseMutex(this->hIOMutex);
  638.     return MP_RESULT_OK;
  639. }
  640. unsigned int MediaDecapsAVI::ReadAudioData(unsigned int StreamId, char *buffer, unsigned int bytes)
  641. {
  642. unsigned int nr, pos, left = 0, todo, posc, posb, asked_bytes;
  643. MediaBuffer *mbi = new MediaBuffer();
  644. if(!this->audio_index || !buffer) {
  645. return MP_RESULT_ERROR; 
  646.     }
  647. asked_bytes = bytes;
  648. posc = this->audio_posc;
  649. posb = this->audio_posb;
  650.    nr = 0; 
  651.    mbi->Alloc(bytes);
  652.    WaitForSingleObject(this->hIOMutex, INFINITE);
  653. while(bytes > 0) {
  654. left = this->audio_index[this->audio_posc].len - this->audio_posb;
  655. if(left == 0) {
  656. if(this->audio_posc >= this->audio_chunks - 1) {
  657. ReleaseMutex(this->hIOMutex);
  658. this->audio_posb = posb;
  659. this->audio_posc = posc;
  660. return 0;
  661. }
  662. this->audio_posc++;
  663. this->audio_posb = 0;
  664. continue;
  665. }
  666. if(bytes < left)
  667. todo = bytes;
  668. else
  669. todo = left;
  670. pos = this->audio_index[this->audio_posc].pos + this->audio_posb;
  671.       
  672. this->input->Seek(pos, INPUT_SEEK_SET);
  673.     if (this->input->Read(mbi, todo) != todo) {
  674. ReleaseMutex(this->hIOMutex);
  675. this->audio_posb = posb;
  676. this->audio_posc = posc;
  677. return 0;
  678. }
  679. memcpy(buffer + nr, mbi->GetData(), todo);
  680. bytes -= todo;
  681. nr    += todo;
  682. this->audio_posb += todo;
  683. }
  684. mbi->Free();
  685. delete mbi;
  686.     ReleaseMutex(this->hIOMutex);
  687.     return asked_bytes;
  688. }
  689. MP_RESULT     MediaDecapsAVI::UpdateForSize()
  690. {
  691. this->ReFillIndex();
  692. return MP_RESULT_OK;
  693. }
  694. MP_RESULT     MediaDecapsAVI::SeekAudio(unsigned int StreamId, long bytes)
  695. {
  696.    long n0, n1, n;
  697.    if(!this->audio_index) { 
  698.        return MP_RESULT_ERROR; 
  699.    }
  700.    if(bytes < 0) 
  701.    bytes = 0;
  702.    n0 = 0;
  703.    n1 = this->audio_chunks;
  704.    while(n0 < n1 - 1)
  705.    {
  706.       n = (n0 + n1) / 2;
  707.       if(this->audio_index[n].tot > bytes)
  708.          n1 = n;
  709.       else
  710.          n0 = n;
  711.    }
  712.    this->audio_posc = n0;
  713.    if(this->audio_index[n0].len > 1000) {
  714.  this->audio_posb = bytes - this->audio_index[n0].tot;
  715.    }
  716.    else {
  717.      this->audio_posb = 0;
  718.    }
  719.    return MP_RESULT_OK;
  720. }
  721. MP_RESULT     MediaDecapsAVI::SeekVideo(unsigned int StreamId, long frame)
  722. {
  723. if(!this->video_index) {
  724. return MP_RESULT_ERROR; 
  725.     }
  726. if (frame < 0 ) {
  727. frame = 0;
  728. }
  729.    this->video_pos = frame;
  730.    return MP_RESULT_OK;
  731. }
  732. MP_RESULT     MediaDecapsAVI::ReSeekAudio(unsigned int StreamId)
  733. {
  734. double ratio;
  735. long audio_bytes;
  736.     if(this->GetNumberOfAudioStreams() > 0) {
  737.   WaitForSingleObject(this->hIOMutex, INFINITE);
  738.       ratio = (double) ((double) this->video_pos / (double) this->video_frames);
  739.       
  740.       audio_bytes  = (long) (ratio * this->audio_bytes);
  741.       audio_bytes  -= (audio_bytes % this->waveformatex.nBlockSize);
  742.       this->SeekAudio(StreamId, audio_bytes);
  743.       ReleaseMutex(this->hIOMutex);
  744. }
  745.     return MP_RESULT_OK;
  746. }
  747. MP_RESULT     MediaDecapsAVI::Seek(unsigned int videoStreamId, unsigned int audioStreamId, int percent)
  748. {
  749. long frame;
  750. double ratio;
  751. long audio_bytes;
  752.   
  753. WaitForSingleObject(this->hIOMutex, INFINITE);
  754.     frame = (long) (percent * this->video_frames / 100);
  755.  
  756.   
  757.     while(!this->isKeyframe(frame) && frame < this->video_frames) {
  758.       frame++;
  759.     }
  760. if(frame >= this->video_frames)
  761. frame = 0;
  762.     
  763. this->SeekVideo(videoStreamId, frame);
  764.     if(this->GetNumberOfAudioStreams() > 0) {
  765.       
  766.       ratio = (double) ((double) frame / (double) this->video_frames);
  767.       
  768.  
  769.       audio_bytes  = (long) (ratio * this->audio_bytes);
  770.       audio_bytes  -= (audio_bytes % this->waveformatex.nBlockSize);
  771.       this->SeekAudio(audioStreamId, audio_bytes);
  772.       ReleaseMutex(this->hIOMutex);
  773.       return MP_RESULT_OK;
  774. }
  775.     ReleaseMutex(this->hIOMutex);
  776. return MP_RESULT_OK;
  777. }
  778. MP_RESULT     MediaDecapsAVI::Rewind(unsigned int videoStreamId, unsigned int audioStreamId)
  779. {
  780. this->video_pos  = 0;
  781. this->audio_posc = 0;
  782. this->audio_posb = 0;
  783. return MP_RESULT_OK;
  784. }
  785. MP_RESULT     MediaDecapsAVI::SeekNextKeyFrame(unsigned int StreamId)
  786. {
  787. WaitForSingleObject(this->hIOMutex, INFINITE);
  788. this->video_pos++;
  789. while(!isKeyframe(this->video_pos) && this->video_pos < this->video_frames)
  790. this->video_pos++;
  791.     ReleaseMutex(this->hIOMutex);
  792. return MP_RESULT_OK;
  793. }
  794. MP_RESULT     MediaDecapsAVI::SeekPreviousKeyFrame(unsigned int StreamId)
  795. {
  796. WaitForSingleObject(this->hIOMutex, INFINITE);
  797. if(this->video_pos > 1) {
  798. this->video_pos--;
  799. this->video_pos--;
  800. }
  801. while(!isKeyframe(this->video_pos) && this->video_pos > 0)
  802. this->video_pos--;
  803.     ReleaseMutex(this->hIOMutex);
  804. return MP_RESULT_OK;
  805. }