mpeg3vtrack.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:13k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. #include "libmpeg3.h"
  2. #include "mpeg3private.h"
  3. #include "mpeg3protos.h"
  4. #include "mpeg3vtrack.h"
  5. #include "video/mpeg3video.h"
  6. #include "video/mpeg3videoprotos.h"
  7. #include "mp4av.h"
  8. #include <stdlib.h>
  9. void mpeg3vtrack_cleanup_frame (mpeg3_vtrack_t *track)
  10. {
  11.   long size;
  12.   if (track->track_frame_buffer == NULL) return;
  13.   size = track->track_frame_buffer_size;
  14.   track->track_frame_buffer[0] = track->track_frame_buffer[size - 4];
  15.   track->track_frame_buffer[1] = track->track_frame_buffer[size - 3];
  16.   track->track_frame_buffer[2] = track->track_frame_buffer[size - 2];
  17.   track->track_frame_buffer[3] = track->track_frame_buffer[size - 1];
  18. #if 0
  19.   printf("Clean up - code is %x %x %x %xn",
  20.  track->track_frame_buffer[0],
  21.  track->track_frame_buffer[1],
  22.  track->track_frame_buffer[2],
  23.  track->track_frame_buffer[3]);
  24. #endif
  25.   track->track_frame_buffer_size = 4;
  26. }
  27. static 
  28. int mpeg3vtrack_locate_frame (mpeg3_vtrack_t *track,
  29.     long frame)
  30. {
  31.   mpeg3_demuxer_t *demux;
  32.   long start_frame;
  33.   uint32_t offset;
  34.   uint32_t code = 0;
  35.   demux = track->demuxer;
  36.   if (frame < track->current_position) {
  37.     mpeg3demux_seek_start(demux);
  38.     start_frame = 0;
  39.   } else
  40.     start_frame = track->current_position;
  41.   // clean out last frame
  42.   while (!mpeg3demux_eof(demux)) {
  43.     mpeg3vtrack_cleanup_frame(track);
  44.     offset = 4;
  45.     track->track_frame_buffer_size = 
  46.     mpeg3demux_read_data(demux,
  47.  track->track_frame_buffer,
  48.  track->track_frame_buffer_maxsize);
  49.     for (offset = 4, code = 0; offset < track->track_frame_buffer_size - 3; offset++) {
  50.       code <<= 8;
  51.       code |= track->track_frame_buffer[offset];
  52.       if (code == MPEG3_PICTURE_START_CODE) {
  53. start_frame++;
  54. if (start_frame >= frame) {
  55.   for (offset = offset - 3; 
  56.        offset < track->track_frame_buffer_size; 
  57.        offset++) {
  58.     mpeg3demux_read_prev_char(demux);
  59.   }
  60.   track->track_frame_buffer_size = 0;
  61.   track->current_position = frame;
  62.   return 0;
  63. }
  64.       }
  65.     }
  66.   }
  67.   return 1;
  68. }
  69.   
  70.   
  71.     
  72. static
  73. int mpeg3vtrack_get_frame (mpeg3_vtrack_t *track)
  74. {
  75. u_int32_t code = 0;
  76. int have_pict_start, done;
  77. mpeg3_demuxer_t *demux = track->demuxer;
  78. unsigned char *output;
  79. have_pict_start = 0;
  80. track->current_position++;
  81. output = track->track_frame_buffer;
  82. if ((track->track_frame_buffer_size != 0) &&
  83.     output[0] == 0 && output[1] == 0 && output[2] == 1) {
  84.   if (output[3] == 0)
  85.       have_pict_start = 1;
  86.     output += 4;
  87. done = 0;
  88. while(done == 0 && 
  89. code != MPEG3_SEQUENCE_END_CODE &&
  90. !mpeg3demux_eof(demux))
  91. {
  92.   if (track->track_frame_buffer_size + 3 >= 
  93.       track->track_frame_buffer_maxsize) {
  94.     int diff = output - track->track_frame_buffer;
  95.     track->track_frame_buffer_maxsize += 4096;
  96.     track->track_frame_buffer = 
  97.       realloc(track->track_frame_buffer, 
  98.       track->track_frame_buffer_maxsize);
  99.     if (track->track_frame_buffer == NULL) exit(1);
  100.     output = track->track_frame_buffer + diff;
  101.   }
  102.   
  103.   code <<= 8;
  104.   // can't do this yet - we're still reading from the demuxer...
  105.   *output = mpeg3demux_read_char(track->demuxer);
  106.   code |= *output++;
  107.   //   printf("%d %08xn", track->track_frame_buffer_size, code);
  108.   track->track_frame_buffer_size++;
  109.   if (code == MPEG3_PICTURE_START_CODE) {
  110.     if (have_pict_start == 1) done = 1;
  111.     have_pict_start = 1;
  112.   } else if ((code == MPEG3_GOP_START_CODE) ||
  113.      (code == MPEG3_SEQUENCE_START_CODE)) {
  114.     if (have_pict_start == 1) done = 1;
  115.   }
  116. }
  117. return mpeg3demux_eof(demux);
  118. }
  119. /* Line up on the beginning of the previous code. */
  120. int mpeg3vtrack_prev_code(mpeg3_demuxer_t* demux, uint32_t code)
  121. {
  122.   uint32_t testcode = 0;
  123.   int bytes = 0;
  124.   if (mpeg3demux_bof(demux)) return mpeg3demux_bof(demux);
  125.   do {
  126.     testcode >>= 8;
  127.     testcode |= (mpeg3demux_read_prev_char(demux) << 24);
  128.     bytes++;
  129.   } while(!mpeg3demux_bof(demux) && testcode != code);
  130.   return mpeg3demux_bof(demux);
  131. }
  132. // Must perform seeking now to get timecode for audio
  133. int mpeg3vtrack_seek_percentage(mpeg3_vtrack_t *vtrack, double percentage)
  134. {
  135.   vtrack->percentage_seek = percentage;
  136.   return 0;
  137. }
  138. int mpeg3vtrack_seek_frame(mpeg3_vtrack_t *vtrack, long frame)
  139. {
  140.   vtrack->frame_seek = frame;
  141.   return 0;
  142. }
  143. int mpeg3vtrack_seek(mpeg3_vtrack_t *track, int dont_decode)
  144. {
  145.   long this_gop_start;
  146.   int result = 0;
  147.   int back_step;
  148.   int attempts;
  149.   mpeg3_t *file = track->file;
  150.   int is_video_stream = file->is_video_stream;
  151.   double percentage;
  152.   long frame_number;
  153.   int match_refframes = 1;
  154.   mpeg3_demuxer_t *demux = track->demuxer;
  155.   int ix;
  156.   // Must do seeking here so files which don't use video don't seek.
  157.   /* Seek to percentage */
  158.   if(track->percentage_seek >= 0)
  159.     {
  160.       //printf("mpeg3video_seek 1 %fn", video->percentage_seek);
  161.       track->track_frame_buffer_size = 0;
  162.       percentage = track->percentage_seek;
  163.       track->percentage_seek = -1;
  164.       mpeg3demux_seek_percentage(track->demuxer, percentage);
  165.       printf("Seek time is %gn", mpeg3demux_get_time(track->demuxer));
  166.     }
  167.   else
  168.     /* Seek to a frame */
  169.     if(track->frame_seek >= 0)
  170.       {
  171. frame_number = track->frame_seek;
  172. track->frame_seek = -1;
  173. if(frame_number < 0) frame_number = 0;
  174. if(frame_number > track->total_frames) 
  175.   frame_number = track->total_frames;
  176. //printf("mpeg3video_seek 1 %ld %ldn", frame_number, video->framenum);
  177. /* Seek to I frame in table of contents */
  178. if(track->frame_offsets)
  179.   {
  180.     int i;
  181.     for(i = track->total_keyframe_numbers - 1; i >= 0; i--)
  182.       {
  183. if(track->keyframe_numbers[i] <= frame_number)
  184.   {
  185.     int frame;
  186.     int title_number;
  187.     int64_t byte;
  188.     // Go 2 I-frames before current position
  189.     frame = track->keyframe_numbers[i];
  190.     title_number = (track->frame_offsets[frame] & 
  191.     0xff00000000000000) >> 56;
  192.     byte = track->frame_offsets[frame] & 
  193.       0xffffffffffffff;
  194.     mpeg3demux_open_title(demux, title_number);
  195.     mpeg3demux_seek_byte(demux, byte);
  196.     for (ix = frame; ix < frame_number; ix++) {
  197.       mpeg3vtrack_get_frame(track);
  198.     }
  199.     break;
  200.   }
  201.       }
  202.   }
  203. else
  204.   /* Seek to start of file */
  205.   {
  206.   if(frame_number < 16)
  207.     {
  208.       mpeg3demux_seek_start(demux);
  209.       for (ix = 0; ix < frame_number; ix++) {
  210. mpeg3vtrack_get_frame(track);
  211.       }
  212. #if 0
  213.       track->video->repeat_count = track->video->current_repeat = 0;
  214.       track->video->framenum = 0;
  215.       result = mpeg3vtrack_drop_frames(track, 
  216.        frame_number - video->framenum);
  217. #endif
  218.     }
  219.   else
  220.     {
  221.       /* Seek to an I frame. */
  222.   /* Elementary stream */
  223.   if(is_video_stream)
  224.     {
  225. #if 0
  226.       //mpeg3_t *file = video->file;
  227.       mpeg3_vtrack_t *track = video->track;
  228.       int64_t byte = (int64_t)((double)(mpeg3demuxer_total_bytes(vstream->demuxer) / 
  229. track->total_frames) * 
  230.        frame_number);
  231.       long minimum = 65535;
  232.       int done = 0;
  233.       //printf("seek elementary %dn", frame_number);
  234.       /* Get GOP just before frame */
  235.       do
  236. {
  237.   result = mpeg3demux_seek_byte(demux, byte);
  238.   if(!result) 
  239.     result = mpeg3vtrack_prev_code(demux, MPEG3_GOP_START_CODE);
  240.   mpeg3demux_read_char(demux);
  241.   if(!result) result = mpeg3video_getgophdr(video);
  242.   this_gop_start = mpeg3video_goptimecode_to_frame(video);
  243.   //printf("wanted %ld guessed %ld byte %ld result %dn", frame_number, this_gop_start, byte, result);
  244.   if(labs(this_gop_start - frame_number) >= labs(minimum)) 
  245.     done = 1;
  246.   else
  247.     {
  248.       minimum = this_gop_start - frame_number;
  249.       byte += (long)((float)(frame_number - this_gop_start) * 
  250.      (float)(mpeg3demuxer_total_bytes(vstream->demuxer) / 
  251.      track->total_frames));
  252.       if(byte < 0) byte = 0;
  253.     }
  254. }while(!result && !done);
  255.       //printf("wanted %d guessed %dn", frame_number, this_gop_start);
  256.       if(!result)
  257. {
  258.   video->framenum = this_gop_start;
  259.   result = mpeg3video_drop_frames(video, frame_number - video->framenum);
  260. }
  261. #endif
  262.     }
  263.   else
  264.     /* System stream */
  265.     {
  266.       mpeg3vtrack_locate_frame(track, frame_number);
  267. #if 0
  268.       mpeg3demux_seek_time(demux, ((double)frame_number) / track->frame_rate);
  269.       percentage = mpeg3demux_tell_percentage(demux);
  270. #endif
  271.       //printf("seek frame %ld percentage %f byte %ldn", frame_number, percentage, mpeg3bits_tell(vstream));
  272.     }
  273. }
  274.     }
  275.       }
  276.   return result;
  277. }
  278. int mpeg3vtrack_previous_frame(mpeg3_vtrack_t *vtrack)
  279. {
  280.   int ix;
  281.   if(mpeg3demux_tell_percentage(vtrack->demuxer) <= 0) return 1;
  282.   // Get one picture
  283.   mpeg3vtrack_prev_code(vtrack->demuxer, MPEG3_PICTURE_START_CODE);
  284.   for (ix = 0; ix < 4; ix++) {
  285.     mpeg3demux_read_prev_char(vtrack->demuxer);
  286.   }
  287.   if(mpeg3demux_bof(vtrack->demuxer)) 
  288.     mpeg3demux_seek_percentage(vtrack->demuxer, 0);
  289.   //  vtrack->video->repeat_count = 0;
  290.   return 0;
  291. }
  292. #if 0
  293. int mpeg3vtrack_drop_frames(mpeg3_vtrack_t *vtrack, long frames)
  294. {
  295.   int result = 0;
  296.   long frame_number = video->framenum + frames;
  297.   /* Read the selected number of frames and skip b-frames */
  298.   while(!result && frame_number > video->framenum)
  299.     {
  300.       result = mpeg3video_read_frame_backend(video, frame_number - video->framenum);
  301.     }
  302.   return result;
  303. }
  304. #endif
  305. /* ======================================================================= */
  306. /*                                    ENTRY POINTS */
  307. /* ======================================================================= */
  308. mpeg3_vtrack_t* mpeg3_new_vtrack(mpeg3_t *file, 
  309. int stream_id, 
  310. mpeg3_demuxer_t *demuxer,
  311. int number)
  312. {
  313.   uint32_t h,w;
  314.   double frame_rate;
  315. int result = 0;
  316. mpeg3_vtrack_t *new_vtrack;
  317. new_vtrack = calloc(1, sizeof(mpeg3_vtrack_t));
  318. new_vtrack->file = file;
  319. new_vtrack->demuxer = mpeg3_new_demuxer(file, 0, 1, stream_id);
  320. if(new_vtrack->demuxer) mpeg3demux_copy_titles(new_vtrack->demuxer, demuxer);
  321. new_vtrack->current_position = 0;
  322. new_vtrack->percentage_seek = -1;
  323. new_vtrack->frame_seek = -1;
  324. new_vtrack->track_frame_buffer = NULL;
  325. new_vtrack->track_frame_buffer_maxsize = 0;
  326. //printf("mpeg3_new_vtrack 1n");
  327. // Copy pointers
  328. if(file->frame_offsets)
  329. {
  330. new_vtrack->frame_offsets = file->frame_offsets[number];
  331. new_vtrack->total_frame_offsets = file->total_frame_offsets[number];
  332. new_vtrack->keyframe_numbers = file->keyframe_numbers[number];
  333. new_vtrack->total_keyframe_numbers = file->total_keyframe_numbers[number];
  334. }
  335. //printf("mpeg3_new_vtrack 1n");
  336. //printf("mpeg3_new_vtrack %llxn", mpeg3demux_tell(new_vtrack->demuxer));
  337. /* Get information about the track here. */
  338. if (mpeg3vtrack_get_frame(new_vtrack)) {
  339.   mpeg3_delete_vtrack(file, new_vtrack);
  340.   return NULL;
  341. }
  342. if (MP4AV_Mpeg3ParseSeqHdr(new_vtrack->track_frame_buffer, 
  343.    new_vtrack->track_frame_buffer_size, 
  344.    &h,
  345.    &w, 
  346.    &frame_rate) < 0) {
  347.   mpeg3_delete_vtrack(file, new_vtrack);
  348.   return NULL;
  349. }
  350. new_vtrack->frame_rate = frame_rate;
  351. new_vtrack->width = w;
  352. new_vtrack->height = h;
  353. mpeg3demux_seek_start(new_vtrack->demuxer);
  354. new_vtrack->track_frame_buffer_size = 0;
  355. if (!new_vtrack->frame_offsets) {
  356.   if (file->is_video_stream) {
  357.   } else {
  358.     new_vtrack->total_frames = 
  359.       (long)(mpeg3demux_length(new_vtrack->demuxer) * frame_rate);
  360.   }
  361. } else {
  362.   new_vtrack->total_frames = new_vtrack->total_frame_offsets;
  363. }
  364. //printf("mpeg3_new_vtrack 2n");
  365. return new_vtrack;
  366. }
  367. int mpeg3_delete_vtrack(mpeg3_t *file, mpeg3_vtrack_t *vtrack)
  368. {
  369. if(vtrack->demuxer) mpeg3_delete_demuxer(vtrack->demuxer);
  370. free(vtrack);
  371. return 0;
  372. }
  373. /* Read all the way up to and including the next picture start code */
  374. int mpeg3vtrack_read_raw (mpeg3_vtrack_t *vtrack, 
  375.   unsigned char *output, 
  376.   long *size, 
  377.   long max_size)
  378. {
  379.   u_int32_t code = 0;
  380.   mpeg3_demuxer_t *demux = vtrack->demuxer;
  381.   *size = 0;
  382.   while(code != MPEG3_PICTURE_START_CODE && 
  383. code != MPEG3_SEQUENCE_END_CODE &&
  384. *size < max_size && 
  385. !mpeg3demux_eof(demux))
  386.     {
  387.       code <<= 8;
  388.       *output = mpeg3demux_read_char(demux);
  389.       code |= *output++;
  390.       (*size)++;
  391.     }
  392.   return mpeg3demux_eof(demux);
  393. }
  394. /* Read all the way up to and including the next picture start code */
  395. int mpeg3vtrack_read_raw_resize (mpeg3_vtrack_t *vtrack, 
  396.  unsigned char **optr, 
  397.  long *size, 
  398.  int first)
  399. {
  400.   int result = 0;
  401.   result = mpeg3vtrack_seek(vtrack, 1);
  402.   
  403.   if (!result) result = mpeg3vtrack_get_frame(vtrack);
  404.   if (!result) {
  405.     *optr = vtrack->track_frame_buffer;
  406.     *size = vtrack->track_frame_buffer_size;
  407.   }
  408.   return result;
  409. }