r726: Implementing ability to add textural info to the labels
[cinelerra_cv/mob.git] / libmpeg3 / video / seek.c
blobe523e4c53e48b489b1c996b6e33fdd97bd363408
1 #include "../mpeg3private.h"
2 #include "../mpeg3protos.h"
3 #include "mpeg3video.h"
4 #include <stdlib.h>
5 #include <string.h>
7 void mpeg3video_toc_error()
9 fprintf(stderr,
10 "mpeg3video_seek: frame accurate seeking without a table of contents \n"
11 "is no longer supported. Use mpeg3toc <mpeg file> <table of contents>\n"
12 "to generate a table of contents and load the table of contents instead.\n");
15 unsigned int mpeg3bits_next_startcode(mpeg3_bits_t* stream)
17 /* Perform forwards search */
18 mpeg3bits_byte_align(stream);
22 * printf("mpeg3bits_next_startcode 1 %lld %lld\n",
23 * stream->demuxer->titles[0]->fs->current_byte,
24 * stream->demuxer->titles[0]->fs->total_bytes);
28 //mpeg3_read_next_packet(stream->demuxer);
29 //printf("mpeg3bits_next_startcode 2 %d %d\n",
30 // stream->demuxer->titles[0]->fs->current_byte,
31 // stream->demuxer->titles[0]->fs->total_bytes);
33 //printf("mpeg3bits_next_startcode 2 %llx\n", mpeg3bits_tell(stream));
34 /* Perform search */
35 while(1)
37 unsigned int code = mpeg3bits_showbits32_noptr(stream);
39 if((code >> 8) == MPEG3_PACKET_START_CODE_PREFIX) break;
40 if(mpeg3bits_eof(stream)) break;
43 mpeg3bits_getbyte_noptr(stream);
46 * printf("mpeg3bits_next_startcode 3 %08x %d %d\n",
47 * mpeg3bits_showbits32_noptr(stream),
48 * stream->demuxer->titles[0]->fs->current_byte,
49 * stream->demuxer->titles[0]->fs->total_bytes);
53 //printf("mpeg3bits_next_startcode 4 %d %d\n",
54 // stream->demuxer->titles[0]->fs->current_byte,
55 // stream->demuxer->titles[0]->fs->total_bytes);
56 return mpeg3bits_showbits32_noptr(stream);
59 /* Line up on the beginning of the next code. */
60 int mpeg3video_next_code(mpeg3_bits_t* stream, unsigned int code)
62 while(!mpeg3bits_eof(stream) &&
63 mpeg3bits_showbits32_noptr(stream) != code)
65 mpeg3bits_getbyte_noptr(stream);
67 return mpeg3bits_eof(stream);
70 /* Line up on the beginning of the previous code. */
71 int mpeg3video_prev_code(mpeg3_demuxer_t *demuxer, unsigned int code)
73 uint32_t current_code = 0;
75 #define PREV_CODE_MACRO \
76 { \
77 current_code >>= 8; \
78 current_code |= ((uint32_t)mpeg3demux_read_prev_char(demuxer)) << 24; \
81 PREV_CODE_MACRO
82 PREV_CODE_MACRO
83 PREV_CODE_MACRO
84 PREV_CODE_MACRO
86 while(!mpeg3demux_bof(demuxer) && current_code != code)
88 PREV_CODE_MACRO
90 return mpeg3demux_bof(demuxer);
93 long mpeg3video_goptimecode_to_frame(mpeg3video_t *video)
95 /* printf("mpeg3video_goptimecode_to_frame %d %d %d %d %f\n", */
96 /* video->gop_timecode.hour, video->gop_timecode.minute, video->gop_timecode.second, video->gop_timecode.frame, video->frame_rate); */
97 return (long)(video->gop_timecode.hour * 3600 * video->frame_rate +
98 video->gop_timecode.minute * 60 * video->frame_rate +
99 video->gop_timecode.second * video->frame_rate +
100 video->gop_timecode.frame) - 1 - video->first_frame;
103 int mpeg3video_match_refframes(mpeg3video_t *video)
105 unsigned char *dst, *src;
106 int i, j, size;
108 for(i = 0; i < 3; i++)
110 if(video->newframe[i])
112 if(video->newframe[i] == video->refframe[i])
114 src = video->refframe[i];
115 dst = video->oldrefframe[i];
117 else
119 src = video->oldrefframe[i];
120 dst = video->refframe[i];
123 if(i == 0)
124 size = video->coded_picture_width * video->coded_picture_height + 32 * video->coded_picture_width;
125 else
126 size = video->chrom_width * video->chrom_height + 32 * video->chrom_width;
128 memcpy(dst, src, size);
131 return 0;
134 int mpeg3video_seek_byte(mpeg3video_t *video, int64_t byte)
136 mpeg3_t *file = video->file;
137 mpeg3_bits_t *vstream = video->vstream;
138 mpeg3_demuxer_t *demuxer = vstream->demuxer;
140 video->byte_seek = byte;
144 // Need PTS now so audio can be synchronized
145 mpeg3bits_seek_byte(vstream, byte);
146 // file->percentage_pts = mpeg3demux_scan_pts(demuxer);
147 return 0;
150 int mpeg3video_seek_frame(mpeg3video_t *video, long frame)
152 video->frame_seek = frame;
153 return 0;
156 int mpeg3_rewind_video(mpeg3video_t *video)
158 mpeg3_vtrack_t *track = video->track;
159 mpeg3_bits_t *vstream = video->vstream;
161 if(track->frame_offsets)
162 mpeg3bits_seek_byte(vstream, track->frame_offsets[0]);
163 else
164 mpeg3bits_seek_byte(vstream, 0);
166 return 0;
169 int mpeg3video_seek(mpeg3video_t *video)
171 long this_gop_start;
172 int result = 0;
173 int back_step;
174 int attempts;
175 mpeg3_t *file = video->file;
176 mpeg3_bits_t *vstream = video->vstream;
177 mpeg3_vtrack_t *track = video->track;
178 mpeg3_demuxer_t *demuxer = vstream->demuxer;
179 int64_t byte;
180 long frame_number;
181 int match_refframes = 1;
185 /* Must do seeking here so files which don't use video don't seek. */
186 /* Seeking is done in the demuxer */
187 /* Seek to absolute byte */
188 if(video->byte_seek >= 0)
190 byte = video->byte_seek;
191 video->byte_seek = -1;
192 mpeg3demux_seek_byte(demuxer, byte);
194 // Rewind 2 I-frames
195 if(byte > 0)
197 //printf("mpeg3video_seek 1\n");
198 mpeg3demux_start_reverse(demuxer);
200 //printf("mpeg3video_seek 1 %lld\n", mpeg3demux_tell_byte(demuxer));
201 if(!result)
203 if(video->has_gops)
204 result = mpeg3video_prev_code(demuxer, MPEG3_GOP_START_CODE);
205 else
206 result = mpeg3video_prev_code(demuxer, MPEG3_SEQUENCE_START_CODE);
208 //printf("mpeg3video_seek 2 %lld\n", mpeg3demux_tell_byte(demuxer));
210 if(!result)
212 if(video->has_gops)
213 result = mpeg3video_prev_code(demuxer, MPEG3_GOP_START_CODE);
214 else
215 result = mpeg3video_prev_code(demuxer, MPEG3_SEQUENCE_START_CODE);
218 //printf("mpeg3video_seek 3 %lld\n", mpeg3demux_tell_byte(demuxer));
222 mpeg3demux_start_forward(demuxer);
224 else
226 // Read first frame
227 video->repeat_count = 0;
228 mpeg3bits_reset(vstream);
229 mpeg3video_read_frame_backend(video, 0);
230 mpeg3_rewind_video(video);
231 video->repeat_count = 0;
235 mpeg3bits_reset(vstream);
237 //printf("mpeg3video_seek 4 %lld\n", mpeg3demux_tell_byte(demuxer));
238 // Read up to the correct byte
239 result = 0;
240 video->repeat_count = 0;
241 while(!result &&
242 !mpeg3demux_eof(demuxer) &&
243 mpeg3demux_tell_byte(demuxer) < byte)
245 result = mpeg3video_read_frame_backend(video, 0);
248 //printf("mpeg3video_seek 5 %lld\n", mpeg3demux_tell_byte(demuxer));
253 mpeg3demux_reset_pts(demuxer);
255 //printf("mpeg3video_seek 10\n");
258 else
259 /* Seek to a frame */
260 if(video->frame_seek >= 0)
262 frame_number = video->frame_seek;
263 video->frame_seek = -1;
264 if(frame_number < 0) frame_number = 0;
265 if(frame_number > video->maxframe) frame_number = video->maxframe;
267 //printf("mpeg3video_seek 1 %ld %ld\n", frame_number, video->framenum);
269 /* Seek to I frame in table of contents */
270 if(track->frame_offsets)
272 if((frame_number < video->framenum ||
273 frame_number - video->framenum > MPEG3_SEEK_THRESHOLD))
275 int i;
276 for(i = track->total_keyframe_numbers - 1; i >= 0; i--)
278 if(track->keyframe_numbers[i] <= frame_number)
280 int frame;
281 int64_t byte;
283 // Go 2 I-frames before current position
284 if(i > 0) i--;
286 frame = track->keyframe_numbers[i];
287 if(frame == 0)
288 byte = track->frame_offsets[0];
289 else
290 byte = track->frame_offsets[frame];
291 video->framenum = track->keyframe_numbers[i];
293 mpeg3bits_seek_byte(vstream, byte);
296 // Get first 2 I-frames
297 if(byte == 0)
299 mpeg3video_get_firstframe(video);
300 mpeg3video_read_frame_backend(video, 0);
305 video->repeat_count = 0;
306 mpeg3video_drop_frames(video, frame_number - video->framenum);
307 break;
311 else
313 video->repeat_count = 0;
314 mpeg3video_drop_frames(video, frame_number - video->framenum);
317 else
318 /* Discontinue support of seeking without table of contents */
320 mpeg3video_toc_error();
335 #if 0
336 /* Seek to start of file */
337 if(frame_number < 16)
339 video->repeat_count = video->current_repeat = 0;
340 mpeg3bits_seek_start(vstream);
341 video->framenum = 0;
342 result = mpeg3video_drop_frames(video,
343 frame_number - video->framenum);
345 else
347 /* Seek to an I frame. */
348 //printf(__FUNCTION__ " frame_number=%d video->framenum=%d\n", frame_number, video->framenum);
349 if((frame_number < video->framenum ||
350 frame_number - video->framenum > MPEG3_SEEK_THRESHOLD))
355 /* Elementary stream. Estimate frame position from total bytes. */
356 if(file->is_video_stream)
358 int64_t byte = (int64_t)((double)(mpeg3demux_movie_size(demuxer) /
359 track->total_frames) *
360 frame_number);
361 long minimum = 65535;
362 int done = 0;
364 /* Get GOP just before frame */
367 result = mpeg3bits_seek_byte(vstream, byte);
368 mpeg3bits_start_reverse(vstream);
370 if(!result) result = mpeg3video_prev_code(vstream, MPEG3_GOP_START_CODE);
371 mpeg3bits_start_forward(vstream);
372 mpeg3bits_getbits(vstream, 8);
373 if(!result) result = mpeg3video_getgophdr(video);
374 this_gop_start = mpeg3video_goptimecode_to_frame(video);
376 //printf("wanted %ld guessed %ld byte %ld result %d\n", frame_number, this_gop_start, byte, result);
377 if(labs(this_gop_start - frame_number) >= labs(minimum))
378 done = 1;
379 else
381 minimum = this_gop_start - frame_number;
382 byte += (long)((float)(frame_number - this_gop_start) *
383 (double)(mpeg3demux_movie_size(demuxer) /
384 track->total_frames));
385 if(byte < 0) byte = 0;
387 }while(!result && !done);
389 //printf("wanted %d guessed %d\n", frame_number, this_gop_start);
390 if(!result)
392 video->framenum = this_gop_start;
393 result = mpeg3video_drop_frames(video, frame_number - video->framenum);
396 else
401 /* System stream */
403 mpeg3bits_seek_time(vstream, (double)frame_number / video->frame_rate);
405 byte = mpeg3bits_tell(vstream);
406 mpeg3bits_start_reverse(vstream);
407 mpeg3video_prev_code(vstream, MPEG3_GOP_START_CODE);
408 mpeg3bits_getbits_reverse(vstream, 32);
409 mpeg3bits_start_forward(vstream);
411 while(!result && mpeg3bits_tell(vstream) < byte)
413 result = mpeg3video_read_frame_backend(video, 0);
414 if(match_refframes)
415 mpeg3video_match_refframes(video);
417 match_refframes = 0;
419 //printf("seek system 3 %f\n", (double)frame_number / video->frame_rate);
422 video->framenum = frame_number;
424 else
425 // Drop frames
427 mpeg3video_drop_frames(video, frame_number - video->framenum);
430 #endif
446 mpeg3demux_reset_pts(demuxer);
449 return result;
452 int mpeg3video_previous_frame(mpeg3video_t *video)
454 mpeg3_bits_t *bitstream = video->vstream;
455 mpeg3_demuxer_t *demuxer = bitstream->demuxer;
456 int result = 0;
457 int64_t target_byte = 0;
459 if(mpeg3demux_tell_byte(demuxer) <= 0) return 1;
461 // Get location of end of previous picture
462 mpeg3demux_start_reverse(demuxer);
463 result = mpeg3video_prev_code(demuxer, MPEG3_PICTURE_START_CODE);
464 if(!result) result = mpeg3video_prev_code(demuxer, MPEG3_PICTURE_START_CODE);
465 if(!result) result = mpeg3video_prev_code(demuxer, MPEG3_PICTURE_START_CODE);
466 if(!result) target_byte = mpeg3demux_tell_byte(demuxer);
469 // Rewind 2 I-frames
470 if(!result)
472 if(video->has_gops)
473 result = mpeg3video_prev_code(demuxer, MPEG3_GOP_START_CODE);
474 else
475 result = mpeg3video_prev_code(demuxer, MPEG3_SEQUENCE_START_CODE);
478 if(!result)
480 if(video->has_gops)
481 result = mpeg3video_prev_code(demuxer, MPEG3_GOP_START_CODE);
482 else
483 result = mpeg3video_prev_code(demuxer, MPEG3_SEQUENCE_START_CODE);
486 mpeg3demux_start_forward(demuxer);
487 mpeg3bits_reset(bitstream);
489 // Read up to correct byte
490 result = 0;
491 video->repeat_count = 0;
492 while(!result &&
493 !mpeg3demux_eof(demuxer) &&
494 mpeg3demux_tell_byte(demuxer) < target_byte)
496 result = mpeg3video_read_frame_backend(video, 0);
499 video->repeat_count = 0;
500 return 0;
503 int mpeg3video_drop_frames(mpeg3video_t *video, long frames)
505 int result = 0;
506 long frame_number = video->framenum + frames;
508 //printf("mpeg3video_drop_frames 1 %d %d\n", frame_number, video->framenum);
509 /* Read the selected number of frames and skip b-frames */
510 while(!result && frame_number > video->framenum)
512 result = mpeg3video_read_frame_backend(video, frame_number - video->framenum);
514 //printf("mpeg3video_drop_frames 100\n");
516 return result;