tweak map media vicon popup timeline drag/select
[goodguy/cinelerra.git] / cinelerra-5.1 / libzmpeg3 / video / seek.C
1 #include "../libzmpeg3.h"
2
3 static void
4 toc_error()
5 {
6   zerr( "frame accurate seeking without a table of contents \n"
7     "is no longer supported.  Use mpeg3toc <mpeg file> <table of contents>\n"
8     "to generate a table of contents and load the table of contents instead.\n");
9 }
10
11 void zvideo_t::
12 cache_frame()
13 {
14   if( output_src[0] ) {
15     int coded_size = coded_picture_width * coded_picture_height;
16     int chrom_size = chrom_width * chrom_height;
17     track->frame_cache->put_frame(framenum-1,
18       output_src[0], output_src[1], output_src[2],
19       coded_size, chrom_size, chrom_size);
20   }
21 }
22
23 int zvideo_t::
24 drop_frames(long frames, int cache_it)
25 {
26   int result = 0;
27   long frame_number = framenum + frames;
28 //zmsgs("drop frames framenum %d frames %ld\n", framenum, frames);
29
30 /* Read the selected number of frames and skip b-frames */
31   while(!result && frame_number > framenum ) {
32     if( cache_it ) {
33       result = read_frame_backend(0);
34       if( !result && ref_frames > 1 )
35         cache_frame();
36     }
37     else {
38 //zmsgs("framenum %d frame_offset %jx last_packet_start %jx repeat %d/%d",
39 //  framenum,track->frame_offsets[framenum+1],vstream->demuxer->last_packet_start,
40 //  repeat_fields, current_field);
41       result = read_frame_backend(frame_number - framenum);
42 //zmsgs(" type %c\n","XIPBD"[pict_type]);
43     }
44   }
45
46   return result;
47 }
48
49 int zbits_t::
50 next_start_code()
51 {
52 //zmsg("1\n");
53   /* search forwards */
54   prev_byte_align();
55   int64_t stream_end = demuxer->stream_end;
56   if( demuxer->src->is_transport_stream() )
57     demuxer->stream_end = demuxer->program_byte + MAX_TS_PROBE;
58   else if( demuxer->src->is_program_stream() )
59     demuxer->stream_end = demuxer->program_byte + MAX_PGM_PROBE;
60   int zcode = -1, result = -1;
61
62   while( !eof() ) {
63     int bits = (uint8_t)zcode!=0 ? 24 : 8;
64     zcode = (zcode<<bits) | get_bits_noptr(bits);
65     if( (zcode&0xffffff) == PACKET_START_CODE_PREFIX ) {
66       zcode = (zcode<<8) + get_byte_noptr();
67       reset(result = zcode);
68 //zmsgs("5 %04x\n",zcode);
69       break;
70     }
71   }
72
73   demuxer->stream_end = stream_end;
74   return result;
75 }
76
77 /* Line up on the beginning of the next code. */
78 int zbits_t::
79 next_code(uint32_t zcode)
80 {
81   while(!eof() && show_bits_noptr(32) != zcode ) {
82     get_byte_noptr();
83   }
84   return eof();
85 }
86
87 /* Line up on the beginning of the previous code. */
88 int zdemuxer_t::
89 prev_code(uint32_t zcode)
90 {
91   uint32_t current_code = 0;
92 #define PREV_CODE_MACRO { current_code >>= 8; \
93   current_code |= ((uint32_t)read_prev_char()) << 24; }
94
95   PREV_CODE_MACRO
96   PREV_CODE_MACRO
97   PREV_CODE_MACRO
98   PREV_CODE_MACRO
99
100   while( !bof() && current_code != zcode ) {
101     PREV_CODE_MACRO
102   }
103   return bof();
104 }
105
106 int zvideo_t::
107 seek_byte(int64_t byte)
108 {
109   byte_seek = byte;
110   return 0;
111 }
112
113 int zvideo_t::
114 seek_frame(long frame)
115 {
116   frame_seek = frame;
117   return 0;
118 }
119
120 int zvideo_t::
121 rewind_video(int preload)
122 {
123   vstream->reset();
124   framenum = 0;
125   if( track->frame_offsets )
126     vstream->seek_byte(track->frame_offsets[0]);
127   else
128     vstream->seek_byte(0);
129   track->reset_pts();
130   repeat_data = ref_frames = 0;
131   last_number = framenum = -1;
132   return preload ? read_frame_backend(0) : 0;
133 }
134
135 int zvideo_t::
136 seek()
137 {
138   int result = 0;
139   int64_t byte;
140   long frame_number;
141   int debug = 0;
142   demuxer_t *demux = vstream->demuxer;
143
144 /* Must do seeking here so files which don't use video don't seek. */
145 /* Seeking is done in the demuxer */
146 /* Seek to absolute byte */
147   if( byte_seek >= 0 ) {
148     byte = byte_seek;
149     byte_seek = -1;
150     if( byte != demux->tell_byte() ) {
151       demux->seek_byte(byte);
152       track->reset_pts();
153       if( byte > 0 ) {
154   //zmsg("1\n");
155         demux->start_reverse();
156   //zmsgs("1 %jd\n", demux->tell_byte());
157         for( int i=0; i<2; ++i ) {     /* Rewind 2 I-frames */
158           if( has_gops ?
159             demux->prev_code(GOP_START_CODE) :
160             demux->prev_code(SEQUENCE_START_CODE) ) break;
161         }
162   //zmsgs("2 %jd\n", demux->tell_byte());
163         demux->start_forward();
164         if( track->frame_offsets ) {
165           int64_t offset = demux->tell_byte();
166           for( int k=0; k<track->total_keyframe_numbers; ++k ) {
167             frame_number = track->keyframe_numbers[k];
168             if( track->frame_offsets[frame_number] >= offset ) {
169               /* first entry is special */
170               framenum = frame_number>0 ? frame_number-1 : 0;
171               break;
172             }
173           }
174         }
175         else {
176           /* framenum no longer accurate, clear subtitles */
177           reset_subtitles();
178         }
179       }
180       else { /* Read first frame */
181         rewind_video();
182       }
183       vstream->reset();
184       repeat_data = ref_frames = 0;
185   //zmsgs("4 %jd\n", demux->tell_byte());
186       while( !result && !demux->eof() && demux->tell_byte() < byte ) {
187         result = read_frame_backend(0);
188       }
189     }
190   }
191   else if( frame_seek >= 0 ) {
192     /* Seek to a frame number */
193     frame_number = frame_seek;
194     frame_seek = -1;
195     if( frame_number != framenum ) {
196       if( debug ) zmsgs("%d\n", __LINE__);
197       if( frame_number < 0 ) frame_number = 0;
198       if( frame_number > maxframe ) frame_number = maxframe;
199       if(debug) zmsgs("%d %ld %d\n", __LINE__, frame_number, framenum);
200       /* Seek to I frame in table of contents. */
201       /* Determine time between seek position and previous subtitle. */
202       /* Subtract time difference from subtitle display time. */
203       if( frame_number > 0 && track->frame_offsets ) {
204         if( debug ) zmsgs("%d\n", __LINE__);
205         track->frame_cache->reset();
206         if( debug ) zmsgs("%d\n", __LINE__);
207         if( frame_number < framenum || 
208             frame_number-framenum > SEEK_THRESHOLD ) {
209           int idx = track->find_keyframe_index(frame_number);
210           /* back up 2 I frames, data may reference old refframes */
211           if( --idx < 0 ) idx = 0;
212           idx = track->keyframe_numbers[idx];
213           byte = track->frame_offsets[idx];
214           /* maybe lots of frames in one block, move is to earliest frame */
215           while( idx > 0 && track->frame_offsets[idx-1] == byte ) --idx;
216           if( debug ) zmsgs("%ld idx=%d, byte=%jd\n", frame_number,idx,byte);
217           framenum = idx-1;
218           vstream->seek_byte(byte);
219           track->reset_pts();
220           repeat_data = ref_frames = 0;
221           /* get the first I-frame.  It does not count in the frame sequence */
222           /*   phys order is IBBPBBPBB... presentation order is BBIBBPBB... */
223           result = read_frame_backend(0);
224         }
225         if( debug ) zmsgs("%d %ld %d\n", __LINE__,frame_number,framenum);
226         if( !result && frame_number > framenum ) {
227           /* Read up to current frame */
228           int n = frame_number - framenum;
229           result = drop_frames(n, n < MAX_CACHE_FRAMES ? 1 : 0);
230           if( debug ) zmsgs("%d\n", __LINE__);
231         }
232       }
233       else if( frame_number == 0 ) {
234         result = rewind_video();
235       }
236       else {
237         /* No support for seeking without table of contents */
238         toc_error();
239         result = 1;
240       }
241     }
242   }
243   else if( framenum < 0 ) {   /* preload */
244     result = rewind_video(1);
245   }
246   else
247     return 0;
248
249   seek_time = 0;
250   return result;
251 }
252
253 int zvideo_t::
254 previous_frame()
255 {
256   int result = 0;
257   int64_t target_byte = 0;
258   demuxer_t *demux = vstream->demuxer;
259   if( demux->tell_byte() <= 0 ) return 1;
260   /* Get location of end of previous picture */
261   demux->start_reverse();
262   result = demux->prev_code(PICTURE_START_CODE);
263   if( !result ) result = demux->prev_code(PICTURE_START_CODE);
264   if( !result ) result = demux->prev_code(PICTURE_START_CODE);
265   if( !result ) target_byte = demux->tell_byte();
266   if( !result ) { /* Rewind 2 I-frames */
267     if( has_gops )
268       result = demux->prev_code(GOP_START_CODE);
269     else
270       result = demux->prev_code(SEQUENCE_START_CODE);
271   }
272
273   if( !result )
274   {
275     if( has_gops )
276       result = demux->prev_code(GOP_START_CODE);
277     else
278       result = demux->prev_code(SEQUENCE_START_CODE);
279   }
280
281   demux->start_forward();
282   vstream->reset();
283
284   result = 0;    /* Read up to correct byte */
285   repeat_data = ref_frames = 0;
286   while( !result && !demux->eof() && demux->tell_byte() < target_byte ) {
287     result = read_frame_backend(0);
288   }
289   repeat_data = 0;
290
291   return 0;
292 }
293