summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/libmpeg3/video/seek.c
Unidiff
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.c233
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
7unsigned 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. */
22int 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. */
33int 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
43long 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
53int 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
84int 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
222int 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}