Diffstat (limited to 'core/multimedia/opieplayer/libmpeg3/video/seek.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | core/multimedia/opieplayer/libmpeg3/video/seek.c | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/libmpeg3/video/seek.c b/core/multimedia/opieplayer/libmpeg3/video/seek.c new file mode 100644 index 0000000..04faba4 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/seek.c | |||
@@ -0,0 +1,233 @@ | |||
1 | #include "../mpeg3private.h" | ||
2 | #include "../mpeg3protos.h" | ||
3 | #include "mpeg3video.h" | ||
4 | #include <stdlib.h> | ||
5 | #include <string.h> | ||
6 | |||
7 | unsigned int mpeg3bits_next_startcode(mpeg3_bits_t* stream) | ||
8 | { | ||
9 | /* Perform forwards search */ | ||
10 | mpeg3bits_byte_align(stream); | ||
11 | |||
12 | /* Perform search */ | ||
13 | while((mpeg3bits_showbits32_noptr(stream) >> 8) != MPEG3_PACKET_START_CODE_PREFIX && | ||
14 | !mpeg3bits_eof(stream)) | ||
15 | { | ||
16 | mpeg3bits_getbyte_noptr(stream); | ||
17 | } | ||
18 | return mpeg3bits_showbits32_noptr(stream); | ||
19 | } | ||
20 | |||
21 | /* Line up on the beginning of the next code. */ | ||
22 | int mpeg3video_next_code(mpeg3_bits_t* stream, unsigned int code) | ||
23 | { | ||
24 | while(!mpeg3bits_eof(stream) && | ||
25 | mpeg3bits_showbits32_noptr(stream) != code) | ||
26 | { | ||
27 | mpeg3bits_getbyte_noptr(stream); | ||
28 | } | ||
29 | return mpeg3bits_eof(stream); | ||
30 | } | ||
31 | |||
32 | /* Line up on the beginning of the previous code. */ | ||
33 | int mpeg3video_prev_code(mpeg3_bits_t* stream, unsigned int code) | ||
34 | { | ||
35 | while(!mpeg3bits_bof(stream) && | ||
36 | mpeg3bits_showbits_reverse(stream, 32) != code) | ||
37 | { | ||
38 | mpeg3bits_getbits_reverse(stream, 8); | ||
39 | } | ||
40 | return mpeg3bits_bof(stream); | ||
41 | } | ||
42 | |||
43 | long mpeg3video_goptimecode_to_frame(mpeg3video_t *video) | ||
44 | { | ||
45 | /* printf("mpeg3video_goptimecode_to_frame %d %d %d %d %f\n", */ | ||
46 | /* video->gop_timecode.hour, video->gop_timecode.minute, video->gop_timecode.second, video->gop_timecode.frame, video->frame_rate); */ | ||
47 | return (long)(video->gop_timecode.hour * 3600 * video->frame_rate + | ||
48 | video->gop_timecode.minute * 60 * video->frame_rate + | ||
49 | video->gop_timecode.second * video->frame_rate + | ||
50 | video->gop_timecode.frame) - 1 - video->first_frame; | ||
51 | } | ||
52 | |||
53 | int mpeg3video_match_refframes(mpeg3video_t *video) | ||
54 | { | ||
55 | unsigned char *dst, *src; | ||
56 | int i, j, size; | ||
57 | |||
58 | for(i = 0; i < 3; i++) | ||
59 | { | ||
60 | if(video->newframe[i]) | ||
61 | { | ||
62 | if(video->newframe[i] == video->refframe[i]) | ||
63 | { | ||
64 | src = video->refframe[i]; | ||
65 | dst = video->oldrefframe[i]; | ||
66 | } | ||
67 | else | ||
68 | { | ||
69 | src = video->oldrefframe[i]; | ||
70 | dst = video->refframe[i]; | ||
71 | } | ||
72 | |||
73 | if(i == 0) | ||
74 | size = video->coded_picture_width * video->coded_picture_height + 32 * video->coded_picture_width; | ||
75 | else | ||
76 | size = video->chrom_width * video->chrom_height + 32 * video->chrom_width; | ||
77 | |||
78 | memcpy(dst, src, size); | ||
79 | } | ||
80 | } | ||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | int mpeg3video_seek(mpeg3video_t *video) | ||
85 | { | ||
86 | long this_gop_start; | ||
87 | int result = 0; | ||
88 | int back_step; | ||
89 | int attempts; | ||
90 | mpeg3_t *file = video->file; | ||
91 | mpeg3_bits_t *vstream = video->vstream; | ||
92 | double percentage; | ||
93 | long frame_number; | ||
94 | int match_refframes = 1; | ||
95 | |||
96 | /* Seek to a percentage */ | ||
97 | if(video->percentage_seek >= 0) | ||
98 | { | ||
99 | percentage = video->percentage_seek; | ||
100 | video->percentage_seek = -1; | ||
101 | mpeg3bits_seek_percentage(vstream, percentage); | ||
102 | // Go to previous I-frame | ||
103 | mpeg3bits_start_reverse(vstream); | ||
104 | result = mpeg3video_prev_code(vstream, MPEG3_GOP_START_CODE); | ||
105 | if(!result) mpeg3bits_getbits_reverse(vstream, 32); | ||
106 | mpeg3bits_start_forward(vstream); | ||
107 | |||
108 | if(mpeg3bits_tell_percentage(vstream) < 0) mpeg3bits_seek_percentage(vstream, 0); | ||
109 | |||
110 | // Read up to the correct percentage | ||
111 | result = 0; | ||
112 | while(!result && mpeg3bits_tell_percentage(vstream) < percentage) | ||
113 | { | ||
114 | result = mpeg3video_read_frame_backend(video, 0); | ||
115 | if(match_refframes) | ||
116 | mpeg3video_match_refframes(video); | ||
117 | match_refframes = 0; | ||
118 | } | ||
119 | } | ||
120 | else | ||
121 | /* Seek to a frame */ | ||
122 | if(video->frame_seek >= 0) | ||
123 | { | ||
124 | frame_number = video->frame_seek; | ||
125 | video->frame_seek = -1; | ||
126 | if(frame_number < 0) frame_number = 0; | ||
127 | if(frame_number > video->maxframe) frame_number = video->maxframe; | ||
128 | |||
129 | /* Seek to start of file */ | ||
130 | if(frame_number < 16) | ||
131 | { | ||
132 | video->repeat_count = video->current_repeat = 0; | ||
133 | mpeg3bits_seek_start(vstream); | ||
134 | video->framenum = 0; | ||
135 | result = mpeg3video_drop_frames(video, frame_number - video->framenum); | ||
136 | } | ||
137 | else | ||
138 | { | ||
139 | /* Seek to an I frame. */ | ||
140 | if((frame_number < video->framenum || frame_number - video->framenum > MPEG3_SEEK_THRESHOLD)) | ||
141 | { | ||
142 | /* Elementary stream */ | ||
143 | if(file->is_video_stream) | ||
144 | { | ||
145 | mpeg3_t *file = video->file; | ||
146 | mpeg3_vtrack_t *track = video->track; | ||
147 | long byte = (long)((float)(mpeg3demuxer_total_bytes(vstream->demuxer) / | ||
148 | track->total_frames) * | ||
149 | frame_number); | ||
150 | long minimum = 65535; | ||
151 | int done = 0; | ||
152 | |||
153 | //printf("seek elementary %d\n", frame_number); | ||
154 | /* Get GOP just before frame */ | ||
155 | do | ||
156 | { | ||
157 | result = mpeg3bits_seek_byte(vstream, byte); | ||
158 | mpeg3bits_start_reverse(vstream); | ||
159 | if(!result) result = mpeg3video_prev_code(vstream, MPEG3_GOP_START_CODE); | ||
160 | mpeg3bits_start_forward(vstream); | ||
161 | mpeg3bits_getbits(vstream, 8); | ||
162 | if(!result) result = mpeg3video_getgophdr(video); | ||
163 | this_gop_start = mpeg3video_goptimecode_to_frame(video); | ||
164 | |||
165 | //printf("wanted %ld guessed %ld byte %ld result %d\n", frame_number, this_gop_start, byte, result); | ||
166 | if(labs(this_gop_start - frame_number) >= labs(minimum)) | ||
167 | done = 1; | ||
168 | else | ||
169 | { | ||
170 | minimum = this_gop_start - frame_number; | ||
171 | byte += (long)((float)(frame_number - this_gop_start) * | ||
172 | (float)(mpeg3demuxer_total_bytes(vstream->demuxer) / | ||
173 | track->total_frames)); | ||
174 | if(byte < 0) byte = 0; | ||
175 | } | ||
176 | }while(!result && !done); | ||
177 | |||
178 | //printf("wanted %d guessed %d\n", frame_number, this_gop_start); | ||
179 | if(!result) | ||
180 | { | ||
181 | video->framenum = this_gop_start; | ||
182 | result = mpeg3video_drop_frames(video, frame_number - video->framenum); | ||
183 | } | ||
184 | } | ||
185 | else | ||
186 | /* System stream */ | ||
187 | { | ||
188 | mpeg3bits_seek_time(vstream, (double)frame_number / video->frame_rate); | ||
189 | percentage = mpeg3bits_tell_percentage(vstream); | ||
190 | //printf("seek frame %ld percentage %f byte %ld\n", frame_number, percentage, mpeg3bits_tell(vstream)); | ||
191 | mpeg3bits_start_reverse(vstream); | ||
192 | mpeg3video_prev_code(vstream, MPEG3_GOP_START_CODE); | ||
193 | mpeg3bits_getbits_reverse(vstream, 32); | ||
194 | mpeg3bits_start_forward(vstream); | ||
195 | //printf("seek system 1 %f\n", (double)frame_number / video->frame_rate); | ||
196 | |||
197 | while(!result && mpeg3bits_tell_percentage(vstream) < percentage) | ||
198 | { | ||
199 | result = mpeg3video_read_frame_backend(video, 0); | ||
200 | if(match_refframes) | ||
201 | mpeg3video_match_refframes(video); | ||
202 | |||
203 | //printf("seek system 2 %f %f\n", mpeg3bits_tell_percentage(vstream) / percentage); | ||
204 | match_refframes = 0; | ||
205 | } | ||
206 | //printf("seek system 3 %f\n", (double)frame_number / video->frame_rate); | ||
207 | } | ||
208 | |||
209 | video->framenum = frame_number; | ||
210 | } | ||
211 | else | ||
212 | // Drop frames | ||
213 | { | ||
214 | mpeg3video_drop_frames(video, frame_number - video->framenum); | ||
215 | } | ||
216 | } | ||
217 | } | ||
218 | |||
219 | return result; | ||
220 | } | ||
221 | |||
222 | int mpeg3video_drop_frames(mpeg3video_t *video, long frames) | ||
223 | { | ||
224 | int result = 0; | ||
225 | long frame_number = video->framenum + frames; | ||
226 | |||
227 | /* Read the selected number of frames and skip b-frames */ | ||
228 | while(!result && frame_number > video->framenum) | ||
229 | { | ||
230 | result = mpeg3video_read_frame_backend(video, frame_number - video->framenum); | ||
231 | } | ||
232 | return result; | ||
233 | } | ||