r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / libmpeg3 / video / seek.c
blob304ebd45e8bcfff7096697c9023dbf3925ea48d4
1 #include "../mpeg3private.h"
2 #include "../mpeg3protos.h"
3 #include "mpeg3video.h"
4 #include <stdlib.h>
5 #include <string.h>
7 unsigned int mpeg3bits_next_startcode(mpeg3_bits_t* stream)
9 /* Perform forwards search */
10 mpeg3bits_byte_align(stream);
13 //printf("mpeg3bits_next_startcode 1 %lld %lld\n",
14 // stream->demuxer->titles[0]->fs->current_byte,
15 // stream->demuxer->titles[0]->fs->total_bytes);
18 //mpeg3_read_next_packet(stream->demuxer);
19 //printf("mpeg3bits_next_startcode 2 %d %d\n",
20 // stream->demuxer->titles[0]->fs->current_byte,
21 // stream->demuxer->titles[0]->fs->total_bytes);
23 //printf("mpeg3bits_next_startcode 2 %llx\n", mpeg3bits_tell(stream));
24 /* Perform search */
25 while(1)
27 unsigned int code = mpeg3bits_showbits32_noptr(stream);
29 if((code >> 8) == MPEG3_PACKET_START_CODE_PREFIX) break;
30 if(mpeg3bits_eof(stream)) break;
33 mpeg3bits_getbyte_noptr(stream);
36 * printf("mpeg3bits_next_startcode 3 %08x %d %d\n",
37 * mpeg3bits_showbits32_noptr(stream),
38 * stream->demuxer->titles[0]->fs->current_byte,
39 * stream->demuxer->titles[0]->fs->total_bytes);
43 //printf("mpeg3bits_next_startcode 4 %d %d\n",
44 // stream->demuxer->titles[0]->fs->current_byte,
45 // stream->demuxer->titles[0]->fs->total_bytes);
46 return mpeg3bits_showbits32_noptr(stream);
49 /* Line up on the beginning of the next code. */
50 int mpeg3video_next_code(mpeg3_bits_t* stream, unsigned int code)
52 while(!mpeg3bits_eof(stream) &&
53 mpeg3bits_showbits32_noptr(stream) != code)
55 mpeg3bits_getbyte_noptr(stream);
57 return mpeg3bits_eof(stream);
60 /* Line up on the beginning of the previous code. */
61 int mpeg3video_prev_code(mpeg3_bits_t* stream, unsigned int code)
63 while(!mpeg3bits_bof(stream) &&
64 mpeg3bits_showbits_reverse(stream, 32) != code)
66 //printf("mpeg3video_prev_code %08x %08x\n",
67 // mpeg3bits_showbits_reverse(stream, 32), mpeg3demux_tell(stream->demuxer));
68 mpeg3bits_getbits_reverse(stream, 8);
70 return mpeg3bits_bof(stream);
73 long mpeg3video_goptimecode_to_frame(mpeg3video_t *video)
75 /* printf("mpeg3video_goptimecode_to_frame %d %d %d %d %f\n", */
76 /* video->gop_timecode.hour, video->gop_timecode.minute, video->gop_timecode.second, video->gop_timecode.frame, video->frame_rate); */
77 return (long)(video->gop_timecode.hour * 3600 * video->frame_rate +
78 video->gop_timecode.minute * 60 * video->frame_rate +
79 video->gop_timecode.second * video->frame_rate +
80 video->gop_timecode.frame) - 1 - video->first_frame;
83 int mpeg3video_match_refframes(mpeg3video_t *video)
85 unsigned char *dst, *src;
86 int i, j, size;
88 for(i = 0; i < 3; i++)
90 if(video->newframe[i])
92 if(video->newframe[i] == video->refframe[i])
94 src = video->refframe[i];
95 dst = video->oldrefframe[i];
97 else
99 src = video->oldrefframe[i];
100 dst = video->refframe[i];
103 if(i == 0)
104 size = video->coded_picture_width * video->coded_picture_height + 32 * video->coded_picture_width;
105 else
106 size = video->chrom_width * video->chrom_height + 32 * video->chrom_width;
108 memcpy(dst, src, size);
111 return 0;
114 int mpeg3video_seek_percentage(mpeg3video_t *video, double percentage)
116 mpeg3_t *file = video->file;
117 mpeg3_bits_t *vstream = video->vstream;
118 mpeg3_demuxer_t *demuxer = vstream->demuxer;
120 video->percentage_seek = percentage;
124 // Need PTS now so audio can be synchronized
125 mpeg3bits_seek_percentage(vstream, percentage);
126 file->percentage_pts = mpeg3demux_scan_pts(demuxer);
127 return 0;
130 int mpeg3video_seek_frame(mpeg3video_t *video, long frame)
132 video->frame_seek = frame;
133 return 0;
136 int mpeg3video_seek(mpeg3video_t *video)
138 long this_gop_start;
139 int result = 0;
140 int back_step;
141 int attempts;
142 mpeg3_t *file = video->file;
143 mpeg3_bits_t *vstream = video->vstream;
144 mpeg3_vtrack_t *track = video->track;
145 mpeg3_demuxer_t *demuxer = vstream->demuxer;
146 double percentage;
147 long frame_number;
148 int match_refframes = 1;
151 //printf("mpeg3video_seek 1 %d\n", video->frame_seek);
152 // Must do seeking here so files which don't use video don't seek.
153 /* Seek to percentage */
154 if(video->percentage_seek >= 0)
164 //printf("mpeg3video_seek 1 %f\n", video->percentage_seek);
165 percentage = video->percentage_seek;
166 video->percentage_seek = -1;
167 mpeg3bits_seek_percentage(vstream, percentage);
169 // Go to previous I-frame #1
171 mpeg3bits_start_reverse(vstream);
172 //printf("mpeg3video_seek 2\n");
174 if(video->has_gops)
175 result = mpeg3video_prev_code(vstream, MPEG3_GOP_START_CODE);
176 else
177 result = mpeg3video_prev_code(vstream, MPEG3_SEQUENCE_START_CODE);
178 //printf("mpeg3video_seek 3\n");
180 if(!result) mpeg3bits_getbits_reverse(vstream, 32);
182 //printf("mpeg3video_seek 4\n");
185 // Go to previous I-frame #2
186 if(video->has_gops)
187 result = mpeg3video_prev_code(vstream, MPEG3_GOP_START_CODE);
188 else
189 result = mpeg3video_prev_code(vstream, MPEG3_SEQUENCE_START_CODE);
190 //printf("mpeg3video_seek 4\n");
192 if(!result) mpeg3bits_getbits_reverse(vstream, 32);
194 //printf("mpeg3video_seek 4\n");
198 mpeg3bits_start_forward(vstream);
199 //printf("mpeg3video_seek 4\n");
201 // Reread first two I frames
202 if(mpeg3bits_tell_percentage(vstream) <= 0)
204 //printf("mpeg3video_seek 4.1\n");
205 mpeg3bits_seek_percentage(vstream, 0);
206 //printf("mpeg3video_seek 4.2\n");
207 mpeg3video_get_firstframe(video);
208 //printf("mpeg3video_seek 4.3\n");
209 mpeg3video_read_frame_backend(video, 0);
210 //printf("mpeg3video_seek 4.4\n");
213 //printf("mpeg3video_seek 5\n");
216 // Read up to the correct percentage
217 result = 0;
218 while(!result && mpeg3bits_tell_percentage(vstream) < percentage)
220 result = mpeg3video_read_frame_backend(video, 0);
224 //printf("mpeg3video_seek 6 %f\n", mpeg3demux_scan_pts(demuxer));
228 mpeg3demux_reset_pts(demuxer);
230 //printf("mpeg3video_seek 7\n");
233 else
234 /* Seek to a frame */
235 if(video->frame_seek >= 0)
237 frame_number = video->frame_seek;
238 video->frame_seek = -1;
239 if(frame_number < 0) frame_number = 0;
240 if(frame_number > video->maxframe) frame_number = video->maxframe;
242 //printf("mpeg3video_seek 1 %ld %ld\n", frame_number, video->framenum);
244 /* Seek to I frame in table of contents */
245 if(track->frame_offsets)
247 //printf("mpeg3video_seek 2 %d %d\n", video->framenum, frame_number);
248 if((frame_number < video->framenum ||
249 frame_number - video->framenum > MPEG3_SEEK_THRESHOLD))
251 int i;
252 for(i = track->total_keyframe_numbers - 1; i >= 0; i--)
254 //printf("mpeg3video_seek 3 %lld %d\n", track->keyframe_numbers[i], frame_number);
255 if(track->keyframe_numbers[i] <= frame_number)
257 int frame;
258 int title_number;
259 int64_t byte;
261 // Go 2 I-frames before current position
262 if(i > 0) i--;
264 frame = track->keyframe_numbers[i];
265 title_number = (track->frame_offsets[frame] &
266 0xff00000000000000) >> 56;
267 byte = track->frame_offsets[frame] &
268 0xffffffffffffff;
270 video->framenum = track->keyframe_numbers[i];
272 mpeg3bits_open_title(vstream, title_number);
273 mpeg3bits_seek_byte(vstream, byte);
276 // Get first 2 I-frames
277 if(byte == 0)
279 mpeg3video_get_firstframe(video);
280 mpeg3video_read_frame_backend(video, 0);
284 //printf("mpeg3video_seek 2 %ld %ld\n", frame_number, video->framenum);
286 mpeg3video_drop_frames(video, frame_number - video->framenum);
287 break;
291 else
293 mpeg3video_drop_frames(video, frame_number - video->framenum);
296 else
297 /* Seek to start of file */
298 if(frame_number < 16)
300 video->repeat_count = video->current_repeat = 0;
301 mpeg3bits_seek_start(vstream);
302 video->framenum = 0;
303 result = mpeg3video_drop_frames(video,
304 frame_number - video->framenum);
306 else
308 /* Seek to an I frame. */
309 //printf(__FUNCTION__ " frame_number=%d video->framenum=%d\n", frame_number, video->framenum);
310 if((frame_number < video->framenum ||
311 frame_number - video->framenum > MPEG3_SEEK_THRESHOLD))
316 /* Elementary stream */
317 if(file->is_video_stream)
319 mpeg3_t *file = video->file;
320 mpeg3_vtrack_t *track = video->track;
321 int64_t byte = (int64_t)((double)(mpeg3demuxer_total_bytes(demuxer) /
322 track->total_frames) *
323 frame_number);
324 long minimum = 65535;
325 int done = 0;
327 /* Get GOP just before frame */
330 result = mpeg3bits_seek_byte(vstream, byte);
331 mpeg3bits_start_reverse(vstream);
333 if(!result) result = mpeg3video_prev_code(vstream, MPEG3_GOP_START_CODE);
334 mpeg3bits_start_forward(vstream);
335 mpeg3bits_getbits(vstream, 8);
336 if(!result) result = mpeg3video_getgophdr(video);
337 this_gop_start = mpeg3video_goptimecode_to_frame(video);
339 //printf("wanted %ld guessed %ld byte %ld result %d\n", frame_number, this_gop_start, byte, result);
340 if(labs(this_gop_start - frame_number) >= labs(minimum))
341 done = 1;
342 else
344 minimum = this_gop_start - frame_number;
345 byte += (long)((float)(frame_number - this_gop_start) *
346 (float)(mpeg3demuxer_total_bytes(demuxer) /
347 track->total_frames));
348 if(byte < 0) byte = 0;
350 }while(!result && !done);
352 //printf("wanted %d guessed %d\n", frame_number, this_gop_start);
353 if(!result)
355 video->framenum = this_gop_start;
356 result = mpeg3video_drop_frames(video, frame_number - video->framenum);
359 else
364 /* System stream */
366 mpeg3bits_seek_time(vstream, (double)frame_number / video->frame_rate);
368 percentage = mpeg3bits_tell_percentage(vstream);
369 //printf("seek frame %ld percentage %f byte %ld\n", frame_number, percentage, mpeg3bits_tell(vstream));
370 mpeg3bits_start_reverse(vstream);
371 mpeg3video_prev_code(vstream, MPEG3_GOP_START_CODE);
372 mpeg3bits_getbits_reverse(vstream, 32);
373 mpeg3bits_start_forward(vstream);
374 //printf("seek system 1 %f\n", (double)frame_number / video->frame_rate);
376 while(!result && mpeg3bits_tell_percentage(vstream) < percentage)
378 result = mpeg3video_read_frame_backend(video, 0);
379 if(match_refframes)
380 mpeg3video_match_refframes(video);
382 //printf("seek system 2 %f %f\n", mpeg3bits_tell_percentage(vstream) / percentage);
383 match_refframes = 0;
385 //printf("seek system 3 %f\n", (double)frame_number / video->frame_rate);
388 video->framenum = frame_number;
390 else
391 // Drop frames
393 mpeg3video_drop_frames(video, frame_number - video->framenum);
396 mpeg3demux_reset_pts(demuxer);
399 return result;
402 int mpeg3video_previous_frame(mpeg3video_t *video)
404 if(mpeg3bits_tell_percentage(video->vstream) <= 0) return 1;
406 // Get one picture
407 mpeg3bits_start_reverse(video->vstream);
408 mpeg3video_prev_code(video->vstream, MPEG3_PICTURE_START_CODE);
409 mpeg3bits_getbits_reverse(video->vstream, 32);
411 if(mpeg3bits_bof(video->vstream))
412 mpeg3bits_seek_percentage(video->vstream, 0);
413 mpeg3bits_start_forward(video->vstream);
414 video->repeat_count = 0;
415 return 0;
418 int mpeg3video_drop_frames(mpeg3video_t *video, long frames)
420 int result = 0;
421 long frame_number = video->framenum + frames;
423 //printf("mpeg3video_drop_frames 1 %d %d\n", frame_number, video->framenum);
424 /* Read the selected number of frames and skip b-frames */
425 while(!result && frame_number > video->framenum)
427 result = mpeg3video_read_frame_backend(video, frame_number - video->framenum);
429 //printf("mpeg3video_drop_frames 100\n");
431 return result;