quicktime.c
上传用户:luping1608
上传日期:2007-01-06
资源大小:38k
文件大小:22k
源码类别:

多媒体

开发平台:

Unix_Linux

  1. #include "quicktime.h"
  2. int quicktime_check_sig(char *path)
  3. {
  4. quicktime_t file;
  5. quicktime_atom_t leaf_atom;
  6. int result1 = 0, result2 = 0;
  7. if(!(file.stream = fopen(path, "rb"))) 
  8. {
  9. perror("quicktime_check_sig");
  10. return 0;
  11. }
  12. fseek(file.stream, 0, SEEK_END);
  13. file.total_length = ftell(file.stream);
  14. fseek(file.stream, 0, SEEK_SET);
  15. do
  16. {
  17. result1 = quicktime_atom_read_header(file.stream, &leaf_atom);
  18. if(!result1)
  19. {
  20. // just want the "moov" atom
  21. if(quicktime_atom_is(&leaf_atom, "moov"))
  22. {
  23. result2 = 1;
  24. }
  25. else
  26. quicktime_atom_skip(&file, &leaf_atom);
  27. }
  28. }while(!result1 && !result2 && quicktime_position(&file) < file.total_length);
  29. fclose(file.stream);
  30. return result2;
  31. }
  32. int quicktime_make_streamable(char *path)
  33. {
  34. quicktime_t file, *old_file, new_file;
  35. int moov_exists = 0, mdat_exists = 0, result, atoms = 1;
  36. long mdat_start, mdat_size;
  37. quicktime_atom_t leaf_atom;
  38. long moov_length;
  39. // find the moov atom in the old file
  40. if(!(file.stream = fopen(path, "rb")))
  41. {
  42. perror("quicktime_make_streamable");
  43. return 1;
  44. }
  45. fseek(file.stream, 0, SEEK_END);
  46. file.total_length = ftell(file.stream);
  47. fseek(file.stream, 0, SEEK_SET);
  48. // get the locations of moov and mdat atoms
  49. do
  50. {
  51. //printf("%xn", quicktime_position(&file));
  52. result = quicktime_atom_read_header(file.stream, &leaf_atom);
  53. if(!result)
  54. {
  55. if(quicktime_atom_is(&leaf_atom, "moov"))
  56. {
  57. moov_exists = atoms;
  58. moov_length = leaf_atom.size;
  59. }
  60. else
  61. if(quicktime_atom_is(&leaf_atom, "mdat"))
  62. {
  63. mdat_start = quicktime_position(&file) - HEADER_LENGTH;
  64. mdat_size = leaf_atom.size;
  65. mdat_exists = atoms;
  66. }
  67. quicktime_atom_skip(&file, &leaf_atom);
  68. atoms++;
  69. }
  70. }while(!result && quicktime_position(&file) < file.total_length);
  71. fclose(file.stream);
  72. if(!moov_exists)
  73. {
  74. printf("quicktime_make_streamable: no moov atomn");
  75. return 1;
  76. }
  77. if(!mdat_exists)
  78. {
  79. printf("quicktime_make_streamable: no mdat atomn");
  80. return 1;
  81. }
  82. // copy the old file to the new file
  83. if(moov_exists && mdat_exists)
  84. {
  85. // moov wasn't the first atom
  86. if(moov_exists > 1)
  87. {
  88. char *buffer;
  89. long buf_size = 1000000;
  90. char temp_path[1024];
  91. sprintf(temp_path, "%sx", path);
  92. result = 0;
  93. // read the header proper
  94. if(!(old_file = quicktime_open(path, 1, 0)))
  95. {
  96. return 1;
  97. }
  98. quicktime_shift_offsets(&(old_file->moov), moov_length);
  99. // open the output file
  100. if(!(new_file.stream = fopen(temp_path, "wb")))
  101. {
  102. perror("quicktime_make_streamable");
  103. result =  1;
  104. }
  105. else
  106. {
  107. // set up some flags
  108. new_file.wr = 1;
  109. new_file.rd = 0;
  110. quicktime_write_moov(&new_file, &(old_file->moov));
  111. quicktime_set_position(old_file, mdat_start);
  112. if(!(buffer = malloc(buf_size)))
  113. {
  114. result = 1;
  115. printf("quicktime_make_streamable: out of memoryn");
  116. }
  117. else
  118. {
  119. while(quicktime_position(old_file) < mdat_start + mdat_size && !result)
  120. {
  121. if(quicktime_position(old_file) + buf_size > mdat_start + mdat_size)
  122. buf_size = mdat_start + mdat_size - quicktime_position(old_file);
  123. if(!quicktime_read_data(old_file, buffer, buf_size)) result = 1;
  124. if(!result)
  125. {
  126. if(!quicktime_write_data(&new_file, buffer, buf_size)) result = 1;
  127. }
  128. }
  129. free(buffer);
  130. }
  131. fclose(new_file.stream);
  132. if(result)
  133. {
  134. remove(temp_path);
  135. }
  136. }
  137. quicktime_close(old_file);
  138. if(!result)
  139. {
  140. if(remove(path)) perror("quicktime_make_streamable");
  141. if(rename(temp_path, path)) perror("quicktime_make_streamable");
  142. }
  143. }
  144. else
  145. {
  146. printf("quicktime_make_streamable: header already at 0 offsetn");
  147. return 0;
  148. }
  149. }
  150. return 0;
  151. }
  152. int quicktime_video_tracks(quicktime_t *file)
  153. {
  154. int i, result = 0;
  155. for(i = 0; i < file->moov.total_tracks; i++)
  156. {
  157. if(file->moov.trak[i]->mdia.minf.is_video) result++;
  158. }
  159. return result;
  160. }
  161. int quicktime_audio_tracks(quicktime_t *file)
  162. {
  163. int i, result = 0;
  164. quicktime_minf_t *minf;
  165. for(i = 0; i < file->moov.total_tracks; i++)
  166. {
  167. minf = &(file->moov.trak[i]->mdia.minf);
  168. if(minf->is_audio)
  169. result++;
  170. }
  171. return result;
  172. }
  173. int quicktime_set_audio(quicktime_t *file, 
  174. int channels,
  175. long sample_rate,
  176. int bits,
  177. char *compressor)
  178. {
  179. quicktime_trak_t *trak;
  180. // allocate an arbitrary number of tracks
  181. if(channels)
  182. {
  183. // Fake the bits parameter for some formats.
  184. if(quicktime_match_32(compressor, QUICKTIME_ULAW) ||
  185. quicktime_match_32(compressor, QUICKTIME_IMA4)) bits = 16;
  186. file->atracks = (quicktime_audio_map_t*)malloc(sizeof(quicktime_audio_map_t));
  187. trak = quicktime_add_track(&(file->moov));
  188. quicktime_trak_init_audio(file, trak, channels, sample_rate, bits, compressor);
  189. quicktime_init_audio_map(&(file->atracks[0]), trak);
  190. file->atracks[file->total_atracks].track = trak;
  191. file->atracks[file->total_atracks].channels = channels;
  192. file->atracks[file->total_atracks].current_position = 0;
  193. file->atracks[file->total_atracks].current_chunk = 1;
  194. file->total_atracks++;
  195. }
  196. return 1;   // Return the number of tracks created
  197. }
  198. int quicktime_set_video(quicktime_t *file, 
  199. int tracks, 
  200. int frame_w, 
  201. int frame_h,
  202. float frame_rate,
  203. char *compressor)
  204. {
  205. int i;
  206. quicktime_trak_t *trak;
  207. if(tracks)
  208. {
  209. quicktime_mhvd_init_video(file, &(file->moov.mvhd), frame_rate);
  210. file->total_vtracks = tracks;
  211. file->vtracks = (quicktime_video_map_t*)malloc(sizeof(quicktime_video_map_t) * file->total_vtracks);
  212. for(i = 0; i < tracks; i++)
  213. {
  214. trak = quicktime_add_track(&(file->moov));
  215. quicktime_trak_init_video(file, trak, frame_w, frame_h, frame_rate, compressor);
  216. quicktime_init_video_map(&(file->vtracks[i]), trak);
  217. }
  218. }
  219. return 0;
  220. }
  221. quicktime_trak_t* quicktime_add_track(quicktime_moov_t *moov)
  222. {
  223. quicktime_trak_t *trak;
  224. trak = moov->trak[moov->total_tracks] = malloc(sizeof(quicktime_trak_t));
  225. quicktime_trak_init(trak);
  226. trak->tkhd.track_id = moov->mvhd.next_track_id;
  227. moov->mvhd.next_track_id++;
  228. moov->total_tracks++;
  229. return trak;
  230. }
  231. int quicktime_init(quicktime_t *file)
  232. {
  233. quicktime_mdat_init(&(file->mdat));
  234. quicktime_moov_init(&(file->moov));
  235. file->total_atracks = 0;
  236. file->total_vtracks = 0;
  237. file->atracks = 0;
  238. file->vtracks = 0;
  239. return 0;
  240. }
  241. int quicktime_delete(quicktime_t *file)
  242. {
  243. int i;
  244. if(file->total_atracks) 
  245. {
  246. for(i = 0; i < file->total_atracks; i++)
  247. quicktime_delete_audio_map(&(file->atracks[i]));
  248. free(file->atracks);
  249. }
  250. if(file->total_vtracks)
  251. {
  252. for(i = 0; i < file->total_vtracks; i++)
  253. quicktime_delete_video_map(&(file->vtracks[i]));
  254. free(file->vtracks);
  255. }
  256. file->total_atracks = 0;
  257. file->total_vtracks = 0;
  258. quicktime_moov_delete(&(file->moov));
  259. quicktime_mdat_delete(&(file->mdat));
  260. return 0;
  261. }
  262. int quicktime_get_timescale(float frame_rate)
  263. {
  264. int timescale = 600;
  265. if((600 / frame_rate) - (int)(600 / frame_rate) != 0) timescale = 100 * frame_rate;
  266. return timescale;
  267. }
  268. int quicktime_seek_end(quicktime_t *file)
  269. {
  270. quicktime_set_position(file, file->mdat.size + file->mdat.start);
  271. quicktime_update_positions(file);
  272. return 0;
  273. }
  274. int quicktime_seek_start(quicktime_t *file)
  275. {
  276. quicktime_set_position(file, file->mdat.start + HEADER_LENGTH);
  277. quicktime_update_positions(file);
  278. return 0;
  279. }
  280. long quicktime_audio_length(quicktime_t *file, int track)
  281. {
  282. if(file->total_atracks > 0) 
  283. return quicktime_track_samples(file, file->atracks[track].track);
  284. return 0;
  285. }
  286. long quicktime_video_length(quicktime_t *file, int track)
  287. {
  288. //printf("quicktime_video_length %d %dn", quicktime_track_samples(file, file->vtracks[track].track), track);
  289. if(file->total_vtracks > 0)
  290. return quicktime_track_samples(file, file->vtracks[track].track);
  291. return 0;
  292. }
  293. long quicktime_audio_position(quicktime_t *file, int track)
  294. {
  295. return file->atracks[track].current_position;
  296. }
  297. long quicktime_video_position(quicktime_t *file, int track)
  298. {
  299. return file->vtracks[track].current_position;
  300. }
  301. int quicktime_update_positions(quicktime_t *file)
  302. {
  303. // Used for routines that change the positions of all tracks, like
  304. // seek_end and seek_start but not for routines that reposition one track, like
  305. // set_audio_position.
  306. long mdat_offset = quicktime_position(file) - file->mdat.start;
  307. long sample, chunk, chunk_offset;
  308. int i;
  309. if(file->total_atracks)
  310. {
  311. sample = quicktime_offset_to_sample(file->atracks[0].track, mdat_offset);
  312. chunk = quicktime_offset_to_chunk(&chunk_offset, file->atracks[0].track, mdat_offset);
  313. for(i = 0; i < file->total_atracks; i++)
  314. {
  315. file->atracks[i].current_position = sample;
  316. file->atracks[i].current_chunk = chunk;
  317. }
  318. }
  319. if(file->total_vtracks)
  320. {
  321. sample = quicktime_offset_to_sample(file->vtracks[0].track, mdat_offset);
  322. chunk = quicktime_offset_to_chunk(&chunk_offset, file->vtracks[0].track, mdat_offset);
  323. for(i = 0; i < file->total_vtracks; i++)
  324. {
  325. file->vtracks[i].current_position = sample;
  326. file->vtracks[i].current_chunk = chunk;
  327. }
  328. }
  329. return 0;
  330. }
  331. int quicktime_set_audio_position(quicktime_t *file, long sample, int track)
  332. {
  333. long offset;
  334. quicktime_trak_t *trak;
  335. if(file->total_atracks)
  336. {
  337. trak = file->atracks[track].track;
  338. file->atracks[track].current_position = sample;
  339. offset = quicktime_sample_to_offset(trak, sample);
  340. quicktime_set_position(file, offset);
  341. //quicktime_update_positions(file);
  342. }
  343. //printf("quicktime_set_audio_position sample %d offset %dn", sample, quicktime_position(file));
  344. return 0;
  345. }
  346. int quicktime_set_video_position(quicktime_t *file, long frame, int track)
  347. {
  348. long offset;
  349. quicktime_trak_t *trak;
  350. if(file->total_vtracks)
  351. {
  352. trak = file->vtracks[track].track;
  353. file->vtracks[track].current_position = frame;
  354. offset = quicktime_sample_to_offset(trak, frame);
  355. quicktime_set_position(file, offset);
  356. //quicktime_update_positions(file);
  357. }
  358. return 0;
  359. }
  360. int quicktime_has_audio(quicktime_t *file)
  361. {
  362. if(quicktime_audio_tracks(file)) return 1;
  363. return 0;
  364. }
  365. long quicktime_sample_rate(quicktime_t *file, int track)
  366. {
  367. if(file->total_atracks)
  368. return file->atracks[track].track->mdia.minf.stbl.stsd.table[0].sample_rate;
  369. return 0;
  370. }
  371. int quicktime_audio_bits(quicktime_t *file, int track)
  372. {
  373. //printf("quicktime_audio_bits %x %dn", file->atracks[track].track, file->total_atracks);
  374. if(file->total_atracks)
  375. return file->atracks[track].track->mdia.minf.stbl.stsd.table[0].sample_size;
  376. return 0;
  377. }
  378. char* quicktime_audio_compressor(quicktime_t *file, int track)
  379. {
  380. return file->atracks[track].track->mdia.minf.stbl.stsd.table[0].format;
  381. }
  382. int quicktime_track_channels(quicktime_t *file, int track)
  383. {
  384. if(track < file->total_atracks)
  385. return file->atracks[track].channels;
  386. return 0;
  387. }
  388. int quicktime_channel_location(quicktime_t *file, int *quicktime_track, int *quicktime_channel, int channel)
  389. {
  390. *quicktime_track = channel / 2;
  391. *quicktime_channel = channel - *quicktime_track * 2;
  392. return 0;
  393. }
  394. int quicktime_has_video(quicktime_t *file)
  395. {
  396. if(quicktime_video_tracks(file)) return 1;
  397. return 0;
  398. }
  399. int quicktime_video_width(quicktime_t *file, int track)
  400. {
  401. if(file->total_vtracks)
  402. return file->vtracks[track].track->tkhd.track_width;
  403. return 0;
  404. }
  405. int quicktime_video_height(quicktime_t *file, int track)
  406. {
  407. if(file->total_vtracks)
  408. return file->vtracks[track].track->tkhd.track_height;
  409. return 0;
  410. }
  411. float quicktime_frame_rate(quicktime_t *file, int track)
  412. {
  413. if(file->total_vtracks)
  414. return (float)file->vtracks[track].track->mdia.mdhd.time_scale / 
  415. file->vtracks[track].track->mdia.minf.stbl.stts.table[0].sample_duration;
  416. return 0;
  417. }
  418. char* quicktime_video_compressor(quicktime_t *file, int track)
  419. {
  420. return file->vtracks[track].track->mdia.minf.stbl.stsd.table[0].format;
  421. }
  422. int quicktime_write_audio(quicktime_t *file, char *audio_buffer, long samples, int track)
  423. {
  424. long offset;
  425. int result;
  426. long bytes;
  427. // write chunk for 1 track
  428. bytes = samples * quicktime_audio_bits(file, track) / 8 * file->atracks[track].channels;
  429. offset = quicktime_position(file);
  430. //printf("quicktime_write_audio %dn", quicktime_position(file), );
  431. result = quicktime_write_data(file, audio_buffer, bytes);
  432. //printf("quicktime_write_audio %d %xn", result, audio_buffer);
  433. if(result) result = 0; else result = 1; // defeat fwrite's return
  434. quicktime_update_tables(file->atracks[track].track, 
  435. offset, 
  436. file->atracks[track].current_chunk, 
  437. file->atracks[track].current_position, 
  438. samples, 
  439. 0);
  440. file->atracks[track].current_position += samples;
  441. file->atracks[track].current_chunk++;
  442. return result;
  443. }
  444. int quicktime_write_frame(quicktime_t *file, unsigned char *video_buffer, long bytes, int track)
  445. {
  446. long offset = quicktime_position(file);// - file->mdat.start;
  447. int result = 0;
  448. result = quicktime_write_data(file, video_buffer, bytes);
  449. if(result) result = 0; else result = 1;
  450. quicktime_update_tables(file->vtracks[track].track,
  451. offset,
  452. file->vtracks[track].current_chunk,
  453. file->vtracks[track].current_position,
  454. 1,
  455. bytes);
  456. file->vtracks[track].current_position += 1;
  457. file->vtracks[track].current_chunk++;
  458. return result;
  459. }
  460. FILE* quicktime_get_fd(quicktime_t *file)
  461. {
  462. return file->stream;
  463. }
  464. int quicktime_write_frame_init(quicktime_t *file, int track)
  465. {
  466. file->offset = quicktime_position(file);
  467. return 0;
  468. }
  469. int quicktime_write_frame_end(quicktime_t *file, int track)
  470. {
  471. long bytes = quicktime_position(file) - file->offset;
  472. quicktime_update_tables(file->vtracks[track].track,
  473. file->offset,
  474. file->vtracks[track].current_chunk,
  475. file->vtracks[track].current_position,
  476. 1,
  477. bytes);
  478. file->vtracks[track].current_position += 1;
  479. file->vtracks[track].current_chunk++;
  480. return 0;
  481. }
  482. int quicktime_write_audio_init(quicktime_t *file, int track)
  483. {
  484. return quicktime_write_frame_init(file, track);
  485. }
  486. int quicktime_write_audio_end(quicktime_t *file, int track, long samples)
  487. {
  488. long bytes = quicktime_position(file) - file->offset;
  489. quicktime_update_tables(file->atracks[track].track,
  490. file->offset,
  491. file->atracks[track].current_chunk,
  492. file->atracks[track].current_position,
  493. samples,
  494. bytes);
  495. file->atracks[track].current_position += samples;
  496. file->atracks[track].current_chunk++;
  497. return 0;
  498. }
  499. long quicktime_read_audio(quicktime_t *file, char *audio_buffer, long samples, int track)
  500. {
  501. long chunk_sample, chunk;
  502. int result = 1, track_num;
  503. quicktime_trak_t *trak = file->atracks[track].track;
  504. long fragment_len, chunk_end;
  505. long position = file->atracks[track].current_position;
  506. long start = position, end = position + samples;
  507. long bytes, total_bytes = 0;
  508. long buffer_offset;
  509. quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, position);
  510. buffer_offset = 0;
  511. while(position < end && result)
  512. {
  513. quicktime_set_audio_position(file, position, track);
  514. fragment_len = quicktime_chunk_samples(trak, chunk);
  515. chunk_end = chunk_sample + fragment_len;
  516. fragment_len -= position - chunk_sample;
  517. if(position + fragment_len > chunk_end) fragment_len = chunk_end - position;
  518. if(position + fragment_len > end) fragment_len = end - position;
  519. bytes = quicktime_samples_to_bytes(trak, fragment_len);
  520. result = quicktime_read_data(file, &audio_buffer[buffer_offset], bytes);
  521. total_bytes += bytes;
  522. position += fragment_len;
  523. chunk_sample = position;
  524. buffer_offset += bytes;
  525. chunk++;
  526. }
  527. file->atracks[track].current_position = position;
  528. if(!result) return 0;
  529. return total_bytes;
  530. }
  531. int quicktime_read_chunk(quicktime_t *file, char *output, int track, long chunk, long byte_start, long byte_len)
  532. {
  533. quicktime_set_position(file, quicktime_chunk_to_offset(file->atracks[track].track, chunk) + byte_start);
  534. if(quicktime_read_data(file, output, byte_len)) return 0;
  535. else
  536. return 1;
  537. }
  538. long quicktime_frame_size(quicktime_t *file, long frame, int track)
  539. {
  540. int bytes;
  541. quicktime_trak_t *trak = file->vtracks[track].track;
  542. if(trak->mdia.minf.stbl.stsz.sample_size)
  543. {
  544. bytes = trak->mdia.minf.stbl.stsz.sample_size;
  545. }
  546. else
  547. {
  548. bytes = trak->mdia.minf.stbl.stsz.table[frame].size;
  549. }
  550. return bytes;
  551. }
  552. long quicktime_read_frame(quicktime_t *file, unsigned char *video_buffer, int track)
  553. {
  554. long bytes;
  555. int result = 0;
  556. quicktime_trak_t *trak = file->vtracks[track].track;
  557. bytes = quicktime_frame_size(file, file->vtracks[track].current_position, track);
  558. if(!file->vtracks[track].frames_cached)
  559. {
  560. quicktime_set_video_position(file, file->vtracks[track].current_position, track);
  561. result = quicktime_read_data(file, video_buffer, bytes);
  562. }
  563. else
  564. {
  565. int i;
  566. unsigned char *cached_frame;
  567. if(file->vtracks[track].current_position >= file->vtracks[track].frames_cached) result = 1;
  568. if(!result)
  569. {
  570. cached_frame = file->vtracks[track].frame_cache[file->vtracks[track].current_position];
  571. for(i = 0; i < bytes; i++)
  572. video_buffer[i] = cached_frame[i];
  573. }
  574. }
  575. file->vtracks[track].current_position++;
  576. if(!result) return 0;
  577. return bytes;
  578. }
  579. int quicktime_read_frame_init(quicktime_t *file, int track)
  580. {
  581. quicktime_trak_t *trak = file->vtracks[track].track;
  582. quicktime_set_video_position(file, file->vtracks[track].current_position, track);
  583. return 0;
  584. }
  585. int quicktime_read_frame_end(quicktime_t *file, int track)
  586. {
  587. file->vtracks[track].current_position++;
  588. return 0;
  589. }
  590. int quicktime_cache_frames(quicktime_t *file, int track)
  591. {
  592. long i = 0;
  593. int result = 0;
  594. long size;
  595. long total_frames;
  596. if(track > file->total_vtracks) return 1;    // out of range
  597. if(file->vtracks[track].frames_cached) return 1; // already cached
  598. total_frames = quicktime_video_length(file, track);
  599. file->vtracks[track].frame_cache = malloc(sizeof(unsigned char*) * total_frames);
  600. if(!file->vtracks[track].frame_cache) result = 1;
  601. if(!result) quicktime_set_video_position(file, 0, track);
  602. // read the frames
  603. for(i = 0; i < total_frames && !result; i++)
  604. {
  605. size = quicktime_frame_size(file, i, 0);
  606. file->vtracks[track].frame_cache[i] = malloc(size);
  607. if(!file->vtracks[track].frame_cache[i])
  608. {
  609. perror("quicktime_cache_frames");
  610. result = 1;
  611. }
  612. if(!result)
  613. {
  614. result = quicktime_read_frame(file, 
  615. (unsigned char*)file->vtracks[track].frame_cache[i], 
  616. track);
  617. if(result) result = 0; 
  618. else 
  619. {
  620. perror("quicktime_cache_frames");
  621. result = 1;
  622. }
  623. }
  624. }
  625. // don't want to fool quicktime_read_frame so only set this here
  626. file->vtracks[track].frames_cached = total_frames;
  627. // back out
  628. if(result)
  629. {
  630. for(i -= 2; i >= 0; i--)
  631. {
  632. free(file->vtracks[track].frame_cache[i]);
  633. }
  634. if(file->vtracks[track].frame_cache)
  635. free(file->vtracks[track].frame_cache);
  636. file->vtracks[track].frames_cached = 0;
  637. file->vtracks[track].frame_cache = 0;
  638. }
  639. return result;
  640. }
  641. int quicktime_init_video_map(quicktime_video_map_t *vtrack, quicktime_trak_t *trak)
  642. {
  643. vtrack->track = trak;
  644. vtrack->current_position = 0;
  645. vtrack->current_chunk = 1;
  646. vtrack->frame_cache = 0;
  647. vtrack->frames_cached = 0;
  648. quicktime_init_vcodecs(vtrack);
  649. return 0;
  650. }
  651. int quicktime_delete_video_map(quicktime_video_map_t *vtrack)
  652. {
  653. int i;
  654. if(vtrack->frames_cached)
  655. {
  656. for(i = 0; i < vtrack->frames_cached; i++)
  657. {
  658. free(vtrack->frame_cache[i]);
  659. }
  660. free(vtrack->frame_cache);
  661. vtrack->frames_cached = 0;
  662. }
  663. quicktime_delete_vcodecs(vtrack);
  664. return 0;
  665. }
  666. int quicktime_init_audio_map(quicktime_audio_map_t *atrack, quicktime_trak_t *trak)
  667. {
  668. atrack->track = trak;
  669. atrack->channels = trak->mdia.minf.stbl.stsd.table[0].channels;
  670. atrack->current_position = 0;
  671. atrack->current_chunk = 1;
  672. quicktime_init_acodecs(atrack);
  673. return 0;
  674. }
  675. int quicktime_delete_audio_map(quicktime_audio_map_t *atrack)
  676. {
  677. int i;
  678. quicktime_delete_acodecs(atrack);
  679. return 0;
  680. }
  681. int quicktime_read_info(quicktime_t *file)
  682. {
  683. int result1 = 0, result2 = 0;
  684. int i, channel, trak_channel, track;
  685. long start_position = ftell(file->stream);
  686. quicktime_atom_t leaf_atom;
  687. quicktime_trak_t *trak;
  688. // search the entire file for info
  689. fseek(file->stream, 0, SEEK_SET);
  690. do
  691. {
  692. result1 = quicktime_atom_read_header(file->stream, &leaf_atom);
  693. if(!result1)
  694. {
  695. if(quicktime_atom_is(&leaf_atom, "mdat")) 
  696. {
  697. quicktime_read_mdat(file, &(file->mdat), &leaf_atom);
  698. }
  699. else
  700. if(quicktime_atom_is(&leaf_atom, "moov")) 
  701. {
  702. quicktime_read_moov(file, &(file->moov), &leaf_atom);
  703. result2 = 1;
  704. }
  705. else
  706. quicktime_atom_skip(file, &leaf_atom);
  707. }
  708. }while(!result1 && quicktime_position(file) < file->total_length);
  709. // go back to the original position
  710. fseek(file->stream, start_position, SEEK_SET);
  711. if(result2)
  712. {
  713. // get tables for all the different tracks
  714. file->total_atracks = quicktime_audio_tracks(file);
  715. file->atracks = (quicktime_audio_map_t*)malloc(sizeof(quicktime_audio_map_t) * file->total_atracks);
  716. for(i = 0, track = 0; i < file->total_atracks; i++)
  717. {
  718. while(!file->moov.trak[track]->mdia.minf.is_audio)
  719. track++;
  720. //printf("quicktime_read_info %x %xn", file, &(file->atracks[i]));
  721. quicktime_init_audio_map(&(file->atracks[i]), file->moov.trak[track]);
  722. }
  723. file->total_vtracks = quicktime_video_tracks(file);
  724. file->vtracks = (quicktime_video_map_t*)malloc(sizeof(quicktime_video_map_t) * file->total_vtracks);
  725. for(track = 0, i = 0; i < file->total_vtracks; i++)
  726. {
  727. while(!file->moov.trak[track]->mdia.minf.is_video)
  728. track++;
  729. quicktime_init_video_map(&(file->vtracks[i]), file->moov.trak[track]);
  730. }
  731. }
  732. //printf("n");
  733. if(result2) return 0; else return 1;
  734. }
  735. quicktime_t* quicktime_open(char *filename, int rd, int wr)
  736. {
  737. quicktime_t *new_file = malloc(sizeof(quicktime_t));
  738. char flags[10];
  739. int exists = 0;
  740. quicktime_init(new_file);
  741. new_file->wr = wr;
  742. new_file->rd = rd;
  743. new_file->mdat.start = 0;
  744. if(rd && (new_file->stream = fopen(filename, "rb")))
  745. { exists = 1; fclose(new_file->stream); }
  746. if(rd && !wr) sprintf(flags, "rb");
  747. else
  748. if(!rd && wr) sprintf(flags, "wb");
  749. else
  750. if(rd && wr)
  751. {
  752. if(exists) sprintf(flags, "rb+");
  753. else
  754. sprintf(flags, "wb+");
  755. }
  756. //printf("%s %s %xn", filename, flags, new_file);
  757. if(!(new_file->stream = fopen(filename, flags)))
  758. {
  759. perror("quicktime_open");
  760. free(new_file);
  761. return 0;
  762. }
  763. if(rd && exists)
  764. {
  765. fseek(new_file->stream, 0, SEEK_END);
  766. new_file->total_length = ftell(new_file->stream);
  767. fseek(new_file->stream, 0, SEEK_SET);
  768. if(quicktime_read_info(new_file))
  769. {
  770. quicktime_close(new_file);
  771. new_file = 0;
  772. }
  773. }
  774. if(wr)
  775. if(!exists)
  776. {
  777. // start the data atom
  778. // also don't want to do this if making a streamable file
  779. quicktime_write_fixed32(new_file, 0);
  780. quicktime_write_char32(new_file, "mdat");
  781. }
  782. return new_file;
  783. }
  784. int quicktime_close(quicktime_t *file)
  785. {
  786. int result;
  787. if(file->wr)
  788. {
  789. quicktime_write_mdat(file, &(file->mdat));
  790. quicktime_write_moov(file, &(file->moov));
  791. //quicktime_dump(file);
  792. }
  793. result = fclose(file->stream);
  794. quicktime_delete(file);
  795. free(file);
  796. return result;
  797. }
  798. int quicktime_dump(quicktime_t *file)
  799. {
  800. printf("quicktime_dumpn");
  801. printf("movie datan");
  802. printf(" size %ldn", file->mdat.size);
  803. printf(" start %ldn", file->mdat.start);
  804. quicktime_moov_dump(&(file->moov));
  805. return 0;
  806. }