prevent popup deactivation while button_down
[goodguy/history.git] / cinelerra-5.0 / cinelerra / fileogg.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  * 
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  * 
20  */
21
22 #include "asset.h"
23 #include "bcsignals.h"
24 #include "byteorder.h"
25 #include "clip.h"
26 #include "edit.h"
27 #include "file.h"
28 #include "fileogg.h"
29 #include "format.inc"
30 #include "guicast.h"
31 #include "language.h"
32 #include "mainerror.h"
33 #include "mutex.h"
34 #include "mwindow.inc"
35 #include "preferences.h"
36 #include "render.h"
37 #include "vframe.h"
38 #include "videodevice.inc"
39
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <fcntl.h>
43 #include <unistd.h>
44 #include <string.h>
45 #include <errno.h>
46
47 #define READ_SIZE 3*66000
48
49 /* This code was aspired by ffmpeg2theora */
50 /* Special thanks for help on this code goes out to j@v2v.cc */
51
52 int ogg_ret0, ogg_ret1, ogg_ret2;
53
54 FileOGG::FileOGG(Asset *asset, File *file)
55  : FileBase(asset, file)
56 {
57         if(asset->format == FILE_UNKNOWN)
58                 asset->format = FILE_OGG;
59         asset->byte_order = 0;
60         reset_parameters();
61 }
62
63 FileOGG::~FileOGG()
64 {
65         if (tf) 
66         {
67
68                 if (tf->videosync) 
69                 {
70                         ogg_sync_clear(&tf->videosync->sync);
71                         delete tf->videosync;
72                         theora_info_clear(&tf->ti);
73                         theora_comment_clear(&tf->tc);
74                 }
75                 if (tf->audiosync) 
76                 {
77                         ogg_sync_clear(&tf->audiosync->sync);
78                         delete tf->audiosync;
79                         vorbis_info_clear(&tf->vi);
80                         vorbis_comment_clear(&tf->vc);
81                 }
82                 delete tf;
83         }
84         if (temp_frame) delete temp_frame;
85         if (stream) close_file();
86         if(pcm_history)
87         {
88                 for(int i = 0; i < asset->channels; i++)
89                         delete [] pcm_history[i];
90                 delete [] pcm_history;
91         }
92
93         if (flush_lock) delete flush_lock;
94 }
95
96 void FileOGG::get_parameters(BC_WindowBase *parent_window,
97         Asset *asset,
98         BC_WindowBase* &format_window,
99         int audio_options,
100         int video_options)
101 {
102         if(audio_options)
103         {
104                 OGGConfigAudio *window = new OGGConfigAudio(parent_window, asset);
105                 format_window = window;
106                 window->create_objects();
107                 window->run_window();
108                 delete window;
109         }
110         else
111         if(video_options)
112         {
113                 OGGConfigVideo *window = new OGGConfigVideo(parent_window, asset);
114                 format_window = window;
115                 window->create_objects();
116                 window->run_window();
117                 delete window;
118         }
119 }
120
121 int FileOGG::reset_parameters_derived()
122 {
123         tf = 0;
124         temp_frame = 0;
125         stream = 0;
126         flush_lock = 0;
127         pcm_history = 0;
128         start_frame = 0;
129         return 0;
130 }
131
132 static int read_buffer(FILE *in, sync_window_t *sw, int buflen)
133 {
134         char *buffer = ogg_sync_buffer(&sw->sync, buflen);
135 //      printf("reading range: %lli - %lli\n", sw->file_bufpos, sw->file_bufpos + buflen);
136         sw->wlen = fread(buffer, 1, buflen, in);
137         ogg_sync_wrote(&sw->sync, sw->wlen);
138 //      printf("XX data: %c %c %c %c\n", sw->sync.data[0], sw->sync.data[1], sw->sync.data[2], sw->sync.data[3]);
139         sw->file_bufpos += sw->wlen;
140 //      printf("sb: %i\n",buffer);
141         return (sw->wlen);
142 }
143
144 static int read_buffer_at(FILE *in, sync_window_t *sw, int buflen, off_t filepos)
145 {
146 //      printf("seeking to %lli %lli\n", filepos, sw->file_bufpos);
147         fseeko(in, filepos, SEEK_SET);
148 //      if (sw->file_bufpos != filepos)
149 //      {
150                 sw->file_bufpos = filepos;
151                 sw->file_pagepos = filepos; // this one is not valid until sync_pageseek!
152                 ogg_sync_reset(&sw->sync);
153                         
154 //      }
155         return read_buffer(in, sw, buflen);
156 }
157
158 static int take_page_out_autoadvance(FILE *in, sync_window_t *sw, ogg_page *og)
159 {
160         while (1)
161         {
162                 int ret = ogg_sync_pageout(&sw->sync, og);
163                 if (ret > 0)
164                 {
165 //              printf("fpa: %lli\n", sw->file_pagepos);
166 // advance 'virtual' position
167                         sw->file_pagepos += og->header_len + og->body_len; 
168 //              printf("ret2: %i %i\n",ret, og->header_len + og->body_len); 
169                         return ret;
170                 }
171                 else if (ret < 0)
172                 {
173                         printf(_("FileOGG: Taking page out on nonsynced stream!\n"));
174                         return ret;
175                         
176                 } else
177                 {
178                         // need more data for page
179                         if ((ret = read_buffer(in, sw, READ_SIZE)) == 0) 
180                         {
181                                 printf(_("FileOGG: There is no more data in the file we are reading from\n"));
182                                 return 0;  // No more data
183                         }
184                 }
185         }
186         return 1;
187 }
188
189
190 // we never need to autoadvance when syncing, since our read chunks are larger than 
191 // maximum page size
192 static int sync_and_take_page_out(sync_window_t *sw, ogg_page *page)
193 {
194         page->header_len = 0;
195         page->body_len = 0;
196         page->header = 0;
197         page->body = 0;
198         int ret = ogg_sync_pageseek(&sw->sync, page);
199         if (ret < 0)
200         {
201                 sw->file_pagepos -= ret;
202         }
203         else if (ret > 0)
204         {
205                 sw->file_pagepos += ret;
206 //              printf("ret: %i %i\n",ret, page->header_len + page->body_len); 
207         }
208         return ret;
209 }
210
211 int FileOGG::open_file(int rd, int wr)
212 {
213         if (!tf)
214         {
215                 tf = new theoraframes_info_t;
216                 tf->audiosync = 0;
217                 tf->videosync = 0;
218         }
219
220
221         if(wr)
222         {
223
224
225                 if((stream = fopen(asset->path, "w+b")) == 0)
226                 {
227                         perror(_("FileOGG::open_file rdwr"));
228                         return 1;
229                 }
230
231                 tf->audio_bytesout = 0;
232                 tf->video_bytesout = 0;
233                 tf->videotime = 0;
234                 tf->audiotime = 0;
235
236                 tf->vpage_valid = 0;
237                 tf->apage_valid = 0;
238                 tf->apage_buffer_length = 0;
239                 tf->vpage_buffer_length = 0;
240                 tf->apage = NULL;
241                 tf->vpage = NULL;
242             tf->v_pkg=0;
243         tf->a_pkg=0;
244
245
246                 /* yayness.  Set up Ogg output stream */
247                 srand (time (NULL));
248
249                 if(asset->video_data)
250                 {
251                         ogg_stream_init (&tf->to, rand ());    /* oops, add one ot the above */
252                 
253                         theora_info_init (&tf->ti);
254                         
255                         tf->ti.frame_width = asset->width; 
256                         tf->ti.frame_height = asset->height;
257                         
258                         tf->ti.width = ((asset->width + 15) >>4)<<4; // round up to the nearest multiple of 16 
259                         tf->ti.height = ((asset->height + 15) >>4)<<4; // round up to the nearest multiple of 16
260                         if (tf->ti.width != tf->ti.frame_width || tf->ti.height != tf->ti.frame_height)
261                                 printf(_("FileOGG: WARNING: Encoding theora when width or height are not dividable by 16 is suboptimal\n"));
262                         
263                         tf->ti.offset_x = 0;
264                         tf->ti.offset_y = tf->ti.height - tf->ti.frame_height;
265                         tf->ti.fps_numerator = (unsigned int)(asset->frame_rate * 1000000);
266                         tf->ti.fps_denominator = 1000000;
267                         
268                         if (asset->aspect_ratio > 0)
269                         {
270                                 // Cinelerra uses frame aspect ratio, theora uses pixel aspect ratio
271                                 float pixel_aspect = asset->aspect_ratio / asset->width * asset->height;
272                                 tf->ti.aspect_numerator = (unsigned int)(pixel_aspect * 1000000);
273                                 tf->ti.aspect_denominator = 1000000;
274                         } else
275                         {
276                                 tf->ti.aspect_numerator = 1000000;
277                                 tf->ti.aspect_denominator = 1000000;
278                         }
279                         if(EQUIV(asset->frame_rate, 25) || EQUIV(asset->frame_rate, 50))
280                                 tf->ti.colorspace = OC_CS_ITU_REC_470BG;
281                         else if((asset->frame_rate > 29 && asset->frame_rate < 31) || (asset->frame_rate > 59 && asset->frame_rate < 61) )
282                                 tf->ti.colorspace = OC_CS_ITU_REC_470M;
283                         else
284                                 tf->ti.colorspace = OC_CS_UNSPECIFIED;
285
286                         if (asset->theora_fix_bitrate)
287                         {
288                                 tf->ti.target_bitrate = asset->theora_bitrate; 
289                                 tf->ti.quality = 0;
290                         } else
291                         {
292                                 tf->ti.target_bitrate = 0;
293                                 tf->ti.quality = asset->theora_quality;     // video quality 0-63
294                         }
295                         tf->ti.dropframes_p = 0;
296                         tf->ti.quick_p = 1;
297                         tf->ti.keyframe_auto_p = 1;
298                         tf->ti.keyframe_frequency = asset->theora_keyframe_frequency;
299                         tf->ti.keyframe_frequency_force = asset->theora_keyframe_force_frequency;
300                         tf->ti.keyframe_data_target_bitrate = (unsigned int) (tf->ti.target_bitrate * 1.5) ;
301                         tf->ti.keyframe_auto_threshold = 80;
302                         tf->ti.keyframe_mindistance = 8;
303                         tf->ti.noise_sensitivity = 1;           
304                         tf->ti.sharpness = 2;
305                         
306                                         
307                         if (theora_encode_init (&tf->td, &tf->ti))
308                         {
309                                 printf(_("FileOGG: initialization of theora codec failed\n"));
310                         }
311                 }
312                 /* init theora done */
313
314                 /* initialize Vorbis too, if we have audio. */
315                 if(asset->audio_data)
316                 {
317                         ogg_stream_init (&tf->vo, rand ());    
318                         vorbis_info_init (&tf->vi);
319                         /* Encoding using a VBR quality mode.  */
320                         int ret;
321                         if(!asset->vorbis_vbr) 
322                         {
323                                 ret = vorbis_encode_init(&tf->vi, 
324                                                         asset->channels, 
325                                                         asset->sample_rate, 
326                                                         asset->vorbis_max_bitrate, 
327                                                         asset->vorbis_bitrate,
328                                                         asset->vorbis_min_bitrate); 
329                         } else
330                         {
331                                 // Set true VBR as demonstrated by http://svn.xiph.org/trunk/vorbis/doc/vorbisenc/examples.html
332                                 ret = vorbis_encode_setup_managed(&tf->vi,
333                                         asset->channels, 
334                                         asset->sample_rate, 
335                                         -1, 
336                                         asset->vorbis_bitrate, 
337                                         -1);
338                                 ret |= vorbis_encode_ctl(&tf->vi, OV_ECTL_RATEMANAGE_AVG, NULL);
339                                 ret |= vorbis_encode_setup_init(&tf->vi);
340                         }
341
342                         if (ret)
343                         {
344                                 eprintf(_("The Vorbis encoder could not set up a mode according to\n"
345                                         "the requested quality or bitrate.\n\n"));
346                                 return 1;
347                         }
348
349                         vorbis_comment_init (&tf->vc); // comment is cleared lateron 
350                         vorbis_comment_add_tag (&tf->vc, (char*)"ENCODER", (char*)PROGRAM_NAME " " CINELERRA_VERSION);
351                         /* set up the analysis state and auxiliary encoding storage */
352                         vorbis_analysis_init (&tf->vd, &tf->vi);
353                         vorbis_block_init (&tf->vd, &tf->vb);
354
355                 }
356                 /* audio init done */
357
358                 /* write the bitstream header packets with proper page interleave */
359
360                 /* first packet will get its own page automatically */
361                 if(asset->video_data)
362                 {
363                         theora_encode_header (&tf->td, &tf->op);
364                         ogg_stream_packetin (&tf->to, &tf->op);
365                         if (ogg_stream_pageout (&tf->to, &tf->og) != 1)
366                         {
367                                 eprintf(_("Internal Ogg library error.\n"));
368                                 return 1;
369                         }
370                         fwrite (tf->og.header, 1, tf->og.header_len, stream);
371                         fwrite (tf->og.body, 1, tf->og.body_len, stream);
372
373                         /* create the remaining theora headers */
374                         theora_comment_init (&tf->tc);
375                         theora_comment_add_tag (&tf->tc, (char*)"ENCODER", (char*)PROGRAM_NAME " " CINELERRA_VERSION);
376                         theora_encode_comment (&tf->tc, &tf->op);
377                         ogg_stream_packetin (&tf->to, &tf->op);
378                         theora_comment_clear(&tf->tc);
379                         theora_encode_tables (&tf->td, &tf->op);
380                         ogg_stream_packetin (&tf->to, &tf->op);
381                 }
382                 if(asset->audio_data)
383                 {
384                         ogg_packet header;
385                         ogg_packet header_comm;
386                         ogg_packet header_code;
387
388                         vorbis_analysis_headerout (&tf->vd, &tf->vc, &header,
389                                        &header_comm, &header_code);
390                         ogg_stream_packetin (&tf->vo, &header);    /* automatically placed in its own page */
391                         vorbis_comment_clear(&tf->vc);
392                         if (ogg_stream_pageout (&tf->vo, &tf->og) != 1)
393                         {
394                                 eprintf(_("Internal Ogg library error.\n"));
395                                 return 1;
396                         }
397                         fwrite (tf->og.header, 1, tf->og.header_len, stream);
398                         fwrite (tf->og.body, 1, tf->og.body_len, stream);
399
400                         /* remaining vorbis header packets */
401                         ogg_stream_packetin (&tf->vo, &header_comm);
402                         ogg_stream_packetin (&tf->vo, &header_code);
403                 }
404
405                 /* Flush the rest of our headers. This ensures
406                  * the actual data in each stream will start
407                  * on a new page, as per spec. */
408                 while (1 && asset->video_data)
409                 {
410                         int result = ogg_stream_flush (&tf->to, &tf->og);
411                         if (result < 0)
412                         {
413                                 /* can't get here */
414                                 eprintf(_("Internal Ogg library error.\n"));
415                                 return 1;
416                         }
417                         if (result == 0)
418                                 break;
419                         fwrite (tf->og.header, 1, tf->og.header_len, stream);
420                         fwrite (tf->og.body, 1, tf->og.body_len, stream);
421                 }
422                 while (1 && asset->audio_data)
423                 {
424                         int result = ogg_stream_flush (&tf->vo, &tf->og);
425                         if (result < 0)
426                         {
427                                 /* can't get here */
428                                 eprintf(_("Internal Ogg library error.\n"));
429                                 return 1;
430                         }
431                         if (result == 0)
432                                 break;
433                         fwrite (tf->og.header, 1, tf->og.header_len, stream);
434                         fwrite (tf->og.body, 1, tf->og.body_len, stream);
435                 }
436                 flush_lock = new Mutex("OGGFile::Flush lock");
437 //              printf("End of headers at position: %lli\n", ftello(stream));
438         } else
439         if (rd)
440         {
441
442                 if((stream = fopen(asset->path, "rb")) == 0)
443                 {
444                         perror(_("FileOGG::open_file rdwr"));
445                         return 1;
446                 }
447
448                 /* get file length */
449                 struct stat file_stat;
450                 stat(asset->path, &file_stat);
451                 file_length = file_stat.st_size;
452
453                 /* start up Ogg stream synchronization layer */
454                 /* oy is used just here to parse header, we use separate syncs for video and audio*/
455                 sync_window_t oy;
456                 ogg_sync_init(&oy.sync);
457                 // make sure we init the position structures to zero
458                 read_buffer_at(stream, &oy, READ_SIZE, 0);
459
460
461                 /* init supporting Vorbis structures needed in header parsing */
462                 vorbis_info_init(&tf->vi);
463                 vorbis_comment_init(&tf->vc);
464
465
466                 /* init supporting Theora structures needed in header parsing */
467                 theora_comment_init(&tf->tc);
468                 theora_info_init(&tf->ti);
469
470
471
472                 /* Ogg file open; parse the headers */
473                 /* Only interested in Vorbis/Theora streams */
474                 int stateflag = 0;
475                 int theora_p = 0;
476                 int vorbis_p = 0;
477                 while(!stateflag)
478                 {
479
480
481 //                      int ret = read_buffer(stream, &oy, 4096);
482                         TRACE("FileOGG::open_file 60")
483 //                      if(ret == 0)
484 //                              break;
485                         
486                         while(take_page_out_autoadvance(stream, &oy, &tf->og) > 0)
487                         {
488                                 ogg_stream_state test;
489
490                                 /* is this a mandated initial header? If not, stop parsing */
491                                 if(!ogg_page_bos(&tf->og))
492                                 {
493                                         /* don't leak the page; get it into the appropriate stream */
494                                 //      queue_page(&tf->og);
495                                         if(theora_p)ogg_stream_pagein(&tf->to, &tf->og);
496                                         if(vorbis_p)ogg_stream_pagein(&tf->vo, &tf->og);
497                                 
498                                         stateflag = 1;
499                                         break;
500                                 }
501
502                                 ogg_stream_init(&test, ogg_page_serialno(&tf->og));
503                                 ogg_stream_pagein(&test, &tf->og);
504                                 ogg_stream_packetout(&test, &tf->op);
505
506                                 /* identify the codec: try theora */
507                                 if(!theora_p && theora_decode_header(&tf->ti, &tf->tc, &tf->op)>=0)
508                                 {
509                                         /* it is theora */
510                                         memcpy(&tf->to, &test, sizeof(test));
511                                         theora_p = 1;
512         // find out granule shift - from liboggz's oggz_auto.c
513                                         unsigned char * header = tf->op.packet;
514                                         theora_keyframe_granule_shift = (char) ((header[40] & 0x03) << 3);
515                                         theora_keyframe_granule_shift |= (header[41] & 0xe0) >> 5;
516
517                                 } else if(!vorbis_p && vorbis_synthesis_headerin(&tf->vi, &tf->vc, &tf->op)>=0)
518                                 {
519                                         /* it is vorbis */
520                                         memcpy(&tf->vo, &test, sizeof(test));
521                                         vorbis_p = 1;
522                                 } else 
523                                 {
524                                         /* whatever it is, we don't care about it */
525                                         ogg_stream_clear(&test);
526                                 }
527                         }
528                 /* fall through to non-bos page parsing */
529                 }
530
531
532                 /* we're expecting more header packets. */
533                 while((theora_p && theora_p < 3) || (vorbis_p && vorbis_p < 3))
534                 {
535                         int ret;
536
537                         /* look for further theora headers */
538                         while(theora_p && (theora_p < 3) && (ret = ogg_stream_packetout(&tf->to, &tf->op)))
539                         {
540                                 if(ret < 0)
541                                 {
542                                         eprintf(_("FileOGG: Error parsing Theora stream headers; corrupt stream?\n"));
543                                         return 1;
544                                 }
545                                 if(theora_decode_header(&tf->ti, &tf->tc, &tf->op))
546                                 {
547                                         printf(_("FileOGG: Error parsing Theora stream headers; corrupt stream?\n"));
548                                         return 1;
549                                 }
550                                 theora_p++;
551                                 if(theora_p == 3) 
552                                         break;
553                         }
554
555                         /* look for more vorbis header packets */
556                         while(vorbis_p && (vorbis_p < 3) && (ret = ogg_stream_packetout(&tf->vo, &tf->op)))
557                         {
558                                 if(ret<0)
559                                 {
560                                         eprintf(_("FileOGG: Error parsing Vorbis stream headers; corrupt stream?\n"));
561                                         return 1;
562                                 }
563                                 if (vorbis_synthesis_headerin(&tf->vi, &tf->vc, &tf->op))
564                                 {
565                                         eprintf(_("FileOGG: Error parsing Vorbis stream headers; corrupt stream?\n"));
566                                         return 1;
567                                 }
568                                 vorbis_p++;
569                                 if (vorbis_p == 3)
570                                         break;
571                         }
572
573                         if (vorbis_p == 3 && theora_p == 3) 
574                                 break;
575                         /* The header pages/packets will arrive before anything else we
576                             care about, or the stream is not obeying spec */
577
578                         if(take_page_out_autoadvance(stream, &oy, &tf->og) > 0)
579                         {
580 //                              queue_page(&tf->og); /* demux into the appropriate stream */
581                                 if(theora_p) ogg_stream_pagein(&tf->to, &tf->og);
582                                 if(vorbis_p) ogg_stream_pagein(&tf->vo, &tf->og);
583
584                         } else
585                         {
586                                 eprintf(_("FileOGG: End of file while searching for codec headers.\n"));
587                                 return 1;
588                         }
589                 }
590                 // Remember where the real data begins for later seeking purposes
591                 filedata_begin = oy.file_pagepos; 
592
593
594
595                 /* and now we have it all.  initialize decoders */
596                 if(theora_p)
597                 {
598                         int ret;
599
600 // WORKAROUND for bug in alpha4 version of theora:
601                         tf->td.internal_encode = 0;
602
603                         ret = theora_decode_init(&tf->td, &tf->ti);
604                         if( ret ) printf("theora_decode_init ret=%d\n", ret);
605                         double fps = (double)tf->ti.fps_numerator/tf->ti.fps_denominator;
606 /*                      printf("FileOGG: Ogg logical stream %x is Theora %dx%d %.02f fps\n",
607                                 (unsigned int)tf->to.serialno, tf->ti.width, tf->ti.height, 
608                                 fps);
609 */
610 /*
611 Not yet available in alpha4, we assume 420 for now
612
613                         switch(tf->ti.pixelformat)
614                         {
615                                 case OC_PF_420: printf(" 4:2:0 video\n"); break;
616                                 case OC_PF_422: printf(" 4:2:2 video\n"); break;
617                                 case OC_PF_444: printf(" 4:4:4 video\n"); break;
618                                 case OC_PF_RSVD:
619                                 default:
620                                         printf(" video\n  (UNKNOWN Chroma sampling!)\n");
621                                 break;
622                         }
623 */
624
625                         theora_cmodel = BC_YUV420P;
626                         
627                         if(tf->ti.width!=tf->ti.frame_width || tf->ti.height!=tf->ti.frame_height)
628                                 printf("FileOGG::  Frame content is %dx%d with offset (%d,%d), We do not support this yet.\n",
629                                 tf->ti.frame_width, tf->ti.frame_height, tf->ti.offset_x, tf->ti.offset_y);
630
631                         tf->videosync = new sync_window_t;
632                         ogg_sync_init(&tf->videosync->sync);
633                         tf->videosync->wlen = 0;
634
635                         ret = ogg_get_first_page(tf->videosync, tf->to.serialno, &tf->videopage);
636                         if( !ret ) printf("ogg_get_first_page ret=%d\n", ret);
637                         ogg_packet op;
638
639                         // we have headers already decoded, so just skip them
640                         ogg_stream_reset(&tf->to);
641                         ogg_stream_pagein(&tf->to, &tf->videopage);
642                         while (1)
643                         {
644                                 while (ogg_stream_packetpeek(&tf->to, NULL) != 1)
645                                 {
646                                         if (!ogg_get_next_page(tf->videosync, tf->to.serialno, &tf->videopage))
647                                         {
648                                                 printf(_("FileOGG: Cannot find next page while looking for first non-header packet\n"));
649                                                 return 1;
650                                         }
651                                         ogg_stream_pagein(&tf->to, &tf->videopage);
652                                 }
653                                 ogg_stream_packetout(&tf->to, &op);
654                                 if (!theora_packet_isheader(&op))
655                                         break;
656                         }
657                         // now get to the page of the finish of the first packet
658                         while (ogg_page_packets(&tf->videopage) == 0) 
659                         {
660                                 if (ogg_page_granulepos(&tf->videopage) != -1)
661                                 {
662                                         printf(_("FileOGG: Broken ogg file - broken page: ogg_page_packets == 0 and granulepos != -1\n"));
663                                         return 1;
664                                 }
665                                 ogg_get_next_page(tf->videosync, tf->to.serialno, &tf->videopage);
666                         }
667                         // FIXME - LOW PRIORITY - start counting at first decodable keyframe!
668                         // but then we have to fix a/v sync somehow
669                         start_frame = (int64_t) (theora_granule_frame (&tf->td, ogg_page_granulepos(&tf->videopage)) - ogg_page_packets(&tf->videopage)) + 1;
670
671                         ret = ogg_get_last_page(tf->videosync, tf->to.serialno, &tf->videopage);
672                         last_frame = (int64_t) (theora_granule_frame (&tf->td, ogg_page_granulepos(&tf->videopage)));
673                         asset->video_length = last_frame - start_frame + 1;
674 //                      printf("FileOGG:: first frame: %lli, last frame: %lli, video length: %lli\n", start_frame, last_frame, asset->video_length);
675                         
676                         asset->layers = 1;
677                         // FIXME - LOW PRIORITY Cinelerra does not honor the frame_width and frame_height
678                         asset->width = tf->ti.width;
679                         asset->height = tf->ti.height;
680 // Don't want a user configured frame rate to get destroyed
681                         if(!asset->frame_rate)
682                                 asset->frame_rate = fps;
683
684         /*              ogg_get_page_of_frame(tf->videosync, tf->to.serialno, &og, 0 +start_frame);
685                         ogg_get_page_of_frame(tf->videosync, tf->to.serialno, &og, 1 +start_frame);
686                         ogg_get_page_of_frame(tf->videosync, tf->to.serialno, &og, 5 +start_frame);
687                         ogg_get_page_of_frame(tf->videosync, tf->to.serialno, &og, 206 +start_frame);
688                         ogg_get_page_of_frame(tf->videosync, tf->to.serialno, &og, 207 +start_frame);
689                         ogg_get_page_of_frame(tf->videosync, tf->to.serialno, &og, 208 +start_frame);
690
691                         int64_t kf;
692                         ogg_seek_to_keyframe(tf->videosync, tf->to.serialno, 0 + start_frame, &kf);
693                         ogg_seek_to_keyframe(tf->videosync, tf->to.serialno, 1 + start_frame, &kf);
694                         ogg_seek_to_keyframe(tf->videosync, tf->to.serialno, 5 + start_frame, &kf);
695                         ogg_seek_to_keyframe(tf->videosync, tf->to.serialno, 66 + start_frame, &kf);
696                         //printf("Keyframe: %lli\n", kf);
697                         ogg_seek_to_keyframe(tf->videosync, tf->to.serialno, 1274 + start_frame, &kf);
698 */
699         
700                         set_video_position(0); // make sure seeking is done to the first sample
701                         ogg_frame_position = -10;
702                         asset->video_data = 1;
703                         strncpy(asset->vcodec, "theo", 4);
704
705
706 //                  report_colorspace(&ti);
707 //                  dump_comments(&tc);
708                 } else 
709                 {
710                         /* tear down the partial theora setup */
711                         theora_info_clear(&tf->ti);
712                         theora_comment_clear(&tf->tc);
713                 }
714
715
716                 if(vorbis_p)
717                 {
718                         vorbis_synthesis_init(&tf->vd, &tf->vi);
719                         vorbis_block_init(&tf->vd, &tf->vb);
720 /*                      eprintf("FileOGG: Ogg logical stream %x is Vorbis %d channel %d Hz audio.\n",
721                                 (unsigned int)tf->vo.serialno, tf->vi.channels, (int)tf->vi.rate);
722 */                      
723                         /* init audio_sync structure */
724                         tf->audiosync = new sync_window_t;
725                         ogg_sync_init(&tf->audiosync->sync);
726                         tf->audiosync->wlen = 0;
727
728                         ogg_get_first_page(tf->audiosync, tf->vo.serialno, &tf->audiopage);
729                         ogg_packet op;
730                         ogg_stream_reset(&tf->vo);
731                         // FIXME - LOW PRIORITY should be getting pages until one has granulepos,
732                         //   probably never happens in pracitce
733                         ogg_ret2 = ogg_stream_pagein(&tf->vo, &tf->audiopage);
734                         ogg_int64_t accumulated = 0;
735                         long lastblock = -1;
736                         int result;
737                         while((result = ogg_stream_packetout(&tf->vo, &op)))
738                         {
739                                 if(result > 0)
740                                 { // ignore holes 
741                                         long thisblock =  vorbis_packet_blocksize(&tf->vi, &op);
742                                         if(lastblock != -1)
743                                                 accumulated += (lastblock + thisblock) >> 2;
744                                         lastblock = thisblock;
745                                 }
746                         }
747                         start_sample = ogg_page_granulepos(&tf->audiopage) - accumulated;
748 /*
749                         printf("Begin: %lli, To byte: %lli,  granule: %lli, serialno: %x\n", 
750                                         tf->audiosync->file_pagepos_found,
751                                         tf->audiosync->file_pagepos_found + tf->audiopage.body_len + tf->audiopage.header_len,
752                                         ogg_page_granulepos(&tf->audiopage), 
753                                         ogg_page_serialno(&tf->audiopage));
754                         while (ogg_get_next_page(tf->audiosync, tf->vo.serialno, &tf->audiopage))
755                                 printf("At byte: %lli, To byte: %lli,  granule: %lli, serialno: %x\n", 
756                                         tf->audiosync->file_pagepos_found,
757                                         tf->audiosync->file_pagepos_found + tf->audiopage.body_len + tf->audiopage.header_len,
758                                         ogg_page_granulepos(&tf->audiopage), 
759                                         ogg_page_serialno(&tf->audiopage));
760 */
761
762                         ogg_ret1 = ogg_get_last_page(tf->audiosync, tf->vo.serialno, &tf->audiopage);
763                         last_sample = ogg_page_granulepos(&tf->audiopage);
764                         asset->audio_length = last_sample - start_sample;
765                                                 
766 /*                      printf("FileOGG:: First sample: %lli, last_sample: %lli\n", start_sample, last_sample);
767                         printf("FileOGG:: audio length: samples: %lli, playing time: %f\n", asset->audio_length, 1.0 * asset->audio_length / tf->vi.rate);
768 */                      
769 /*                      printf("End: %lli, To byte: %lli,  granule: %lli, serialno: %x\n", 
770                                         tf->audiosync->file_pagepos_found,
771                                         tf->audiosync->file_pagepos_found + tf->audiopage.body_len + tf->audiopage.header_len,
772                                         ogg_page_granulepos(&tf->audiopage), 
773                                         ogg_page_serialno(&tf->audiopage));
774                         while (ogg_get_prev_page(tf->audiosync, tf->vo.serialno, &tf->audiopage))
775                                 printf("At byte: %lli, To byte: %lli,  granule: %lli, serialno: %x\n", 
776                                         tf->audiosync->file_pagepos_found,
777                                         tf->audiosync->file_pagepos_found + tf->audiopage.body_len + tf->audiopage.header_len,
778                                         ogg_page_granulepos(&tf->audiopage), 
779                                         ogg_page_serialno(&tf->audiopage));
780 */
781                         
782 /*                      ogg_get_page_of_sample(tf->audiosync, tf->vo.serialno, &tf->audiopage, 0);
783                         ogg_get_page_of_sample(tf->audiosync, tf->vo.serialno, &tf->audiopage, 1);
784                         ogg_get_page_of_sample(tf->audiosync, tf->vo.serialno, &tf->audiopage, 50);
785                         ogg_get_page_of_sample(tf->audiosync, tf->vo.serialno, &tf->audiopage, 5000);
786                         ogg_get_page_of_sample(tf->audiosync, tf->vo.serialno, &tf->audiopage, 30000);
787                         ogg_get_page_of_sample(tf->audiosync, tf->vo.serialno, &tf->audiopage, 50000);
788                         ogg_get_page_of_sample(tf->audiosync, tf->vo.serialno, &tf->audiopage, 90000);
789                         ogg_get_page_of_sample(tf->audiosync, tf->vo.serialno, &tf->audiopage, 95999);
790                         ogg_get_page_of_sample(tf->audiosync, tf->vo.serialno, &tf->audiopage, 96000);
791                         ogg_seek_to_sample(tf->audiosync, tf->vo.serialno, 0);
792                         ogg_seek_to_sample(tf->audiosync, tf->vo.serialno, 1);
793                         ogg_seek_to_sample(tf->audiosync, tf->vo.serialno, 5000);
794                         ogg_seek_to_sample(tf->audiosync, tf->vo.serialno, 30000);
795                         ogg_seek_to_sample(tf->audiosync, tf->vo.serialno, 50000);
796                         ogg_seek_to_sample(tf->audiosync, tf->vo.serialno, 90000);
797                         ogg_seek_to_sample(tf->audiosync, tf->vo.serialno, 95999);
798                         ogg_seek_to_sample(tf->audiosync, tf->vo.serialno, 96000);
799 */                      
800                         asset->channels = tf->vi.channels;
801                         if(!asset->sample_rate)
802                                 asset->sample_rate = tf->vi.rate;
803                         asset->audio_data = 1;
804                         
805
806                         ogg_sample_position = -10;
807                         set_audio_position(0); // make sure seeking is done to the first sample
808                         strncpy(asset->acodec, "vorb", 4);
809
810
811                 } else 
812                 {
813                         /* tear down the partial vorbis setup */
814                         vorbis_info_clear(&tf->vi);
815                         vorbis_comment_clear(&tf->vc);
816                 }
817
818                 ogg_sync_clear(&oy.sync);
819
820         }
821         return 0;
822 }
823
824 int FileOGG::ogg_get_prev_page(sync_window_t *sw, long serialno, ogg_page *og)
825 {
826         ogg_page page;
827         off_t filepos = sw->file_pagepos_found - READ_SIZE;
828         int first_page_offset = 0;
829         int done = 0;   
830         int read_len = READ_SIZE;
831
832 //      printf("fp: %lli pagepos found: %lli\n", filepos, sw->file_pagepos_found);
833         while (!done)
834         {
835                 if (filepos < 0)
836                 {
837 //                      read_len = read_len - (filedata_begin - filepos);
838                         read_len = read_len + filepos;
839                         filepos = 0;
840                 }
841                 if (read_len <= 0) 
842                         return 0;
843                 int have_read = read_buffer_at(stream, sw, read_len, filepos);
844                 
845 //              printf("reading at %lli, len: %i, read: %i, pagepos: %lli, pageposfound: %lli\n", filepos, read_len, have_read, sw->file_pagepos, sw->file_pagepos_found);
846 //              printf("Buffer position: %lli\n", sw->file_bufpos);
847 //              printf("SS: storage: %i, fill: %i, returned: %i\n", sw->sync.storage, sw->sync.fill, sw->sync.returned);
848 //              printf("US: unsynced%i, headrebytes: %i, bodybyes: %i\n", sw->sync.unsynced, sw->sync.headerbytes, sw->sync.bodybytes);
849 //              printf("data: %c %c %c %c\n", sw->sync.data[0], sw->sync.data[1], sw->sync.data[2], sw->sync.data[3]);
850                 if (!have_read) 
851                         return 0;
852                 
853 // read all pages in the buffer
854                 int page_offset = 0;
855                 int page_length = 0;
856                 int first_page = 1;
857                 while (first_page || page_length) 
858                 {
859                         // if negative, skip bytes
860                         while ((page_length = sync_and_take_page_out(sw, &page)) < 0)
861                         {
862                                 page_offset -= page_length;
863                                                 
864 //                              if (filepos == 0)
865 //                                      printf("BBBb page_len: %i\n", page_length);
866                         }
867 //                      if (filepos == 0 && page_length)
868 //                      {
869 //                              printf("AAAAAAAAAAAAAAAAAAAAAAAAAaaa\n");
870 //                              printf("pp: %lli %x\n", sw->file_pagepos, ogg_page_serialno(&page));
871 //                      }
872                         if (first_page)
873                                 first_page_offset = page_offset;
874                         first_page = 0;
875 //                      printf("pl: %i, serial: %x iscem: %x\n", page_length, ogg_page_serialno(&page), serialno);
876                         if (page_length && ogg_page_serialno(&page) == serialno)
877                         {
878                                 // we will copy every page until last page in this buffer
879                                 done = 1;
880                                 
881                                 sw->file_pagepos_found = sw->file_pagepos - page.header_len - page.body_len;
882 //                              printf("got it : %lli %i %i\n", sw->file_pagepos, page.header_len, page.body_len);
883                                 memcpy(og, &page, sizeof(page));
884                         }
885                 }
886 //              printf("fpo: %i\n", first_page_offset);
887                 filepos += first_page_offset - READ_SIZE;
888         }
889         
890 //      printf("finished\n");
891         if (done) 
892                 return 1;
893         else 
894                 return 0;
895 }
896
897 int FileOGG::ogg_get_last_page(sync_window_t *sw, long serialno, ogg_page *og)
898 {
899         ogg_page page;
900         off_t filepos = file_length - READ_SIZE;
901         if (filepos < 0) 
902                 filepos = 0;
903
904         int first_page_offset = 0;
905         int done = 0;   
906         while (!done && filepos >= 0)
907         {
908                 //int readlen =
909                   read_buffer_at(stream, sw, READ_SIZE, filepos);
910
911 // read all pages in the buffer
912                 int page_offset = 0;
913                 int page_length = 0;
914                 int first_page = 1;
915                 while (first_page || page_length) 
916                 {
917                         // if negative, skip bytes
918                         while ((page_length = sync_and_take_page_out(sw, &page)) < 0)
919                                         page_offset -= page_length;
920                         if (first_page)
921                                 first_page_offset = page_offset;
922                         first_page = 0;
923                         if (page_length && ogg_page_serialno(&page) == serialno)
924                         {
925                                 // we will copy every page until last page in this buffer
926                                 done = 1;
927                                 sw->file_pagepos_found = sw->file_pagepos - page.header_len - page.body_len;
928                                 memcpy(og, &page, sizeof(page));
929                         }
930                 }
931                 filepos = filepos + first_page_offset - READ_SIZE;              
932         }
933         
934         if (done) 
935                 return 1;
936         else 
937                 return 0;
938 }
939
940 int FileOGG::ogg_get_first_page(sync_window_t *sw, long serialno, ogg_page *og)
941 {
942 //      printf("FileOGG:: Seeking to first page at %lli\n", filedata_begin);
943         read_buffer_at(stream, sw, READ_SIZE, 0);
944 // we don't even need to sync since we _know_ it is right
945         return (ogg_get_next_page(sw, serialno, og));
946 }
947
948 int FileOGG::ogg_seek_to_databegin(sync_window_t *sw, long serialno)
949 {
950         
951 //      printf("FileOGG:: Seeking to first page at %lli\n", filedata_begin);
952         read_buffer_at(stream, sw, READ_SIZE, filedata_begin);
953 // we don't even need to sync since we _know_ it is right
954         return (0);
955 }
956
957 int FileOGG::ogg_get_next_page(sync_window_t *sw, long serialno, ogg_page *og)
958 {
959         while (take_page_out_autoadvance(stream, sw, og) > 0)
960         { 
961                 if (ogg_page_serialno(og) == serialno)
962                 {
963                         sw->file_pagepos_found = sw->file_pagepos - og->header_len - og->body_len;
964                         return 1;
965                 }
966         }
967         return 0;
968 }
969
970 int FileOGG::ogg_sync_and_get_next_page(sync_window_t *sw, long serialno, ogg_page *og)
971 {
972 // TODO: Put better error reporting inhere
973         int ret;
974         while ((ret = sync_and_take_page_out(sw, og)) < 0)
975         {
976                 // do nothing;
977         }
978         if (ret == 0) 
979                 return 0;
980         if (ogg_page_serialno(og) == serialno)
981         {
982                 sw->file_pagepos_found = sw->file_pagepos - og->header_len - og->body_len;
983                 return 1;
984         }
985         while (ogg_get_next_page(sw, serialno, og))
986                 if (ogg_page_serialno(og) == serialno)
987                 {
988                         sw->file_pagepos_found = sw->file_pagepos - og->header_len - og->body_len;
989                         return 1;
990                 }
991         
992         return 0;
993 }
994 // Returns:
995 // >= 0, number of sample within a page
996 // <  0 error
997 int FileOGG::ogg_get_page_of_sample(sync_window_t *sw, long serialno, ogg_page *og, int64_t sample)
998 {
999 // First make an educated guess about position
1000         if (sample >= asset->audio_length + start_sample)
1001         {
1002                 printf(_("FileOGG: Illegal seek beyond end of samples\n"));
1003                 return 0;
1004         }
1005         off_t educated_guess = filedata_begin + (file_length - filedata_begin) * (sample - start_sample) / asset->audio_length - READ_SIZE;
1006         if (educated_guess < 0) 
1007                 educated_guess = 0;
1008 //      printf("My educated guess: %lli\n", educated_guess); 
1009 // now see if we won
1010         read_buffer_at(stream, sw, READ_SIZE, educated_guess);
1011         ogg_sync_and_get_next_page(sw, serialno, og);
1012         int64_t end_sample = ogg_page_granulepos(og);
1013         // linear seek to the sample
1014         int64_t start_sample = 0;
1015 // TODO: Use bisection also
1016 //      printf("Next page granulepos: %lli, pagepos: %lli\n", end_sample, sw->file_pagepos_found);
1017         if (end_sample <= sample)
1018         {
1019         // scan forward
1020                 while (end_sample <= sample)
1021                 {
1022                         ogg_get_next_page(sw, serialno, og); 
1023                         start_sample = end_sample;
1024                         end_sample = ogg_page_granulepos(og);
1025                 }
1026                 ogg_get_prev_page(sw, serialno, og);
1027                 while (ogg_page_continued(og) && ogg_page_packets(og) == 1)
1028                         ogg_get_prev_page(sw, serialno, og);
1029         } else
1030         {
1031         // scan backward
1032                 start_sample = end_sample;
1033                 while (start_sample > sample || (ogg_page_continued(og) && 
1034                         ogg_page_packets(og) == 1))
1035                 {
1036 //                      printf("get prev page: %lli pagepos:%lli\n", ogg_page_granulepos(og), sw->file_pagepos_found);
1037                         ogg_get_prev_page(sw, serialno, og);
1038                         end_sample = start_sample;
1039                         start_sample = ogg_page_granulepos(og);
1040                 }
1041         // go forward one page at the end
1042
1043         }
1044         
1045 //      printf("For sample %lli we need to start decoding on page with granulepos: %lli\n", sample, ogg_page_granulepos(og));
1046         return 1;
1047 }
1048
1049 // seeks, so next sample returned will be the correct one
1050 // sample here is still the vorbis sample number (= cinelerra sample number + start_sample)
1051 // reinits the decoding engine
1052
1053 int FileOGG::ogg_seek_to_sample(sync_window_t *sw, long serialno, int64_t sample)
1054 {
1055         // MAYBE FIXME - find out if we really are decoding previous two packets or not
1056         // get to the sample
1057         ogg_page og;
1058         ogg_packet op;
1059 //      printf("Calling get page of sample\n");
1060         if (!ogg_get_page_of_sample(sw, serialno, &og, sample))
1061         {
1062                 printf(_("FileOGG: Seeking to sample's page failed\n"));
1063                 return 0;
1064         }
1065 //      printf("Pagepos: %lli\n", sw->file_pagepos);
1066         vorbis_synthesis_restart(&tf->vd);
1067         ogg_stream_reset(&tf->vo);
1068         ogg_stream_pagein(&tf->vo, &og);
1069         int sync = 0;
1070 //      printf("seeking to sample : %lli , starting at page with gpos: %lli\n", sample, ogg_page_granulepos(&og));
1071         
1072         int64_t current_comming_sample = -1;
1073         while (1) 
1074         {
1075         
1076                 // make sure we have a packet ready
1077                 while (ogg_stream_packetpeek(&tf->vo, NULL) != 1)
1078                 {
1079                         if (!ogg_get_next_page(sw, serialno, &og))
1080                         {
1081                                 printf(_("FileOGG: Cannot find next page while seeking\n"));
1082                                 return 0;
1083                         }
1084                         ogg_stream_pagein(&tf->vo, &og);
1085                 }
1086                 ogg_stream_packetout(&tf->vo, &op);
1087                 if (sync)
1088                 {
1089                         
1090                         if(!vorbis_synthesis(&tf->vb, &op))
1091                         {
1092                                 ogg_ret0 = vorbis_synthesis_blockin(&tf->vd, &tf->vb);
1093                                 int64_t previous_comming_sample = current_comming_sample;
1094                                 current_comming_sample += vorbis_synthesis_pcmout(&tf->vd, NULL);
1095                                 if (current_comming_sample > sample)
1096                                 {
1097                                         vorbis_synthesis_read(&tf->vd, (sample - previous_comming_sample));
1098 //                                      printf("WE GOT IT, samples already decoded: " _LD "\n", vorbis_synthesis_pcmout(&tf->vd,NULL));
1099                                         return 1; // YAY next sample read is going to be ours, sexy!
1100                                 } else
1101                                 {
1102                                         // discard decoded data before current sample
1103                                         vorbis_synthesis_read(&tf->vd, (current_comming_sample - previous_comming_sample));
1104                                         
1105                                 }
1106                         }
1107                 }
1108                 if (!sync && op.granulepos >= 0)
1109                 {
1110                         sync = 1;
1111                         current_comming_sample = op.granulepos;
1112                         if(!vorbis_synthesis(&tf->vb, &op))
1113                         {
1114                                 vorbis_synthesis_blockin(&tf->vd, &tf->vb);
1115                                 if (vorbis_synthesis_pcmout(&tf->vd, NULL) != 0)
1116                                 {
1117                                         printf(_("FileOGG: Something wrong while trying to seek\n"));
1118                                         return 0;
1119                                 }
1120                         
1121                         }
1122                         
1123                 }
1124         }
1125         
1126         
1127         return 0;
1128 }
1129
1130 int FileOGG::ogg_get_page_of_frame(sync_window_t *sw, long serialno, ogg_page *og, int64_t frame)
1131 {
1132         if (frame >= asset->video_length + start_frame)
1133         {
1134                 printf(_("FileOGG: Illegal seek beyond end of frames\n"));
1135                 return 0;
1136         }
1137 //      printf("frame: %lli start frame: %lli\n", frame, start_frame);
1138 //      printf("file_length: %lli filedata_begin: %lli\n", file_length, filedata_begin);
1139         off_t educated_guess = filedata_begin + (file_length - filedata_begin) * (frame - start_frame) / asset->video_length - READ_SIZE/2;
1140 //      educated_guess += 100000;
1141         if (educated_guess > file_length - READ_SIZE)
1142                 educated_guess = file_length - READ_SIZE;
1143         if (educated_guess < filedata_begin) 
1144                 educated_guess = filedata_begin;
1145 //      printf("My educated guess: %lli\n", educated_guess); 
1146 // now see if we won
1147         read_buffer_at(stream, sw, READ_SIZE, educated_guess);
1148         if( !ogg_sync_and_get_next_page(sw, serialno, og) ) {
1149                 printf(_("FileOGG: ogg_sync_and_get_next_page failed\n"));
1150                 return 0;
1151         }
1152         int64_t pageend_frame;
1153         //int read_back = 0;
1154         // find the page with "real" ending
1155         while ((pageend_frame = ogg_page_granulepos(og)) == -1)
1156         {
1157                 if (ogg_get_next_page(sw, serialno, og) == 0) 
1158                 {
1159                         //read_back = 1;
1160                         break;
1161                 } 
1162         }
1163         pageend_frame = theora_granule_frame(&tf->td, ogg_page_granulepos(og));
1164
1165         // FIXME - MEDIUM PRIORITY: read back if we've gone too far and no page of our serialno at all can be found
1166
1167         
1168         // linear seek to the sample
1169 // TODO: Use bisection also
1170 //      printf("Next page granulepos: %lli, pagepos: %lli\n", end_sample, sw->file_pagepos_found);
1171         //int discard_packets = 0;
1172         int missp = 0;
1173         int missm = 0;
1174         if (pageend_frame <= frame)
1175         {
1176         // scan forward
1177                 while (pageend_frame < frame)
1178                 {
1179                         do {
1180                                 ogg_get_next_page(sw, serialno, og); 
1181                         } while (ogg_page_packets(og) == 0);
1182                         pageend_frame = theora_granule_frame(&tf->td, ogg_page_granulepos(og));
1183                         missp++;
1184                 }
1185                 // go back if this frame starts on previous page
1186                 if (ogg_page_continued(og) && pageend_frame - ogg_page_packets(og) == frame - 1)
1187                 {
1188                         do {
1189                                 ogg_get_prev_page(sw, serialno, og); 
1190                         } while (ogg_page_packets(og) == 0 && ogg_page_continued(og));          
1191                 }
1192                 pageend_frame = theora_granule_frame(&tf->td, ogg_page_granulepos(og));
1193         } else
1194         {
1195         // scan backward
1196                 int64_t first_frame_on_page = theora_granule_frame(&tf->td, ogg_page_granulepos(og)) - ogg_page_packets(og) + 2;
1197                 if (!ogg_page_continued(og))
1198                         first_frame_on_page--;
1199                 while (first_frame_on_page > frame)
1200                 {
1201 //                      printf("get prev page: %lli pagepos:%lli\n", ogg_page_granulepos(og), sw->file_pagepos_found);
1202                         do {
1203                                 ogg_get_prev_page(sw, serialno, og); 
1204                         } while (ogg_page_packets(og) == 0 && ogg_page_continued(og));          
1205                         missm++;
1206 //                      pageend_frame = theora_granule_frame(&tf->td, ogg_page_granulepos(og));
1207                         first_frame_on_page = theora_granule_frame(&tf->td, ogg_page_granulepos(og)) - ogg_page_packets(og) + 2;
1208                         if (!ogg_page_continued(og))
1209                                 first_frame_on_page--;
1210                 }
1211         }
1212 //      printf("Miss plus: %i, miss minus: %i\n", missp, missm);
1213 //      printf("last frame of page with frame : %lli\n", pageend_frame);
1214         return 1;                       
1215 }
1216
1217
1218 int FileOGG::ogg_seek_to_keyframe(sync_window_t *sw, long serialno, int64_t frame, int64_t *keyframe_number)
1219 {
1220         ogg_page og;
1221         ogg_packet op;
1222 //      printf("Searching for the proper position to start decoding frame %lli\n", frame);
1223         if (!ogg_get_page_of_frame(sw, serialno, &og, frame))
1224         {
1225                 printf(_("FileOGG: Seeking to frame failed\n"));
1226                 return 0;
1227         }
1228         // TODO: if the frame we are looking for continoues on the next page, we don't need to do this
1229         // Now go to previous page in order to find out the granulepos
1230         // Don't do it in case this is the first page.
1231 //      printf("GP: %lli\n", ogg_page_granulepos(&og));
1232         int64_t granulepos = ogg_page_granulepos(&og);
1233         int64_t iframe = granulepos >> theora_keyframe_granule_shift;
1234         //int64_t pframe = granulepos - (iframe << theora_keyframe_granule_shift);
1235         // check if maybe iframe is known from this page already
1236         if (granulepos != -1 && iframe <= frame)
1237         {
1238                 // optimisation, iframe is already known from this page
1239         } else
1240         {
1241                 // get previous page so we will get the iframe number 
1242                 do {
1243                         ogg_get_prev_page(sw, serialno, &og); 
1244                 } while (ogg_page_packets(&og) == 0);           
1245
1246                 granulepos = ogg_page_granulepos(&og);
1247                 iframe = granulepos >> theora_keyframe_granule_shift;
1248                 //pframe = granulepos - (iframe << theora_keyframe_granule_shift);
1249         }
1250         int64_t first_frame_on_page = theora_granule_frame(&tf->td, ogg_page_granulepos(&og)) - ogg_page_packets(&og) + 2;
1251         if (!ogg_page_continued(&og))
1252                 first_frame_on_page--;
1253         if (first_frame_on_page <= iframe)
1254         {
1255                 // optimisation, happens mainly in low-bitrate streams, it spares us one seek
1256         } else
1257         {
1258                 // get the page where keyframe starts
1259                 if (!ogg_get_page_of_frame(sw, serialno, &og, iframe))
1260                 {
1261                         printf(_("FileOGG: Seeking to keyframe failed\n"));
1262                         return 0;
1263                 }
1264         }               
1265 //      printf("looking for frame: %lli, last frame of the page: %lli, last keyframe: %lli\n", frame, pframe+iframe, iframe);
1266         ogg_stream_reset(&tf->to);
1267         ogg_stream_pagein(&tf->to, &og);
1268         // Read until one frame before keyframe
1269 //      printf("c: %i\n", ogg_page_continued(&og));
1270         int numread = iframe - (theora_granule_frame(&tf->td, ogg_page_granulepos(&og)) - ogg_page_packets(&og)) - 1;
1271         if (ogg_page_continued(&og))
1272                 numread--;
1273 //      printf("numread: %i\n", numread);
1274 //      printf("FileOGG:: Proper position: %lli\n", theora_granule_frame(&tf->td, ogg_page_granulepos(&og)) + numread - ogg_page_packets(&og));
1275         while (numread > 0)
1276         {
1277                 while (ogg_stream_packetpeek(&tf->to, NULL) != 1)
1278                 {
1279                         if (!ogg_get_next_page(sw, serialno, &og))
1280                         {
1281                                 printf(_("FileOGG: Cannot find next page while seeking\n"));
1282                                 return 0;
1283                         }
1284                         ogg_stream_pagein(&tf->to, &og);
1285                 }
1286                 ogg_stream_packetout(&tf->to, &op);
1287                 numread --;
1288         }
1289         *keyframe_number = iframe;
1290         return 1;
1291 }
1292
1293
1294 int FileOGG::check_sig(Asset *asset)
1295 {
1296
1297         FILE *fd = fopen(asset->path, "rb");
1298
1299 // Test for "OggS"
1300         fseek(fd, 0, SEEK_SET);
1301         char data[4];
1302
1303         (void)fread(data, 4, 1, fd);
1304
1305         if(data[0] == 'O' &&
1306                 data[1] == 'g' &&
1307                 data[2] == 'g' &&
1308                 data[3] == 'S')
1309         {
1310
1311                 fclose(fd);
1312                 printf(_("Yay, we have an ogg file\n"));
1313
1314                 return 1;
1315         }
1316
1317         fclose(fd);
1318
1319         return 0;
1320         
1321 }
1322
1323 int FileOGG::close_file()
1324 {
1325
1326         if (file->wr)
1327         {
1328                 if (asset->audio_data)
1329                         write_samples_vorbis(0, 0, 1); // set eos
1330                 if (asset->video_data)
1331                         write_frames_theora(0, 1, 1); // set eos
1332
1333                 flush_ogg(1); // flush all
1334         
1335                 if (asset->audio_data)
1336                 {
1337                         vorbis_block_clear (&tf->vb);
1338                         vorbis_dsp_clear (&tf->vd);
1339                         vorbis_info_clear (&tf->vi);
1340                         ogg_stream_clear (&tf->vo);
1341                 }
1342                 if (asset->video_data)
1343                 {
1344                         theora_info_clear (&tf->ti);
1345                         ogg_stream_clear (&tf->to);
1346                         theora_clear (&tf->td);
1347                 }
1348                 
1349                 if (stream) fclose(stream);
1350                 stream = 0;
1351         } 
1352         else 
1353         if (file->rd) 
1354         {       
1355                 if (asset->audio_data)
1356                 {
1357                         vorbis_block_clear (&tf->vb);
1358                         vorbis_dsp_clear (&tf->vd);
1359                         vorbis_comment_clear (&tf->vc);
1360                         vorbis_info_clear (&tf->vi);
1361                         ogg_stream_clear (&tf->vo);
1362                 }
1363                 theora_comment_clear(&tf->tc);
1364                 if (asset->video_data)
1365                 {
1366                         theora_info_clear (&tf->ti);
1367                         theora_comment_clear (&tf->tc);
1368                         theora_clear (&tf->td);
1369                         ogg_stream_clear (&tf->to);
1370                 }
1371                 
1372                         
1373                 if (stream) fclose(stream);
1374                 stream = 0;
1375
1376         }
1377         return 0;
1378 }
1379
1380 int FileOGG::close_file_derived()
1381 {
1382 //printf("FileOGG::close_file_derived(): 1\n");
1383         if (stream) fclose(stream);
1384         stream = 0;
1385         return 0;
1386 }
1387
1388 int64_t FileOGG::get_video_position()
1389 {
1390 //      printf("GVP\n");
1391         return next_frame_position - start_frame;
1392 }
1393
1394 int64_t FileOGG::get_audio_position()
1395 {
1396         return next_sample_position - start_sample;
1397 }
1398
1399 int FileOGG::set_video_position(int64_t x)
1400 {
1401 //      x=0;
1402 //      printf("SVP: %lli\n", x);
1403         
1404         next_frame_position = x + start_frame;
1405         return 1;
1406 }
1407
1408
1409 int FileOGG::colormodel_supported(int colormodel)
1410 {
1411 //      printf("CMS\n");
1412
1413         if (colormodel == BC_YUV420P)
1414                 return BC_YUV420P;
1415         else
1416                 return colormodel;
1417 }
1418 int FileOGG::get_best_colormodel(Asset *asset, int driver)
1419 {
1420
1421         return BC_YUV420P;
1422 }
1423
1424
1425 int FileOGG::read_frame(VFrame *frame)
1426 {
1427
1428         if(!stream) return 1;
1429
1430         
1431         // skip is cheaper than seek, do it...
1432         int decode_frames = 0;
1433         int expect_keyframe = 0;
1434         if (ogg_frame_position >= 0 && 
1435             next_frame_position >= ogg_frame_position && 
1436             next_frame_position - ogg_frame_position < 32)
1437         {
1438                 decode_frames = next_frame_position - ogg_frame_position;
1439         } else
1440         if (next_frame_position != ogg_frame_position)
1441         {
1442                 if (!ogg_seek_to_keyframe(tf->videosync, tf->to.serialno,
1443                         next_frame_position, &ogg_frame_position)) {
1444                         printf(_("FileOGG:: Error while seeking to frame's keyframe"
1445                                 " (frame: " _LD ", keyframe: " _LD ")\n"),
1446                                 next_frame_position, ogg_frame_position);
1447                         return 1;
1448                 }
1449 //              printf("For frame: %lli, keyframe is: %lli\n", next_frame_position,ogg_frame_position);
1450                 // skip frames must be > 0 here
1451                 decode_frames = next_frame_position - ogg_frame_position + 1; 
1452                 ogg_frame_position --; // ogg_frame_position is at last decoded frame, so it will point right 
1453                 if (decode_frames <= 0) 
1454                 {
1455                         printf(_("FileOGG:: Error while seeking to keyframe,"
1456                                 " wrong keyframe number (frame: " _LD ", keyframe: " _LD ")\n"),
1457                                 next_frame_position, ogg_frame_position);
1458                         return 1;
1459                         
1460                 }
1461                 expect_keyframe = 1;
1462         }
1463
1464 //      printf("Frames to decode: %i\n", decode_frames);
1465
1466 // THIS IS WHAT CAUSES SLOWNESS OF SEEKING, but we can do nothing about it.
1467         while (decode_frames > 0)
1468         {
1469                 ogg_page og;
1470                 ogg_packet op;
1471                 while (ogg_stream_packetpeek(&tf->to, NULL) != 1)
1472                 {
1473                         if (!ogg_get_next_page(tf->videosync, tf->to.serialno, &og))
1474                         {
1475                                 printf(_("FileOGG: Cannot find next page while seeking\n"));
1476                                 return 1;
1477                         }
1478                         ogg_stream_pagein(&tf->to, &og);
1479                 }
1480                 ogg_stream_packetout(&tf->to, &op);
1481                 if (expect_keyframe && !theora_packet_iskeyframe(&op))
1482                 {
1483                                 printf(_("FileOGG: Expecting keyframe, but didn't get it\n"));
1484                         //      return 1; this is generally not a fatal error
1485                 }
1486                 expect_keyframe = 0;
1487                 
1488                 // decode
1489                 theora_decode_packetin(&tf->td, &op);
1490
1491                 decode_frames --;
1492                 ogg_frame_position ++;
1493         }
1494         {
1495                 yuv_buffer yuv;
1496                 int ret = theora_decode_YUVout (&tf->td, &yuv);
1497                 if (ret)
1498                 {
1499                         printf(_("FileOGG: theora_decode_YUVout failed with code %i\n"), ret);
1500                 }
1501
1502 // Dirty magic 
1503 /*              yuv.y += yuv.y_stride * (yuv.y_height - 1);
1504                 yuv.u += yuv.uv_stride * (yuv.uv_height - 1);
1505                 yuv.v += yuv.uv_stride * (yuv.uv_height - 1);
1506                 yuv.y_stride = - yuv.y_stride;
1507                 yuv.uv_stride = - yuv.uv_stride;*/
1508                 VFrame *temp_frame = new VFrame(yuv.y, 
1509                                                 -1,
1510                                                 0,
1511                                                 yuv.u - yuv.y,
1512                                                 yuv.v - yuv.y,
1513                                                 - yuv.y_stride,
1514                                                 yuv.y_height,
1515                                                 BC_YUV420P,
1516                                                 - yuv.y_stride);
1517                 // copy into temp frame...
1518                 
1519                 BC_CModels::transfer(frame->get_rows(),
1520                         temp_frame->get_rows(),
1521                         frame->get_y(),
1522                         frame->get_u(),
1523                         frame->get_v(),
1524                         temp_frame->get_y(),
1525                         temp_frame->get_u(),
1526                         temp_frame->get_v(),
1527                         0,
1528                         0,
1529                         yuv.y_width,
1530                         yuv.y_height,
1531                         0,
1532                         0,
1533                         yuv.y_width,  // temp_frame can be larger than frame if width not dividable by 16
1534                         yuv.y_height,   
1535                         BC_YUV420P,
1536                         frame->get_color_model(),
1537                         0,
1538                         -temp_frame->get_w(),
1539                         frame->get_w());
1540                 delete temp_frame;
1541         }
1542
1543         next_frame_position ++;
1544         
1545         return 0;               
1546 }
1547
1548
1549
1550 int FileOGG::ogg_decode_more_samples(sync_window_t *sw, long serialno)
1551 {
1552         ogg_page og;
1553         ogg_packet op;
1554         int done = 0;
1555         while (!done)
1556         {
1557                 while (ogg_stream_packetpeek(&tf->vo, NULL) != 1)
1558                 {
1559                         if (!ogg_get_next_page(sw, serialno, &og))
1560                         {
1561                                 printf(_("FileOGG: Cannot find next page while trying to decode more samples\n"));
1562                                 return 0;
1563                         }
1564                         ogg_stream_pagein(&tf->vo, &og);
1565                 }
1566                 ogg_stream_packetout(&tf->vo, &op);
1567                 if(!vorbis_synthesis(&tf->vb, &op))
1568                 {
1569                         done = 1;       
1570                         vorbis_synthesis_blockin(&tf->vd, &tf->vb);
1571                 }
1572         }
1573         return 1;
1574 }
1575
1576 int FileOGG::set_audio_position(int64_t x)
1577 {
1578         next_sample_position = x + start_sample;
1579         return 0;
1580 }
1581
1582 int FileOGG::move_history(int from, int to, int len)
1583 {
1584         for(int i = 0; i < asset->channels; i++)
1585                 memmove(pcm_history[i] + to, pcm_history[i] + from, sizeof(float) * len);
1586         history_start = history_start + from - to;
1587         return 0;
1588
1589
1590 int FileOGG::read_samples(double *buffer, int64_t len)
1591 {
1592         float **vorbis_buffer;
1593         if (len <= 0) 
1594                 return 0;
1595 //      printf("Reading samples: Channel: %i, number of samples: %lli, reading at :%lli\n", file->current_channel, len, next_sample_position);
1596 //              printf("\tnext_sample_position: %lli, length: %i\n", next_sample_position, len);
1597 //              printf("\thistory_start: %lli, length: %i\n", history_start, history_size);
1598
1599         if(len > HISTORY_MAX)
1600         {
1601                 printf("FileOGG::read_samples max samples=%d\n", HISTORY_MAX);
1602                 return 1;
1603         }
1604
1605         if(!pcm_history)
1606         {
1607                 pcm_history = new float*[asset->channels];
1608                 for(int i = 0; i < asset->channels; i++)
1609                         pcm_history[i] = new float[HISTORY_MAX];
1610                 history_start = -100000000; // insane value to trigger reload
1611                 history_size = 0;
1612         }
1613
1614         int64_t hole_start = -1;
1615         int64_t hole_len = -1;
1616         int64_t hole_absstart = -1;
1617         int64_t hole_fill = 0;
1618
1619         if (history_start < next_sample_position && history_start + history_size > next_sample_position && history_start + history_size < next_sample_position + len) 
1620         {
1621 //              printf("a\n");
1622                 hole_fill = 1;
1623                 hole_start = history_start + history_size - next_sample_position;
1624                 hole_len = history_size - hole_start;
1625                 hole_absstart = next_sample_position + hole_start;
1626                 move_history(next_sample_position - history_start,
1627                                 0,
1628                                 hole_start); // 
1629                 
1630         } else
1631         if (next_sample_position < history_start && history_start < next_sample_position + len)
1632         {
1633 //              printf("b\n");
1634                 hole_fill = 1;
1635                 hole_start = 0;
1636                 hole_len = history_start - next_sample_position;
1637                 hole_absstart = next_sample_position;
1638 //              printf("hs: %lli, histstart: %lli, next_sample_position: %lli\n", history_size, history_start, next_sample_position);
1639 //              printf("to: 0, from: %lli, size: %lli\n", 
1640  //                             history_start - next_sample_position,
1641 //                              history_size - history_start + next_sample_position);
1642                 move_history(0, 
1643                                 history_start - next_sample_position,
1644                                 history_size - history_start + next_sample_position);
1645                         
1646         } else 
1647         if (next_sample_position >= history_start + history_size || next_sample_position + len <= history_start)
1648         {
1649 //              printf("c\n");
1650                 hole_fill = 1;
1651                 hole_start = 0;
1652                 hole_len = HISTORY_MAX;
1653                 hole_absstart = next_sample_position;
1654                 history_start = hole_absstart;
1655                 history_size = hole_len;
1656         }
1657         
1658         if (hole_fill)
1659         {
1660                 if (hole_start < 0 || hole_len <= 0 || hole_absstart < 0)
1661                 {
1662                         printf(_("FileOGG: Error at finding out what to read from file\n"));
1663                         return 1;
1664                 }
1665                 
1666                 if (hole_absstart + hole_len > asset->audio_length + start_sample)
1667                 {
1668                         hole_len = asset->audio_length + start_sample - hole_absstart;
1669                         history_size = asset->audio_length + start_sample - history_start;
1670                 } else
1671                 {
1672                         history_size = HISTORY_MAX;
1673                 }
1674                 
1675                 
1676 //              printf("Decode samples at position: %lli, samples to read: %lli\n", hole_absstart, hole_len);
1677         
1678                 int64_t samples_read = 0;        
1679                 if (ogg_sample_position != hole_absstart)
1680                 {
1681                         ogg_sample_position = hole_absstart;
1682                         if (!ogg_seek_to_sample(tf->audiosync, tf->vo.serialno, ogg_sample_position))
1683                         {
1684                                 printf("FileOGG:: Error while seeking to sample\n");
1685                                 return 1;
1686                         }
1687                 }
1688                 // now we have ogg_sample_positon aligned
1689                 int64_t samples_to_read = hole_len;
1690                 while (samples_read < hole_len)
1691                 {
1692                         int64_t waiting_samples = vorbis_synthesis_pcmout(&tf->vd, &vorbis_buffer);
1693                         int64_t takeout_samples;
1694                         if (waiting_samples > samples_to_read - samples_read)
1695                                 takeout_samples = samples_to_read - samples_read;
1696                         else 
1697                                 takeout_samples = waiting_samples;
1698
1699 //                      printf("takeout samples: %lli, samples_read: %lli\n", takeout_samples, samples_read);
1700
1701                         if(waiting_samples)
1702                         {
1703                                 for(int i = 0; i < asset->channels; i++)
1704                                 {
1705                                         float *input = vorbis_buffer[i];
1706                                         float *output = pcm_history[i] + hole_start;
1707                                         // TODO: use memcpy
1708                                         for(int j = 0; j < takeout_samples ; j++)
1709                                         {
1710                                                 output[j] = input[j];
1711                                         }
1712                                 }                                                                   
1713                         }
1714
1715                         vorbis_synthesis_read(&tf->vd, takeout_samples);
1716                         samples_read += takeout_samples;
1717                         ogg_sample_position += takeout_samples;
1718                         hole_start += takeout_samples;
1719                         
1720                         if (samples_read < hole_len)
1721                                 if (!ogg_decode_more_samples(tf->audiosync, tf->vo.serialno))
1722                                 {
1723                                         ogg_sample_position = -1;
1724                                         return 1;
1725                                 }
1726
1727
1728                 }
1729         }       
1730         
1731         // now we can be sure our history is correct, just copy it out
1732         if (next_sample_position < history_start || next_sample_position + len > history_start + history_size)
1733         {
1734                 printf(_("FileOGG:: History not aligned properly \n"));
1735                 printf(_("\tnext_sample_position: " _LD ", length: " _LD "\n"), next_sample_position, len);
1736                 printf(_("\thistory_start: " _LD ", length: " _LD "\n"), history_start, history_size);
1737                 
1738                 return 1;
1739         }
1740         float *input = pcm_history[file->current_channel] + next_sample_position - history_start;
1741         for (int i = 0; i < len; i++)
1742                 buffer[i] = input[i];
1743          
1744         next_sample_position += len;
1745         return 0;
1746 }
1747
1748
1749 int FileOGG::write_audio_page()
1750 {
1751   int ret;
1752
1753   ret = fwrite(tf->apage, 1, tf->apage_len, stream);
1754   if(ret < tf->apage_len) {
1755     eprintf(_("error writing audio page\n")); 
1756   }
1757   tf->apage_valid = 0;
1758   tf->a_pkg -= ogg_page_packets((ogg_page *)&tf->apage);
1759   return ret;
1760 }
1761
1762 int FileOGG::write_video_page()
1763 {
1764   int ret;
1765
1766   ret = fwrite(tf->vpage, 1, tf->vpage_len, stream);
1767   if(ret < tf->vpage_len) {
1768     eprintf(_("error writing video page\n"));
1769   }
1770   tf->vpage_valid = 0;
1771   tf->v_pkg -= ogg_page_packets((ogg_page *)&tf->vpage);
1772   return ret;
1773 }
1774
1775 void FileOGG::flush_ogg (int e_o_s)
1776 {
1777     int len;
1778     ogg_page og;
1779
1780         flush_lock->lock();
1781     /* flush out the ogg pages  */
1782     while(1) {
1783       /* Get pages for both streams, if not already present, and if available.*/
1784       if(asset->video_data && !tf->vpage_valid) {
1785         // this way seeking is much better,
1786         // not sure if 23 packets  is a good value. it works though
1787         int v_next=0;
1788         if(tf->v_pkg>22 && ogg_stream_flush(&tf->to, &og) > 0) {
1789           v_next=1;
1790         }
1791         else if(ogg_stream_pageout(&tf->to, &og) > 0) {
1792           v_next=1;
1793         }
1794         if(v_next) {
1795           len = og.header_len + og.body_len;
1796           if(tf->vpage_buffer_length < len) {
1797             tf->vpage = (unsigned char *)realloc(tf->vpage, len);
1798             tf->vpage_buffer_length = len;
1799           }
1800           tf->vpage_len = len;
1801           memcpy(tf->vpage, og.header, og.header_len);
1802           memcpy(tf->vpage+og.header_len , og.body, og.body_len);
1803
1804           tf->vpage_valid = 1;
1805           tf->videotime = theora_granule_time (&tf->td,
1806                   ogg_page_granulepos(&og));
1807         }
1808       }
1809       if(asset->audio_data && !tf->apage_valid) {
1810         // this way seeking is much better,
1811         // not sure if 23 packets  is a good value. it works though
1812         int a_next=0;
1813         if(tf->a_pkg>22 && ogg_stream_flush(&tf->vo, &og) > 0) {
1814           a_next=1;
1815         }
1816         else if(ogg_stream_pageout(&tf->vo, &og) > 0) {
1817           a_next=1;
1818         }
1819         if(a_next) {
1820           len = og.header_len + og.body_len;
1821           if(tf->apage_buffer_length < len) {
1822             tf->apage = (unsigned char *)realloc(tf->apage, len);
1823             tf->apage_buffer_length = len;
1824           }
1825           tf->apage_len = len;
1826           memcpy(tf->apage, og.header, og.header_len);
1827           memcpy(tf->apage+og.header_len , og.body, og.body_len);
1828
1829           tf->apage_valid = 1;
1830           tf->audiotime= vorbis_granule_time (&tf->vd, 
1831                   ogg_page_granulepos(&og));
1832         }
1833       }
1834
1835       if(!asset->audio_data && tf->vpage_valid) {
1836         write_video_page();
1837       }
1838       else if(!asset->video_data && tf->apage_valid) {
1839         write_audio_page();
1840       }
1841       /* We're using both. We can output only:
1842        *  a) If we have valid pages for both
1843        *  b) At EOS, for the remaining stream.
1844        */
1845       else if(tf->vpage_valid && tf->apage_valid) {
1846         /* Make sure they're in the right order. */
1847         if(tf->videotime <= tf->audiotime)
1848           write_video_page();
1849         else
1850           write_audio_page();
1851       } 
1852       else if(e_o_s && tf->vpage_valid) {
1853           write_video_page();
1854       }
1855       else if(e_o_s && tf->apage_valid) {
1856           write_audio_page();
1857       }
1858       else {
1859         break; /* Nothing more writable at the moment */
1860       }
1861     }
1862         flush_lock->unlock();
1863 }
1864
1865
1866 int FileOGG::write_samples_vorbis(double **buffer, int64_t len, int e_o_s)
1867 {
1868         float **vorbis_buffer;
1869         static int samples = 0;
1870         samples += len;
1871         if(e_o_s)
1872         {
1873                 vorbis_analysis_wrote (&tf->vd, 0);
1874         } else
1875         {
1876                 vorbis_buffer = vorbis_analysis_buffer (&tf->vd, len);
1877                 /* double to float conversion */
1878                 for(int i = 0; i<asset->channels; i++)
1879                 {
1880                         for (int j = 0; j < len; j++)
1881                         {
1882                                 vorbis_buffer[i][j] = buffer[i][j];
1883                         }
1884                 }
1885                 vorbis_analysis_wrote (&tf->vd, len);
1886         }
1887         while(vorbis_analysis_blockout (&tf->vd, &tf->vb) == 1)
1888         {
1889             /* analysis, assume we want to use bitrate management */
1890             vorbis_analysis (&tf->vb, NULL);
1891             vorbis_bitrate_addblock (&tf->vb);
1892             
1893             /* weld packets into the bitstream */
1894             while (vorbis_bitrate_flushpacket (&tf->vd, &tf->op))
1895             {
1896                 flush_lock->lock();
1897                 ogg_stream_packetin (&tf->vo, &tf->op);
1898                 tf->a_pkg++;
1899                 flush_lock->unlock();
1900             }
1901
1902         }
1903         flush_ogg(0);
1904         return 0;
1905
1906
1907 }
1908
1909 int FileOGG::write_samples(double **buffer, int64_t len)
1910 {
1911         if (len > 0)
1912                 return write_samples_vorbis(buffer, len, 0);
1913         return 0;
1914 }
1915
1916 int FileOGG::write_frames_theora(VFrame ***frames, int len, int e_o_s)
1917 {
1918         // due to clumsy theora's design we need to delay writing out by one frame
1919         // always stay one frame behind, so we can correctly encode e_o_s
1920         int result = 0;
1921         if(!stream) return 0;
1922         
1923         for(int j = 0; j < len && !result; j++)
1924         {
1925                 if (temp_frame) // encode previous frame if available
1926                 {
1927                         yuv_buffer yuv;
1928                         yuv.y_width = tf->ti.width;
1929                         yuv.y_height = tf->ti.height;
1930                         yuv.y_stride = temp_frame->get_bytes_per_line();
1931
1932                         yuv.uv_width = tf->ti.width / 2;
1933                         yuv.uv_height = tf->ti.height / 2;
1934                         yuv.uv_stride = temp_frame->get_bytes_per_line() /2;
1935
1936                         yuv.y = temp_frame->get_y();
1937                         yuv.u = temp_frame->get_u();
1938                         yuv.v = temp_frame->get_v();
1939                         int ret = theora_encode_YUVin (&tf->td, &yuv);
1940                         if (ret)
1941                         {
1942                                 printf(_("FileOGG: theora_encode_YUVin failed with code %i\n"), ret);
1943                                 printf("yuv_buffer: y_width: %i, y_height: %i, y_stride: %i,"
1944                                         " uv_width: %i, uv_height: %i, uv_stride: %i\n",
1945                                         yuv.y_width, yuv.y_height, yuv.y_stride,
1946                                         yuv.uv_width, yuv.uv_height, yuv.uv_stride);
1947                         }
1948                         while(theora_encode_packetout (&tf->td, e_o_s, &tf->op)) {
1949                                 flush_lock->lock();
1950                                 ogg_stream_packetin (&tf->to, &tf->op);
1951                                 tf->v_pkg++;
1952                                 flush_lock->unlock();
1953             }
1954                         flush_ogg(0);  // eos flush is done later at close_file
1955                 }
1956 // If we have e_o_s, don't encode any new frames
1957                 if (e_o_s) 
1958                         break;
1959
1960                 if (!temp_frame)
1961                 {
1962                         temp_frame = new VFrame (0, 
1963                                                 -1,
1964                                                 tf->ti.width, 
1965                                                 tf->ti.height,
1966                                                 BC_YUV420P,
1967                                                 -1);
1968                 } 
1969                 VFrame *frame = frames[0][j];
1970                 int in_color_model = frame->get_color_model();
1971                 if (in_color_model == BC_YUV422P &&
1972                     temp_frame->get_w() == frame->get_w() &&
1973                     temp_frame->get_h() == frame->get_h() &&
1974                     temp_frame->get_bytes_per_line() == frame->get_bytes_per_line())
1975                 {
1976                         temp_frame->copy_from(frame);
1977                 } else
1978                 {
1979
1980                         BC_CModels::transfer(temp_frame->get_rows(),
1981                                 frame->get_rows(),
1982                                 temp_frame->get_y(),
1983                                 temp_frame->get_u(),
1984                                 temp_frame->get_v(),
1985                                 frame->get_y(),
1986                                 frame->get_u(),
1987                                 frame->get_v(),
1988                                 0,
1989                                 0,
1990                                 frame->get_w(),
1991                                 frame->get_h(),
1992                                 0,
1993                                 0,
1994                                 frame->get_w(),  // temp_frame can be larger than frame if width not dividable by 16
1995                                 frame->get_h(), 
1996                                 frame->get_color_model(),
1997                                 BC_YUV420P,
1998                                 0,
1999                                 frame->get_w(),
2000                                 temp_frame->get_w());
2001
2002                 }
2003         }                                               
2004                                 
2005         return 0;
2006 }
2007
2008
2009 int FileOGG::write_frames(VFrame ***frames, int len)
2010 {
2011         
2012         return write_frames_theora(frames, len, 0);
2013 }
2014
2015 OGGConfigAudio::OGGConfigAudio(BC_WindowBase *parent_window, Asset *asset)
2016  : BC_Window(_(PROGRAM_NAME ": Audio Compression"),
2017         parent_window->get_abs_cursor_x(1),
2018         parent_window->get_abs_cursor_y(1),
2019         350,
2020         250)
2021 {
2022         this->parent_window = parent_window;
2023         this->asset = asset;
2024 }
2025
2026 OGGConfigAudio::~OGGConfigAudio()
2027 {
2028
2029 }
2030
2031 void OGGConfigAudio::create_objects()
2032 {
2033 //      add_tool(new BC_Title(10, 10, _("There are no audio options for this format")));
2034
2035         int x = 10, y = 10;
2036         int x1 = 150;
2037         char string[BCTEXTLEN];
2038
2039         lock_window("OGGConfigAudio::create_objects");
2040         add_tool(fixed_bitrate = new OGGVorbisFixedBitrate(x, y, this));
2041         add_tool(variable_bitrate = new OGGVorbisVariableBitrate(x1, y, this));
2042
2043         y += 30;
2044         sprintf(string, "%d", asset->vorbis_min_bitrate);
2045         add_tool(new BC_Title(x, y, _("Min bitrate:")));
2046         add_tool(new OGGVorbisMinBitrate(x1, y, this, string));
2047
2048         y += 30;
2049         add_tool(new BC_Title(x, y, _("Avg bitrate:")));
2050         sprintf(string, "%d", asset->vorbis_bitrate);
2051         add_tool(new OGGVorbisAvgBitrate(x1, y, this, string));
2052
2053         y += 30;
2054         add_tool(new BC_Title(x, y, _("Max bitrate:")));
2055         sprintf(string, "%d", asset->vorbis_max_bitrate);
2056         add_tool(new OGGVorbisMaxBitrate(x1, y, this, string));
2057
2058
2059         add_subwindow(new BC_OKButton(this));
2060         show_window(1);
2061         unlock_window();
2062 }
2063
2064 int OGGConfigAudio::close_event()
2065 {
2066         set_done(0);
2067         return 1;
2068 }
2069
2070 OGGVorbisFixedBitrate::OGGVorbisFixedBitrate(int x, int y, OGGConfigAudio *gui)
2071  : BC_Radial(x, y, !gui->asset->vorbis_vbr, _("Average bitrate"))
2072 {
2073         this->gui = gui;
2074 }
2075 int OGGVorbisFixedBitrate::handle_event()
2076 {
2077         gui->asset->vorbis_vbr = 0;
2078         gui->variable_bitrate->update(0);
2079         return 1;
2080 }
2081
2082 OGGVorbisVariableBitrate::OGGVorbisVariableBitrate(int x, int y, OGGConfigAudio *gui)
2083  : BC_Radial(x, y, gui->asset->vorbis_vbr, _("Variable bitrate"))
2084 {
2085         this->gui = gui;
2086 }
2087 int OGGVorbisVariableBitrate::handle_event()
2088 {
2089         gui->asset->vorbis_vbr = 1;
2090         gui->fixed_bitrate->update(0);
2091         return 1;
2092 }
2093
2094
2095 OGGVorbisMinBitrate::OGGVorbisMinBitrate(int x, 
2096         int y, 
2097         OGGConfigAudio *gui, 
2098         char *text)
2099  : BC_TextBox(x, y, 180, 1, text)
2100 {
2101         this->gui = gui;
2102 }
2103 int OGGVorbisMinBitrate::handle_event()
2104 {
2105         gui->asset->vorbis_min_bitrate = atol(get_text());
2106         return 1;
2107 }
2108
2109
2110
2111 OGGVorbisMaxBitrate::OGGVorbisMaxBitrate(int x, 
2112         int y, 
2113         OGGConfigAudio *gui,
2114         char *text)
2115  : BC_TextBox(x, y, 180, 1, text)
2116 {
2117         this->gui = gui;
2118 }
2119 int OGGVorbisMaxBitrate::handle_event()
2120 {
2121         gui->asset->vorbis_max_bitrate = atol(get_text());
2122         return 1;
2123 }
2124
2125
2126
2127 OGGVorbisAvgBitrate::OGGVorbisAvgBitrate(int x, int y, OGGConfigAudio *gui, char *text)
2128  : BC_TextBox(x, y, 180, 1, text)
2129 {
2130         this->gui = gui;
2131 }
2132 int OGGVorbisAvgBitrate::handle_event()
2133 {
2134         gui->asset->vorbis_bitrate = atol(get_text());
2135         return 1;
2136 }
2137
2138
2139
2140
2141
2142 OGGConfigVideo::OGGConfigVideo(BC_WindowBase *parent_window, Asset *asset)
2143  : BC_Window(_(PROGRAM_NAME ": Video Compression"),
2144         parent_window->get_abs_cursor_x(1),
2145         parent_window->get_abs_cursor_y(1),
2146         450,
2147         220)
2148 {
2149         this->parent_window = parent_window;
2150         this->asset = asset;
2151 }
2152
2153 OGGConfigVideo::~OGGConfigVideo()
2154 {
2155
2156 }
2157
2158 void OGGConfigVideo::create_objects()
2159 {
2160 //      add_tool(new BC_Title(10, 10, _("There are no video options for this format")));
2161         int x = 10, y = 10;
2162         int x1 = x + 150;
2163         int x2 = x + 300;
2164
2165         lock_window("OGGConfigVideo::create_objects");
2166         add_subwindow(new BC_Title(x, y + 5, _("Bitrate:")));
2167         add_subwindow(new OGGTheoraBitrate(x1, y, this));
2168         add_subwindow(fixed_bitrate = new OGGTheoraFixedBitrate(x2, y, this));
2169         y += 30;
2170
2171         add_subwindow(new BC_Title(x, y, _("Quality:")));
2172         add_subwindow(new BC_ISlider(x + 80, 
2173                 y,
2174                 0,
2175                 200,
2176                 200,
2177                 0,
2178                 63,
2179                 asset->theora_quality,
2180                 0,
2181                 0,
2182                 &asset->theora_quality));
2183
2184         
2185         add_subwindow(fixed_quality = new OGGTheoraFixedQuality(x2, y, this));
2186         y += 30;
2187
2188         add_subwindow(new BC_Title(x, y, _("Keyframe frequency:")));
2189         OGGTheoraKeyframeFrequency *keyframe_frequency = 
2190                 new OGGTheoraKeyframeFrequency(x1 + 60, y, this);
2191         keyframe_frequency->create_objects();
2192         y += 30;
2193         
2194         add_subwindow(new BC_Title(x, y, _("Keyframe force frequency:")));
2195         OGGTheoraKeyframeForceFrequency *keyframe_force_frequency = 
2196                 new OGGTheoraKeyframeForceFrequency(x1 + 60, y, this);
2197         keyframe_force_frequency->create_objects();
2198         y += 30;
2199
2200         add_subwindow(new BC_Title(x, y, _("Sharpness:")));
2201         OGGTheoraSharpness *sharpness = 
2202                 new OGGTheoraSharpness(x1 + 60, y, this);
2203         sharpness->create_objects();
2204         y += 30;
2205         
2206
2207         add_subwindow(new BC_OKButton(this));
2208         show_window(1);
2209         unlock_window();
2210 }
2211
2212
2213
2214
2215 int OGGConfigVideo::close_event()
2216 {
2217         set_done(0);
2218         return 1;
2219 }
2220
2221 OGGTheoraBitrate::OGGTheoraBitrate(int x, int y, OGGConfigVideo *gui)
2222  : BC_TextBox(x, y, 100, 1, gui->asset->theora_bitrate)
2223 {
2224         this->gui = gui;
2225 }
2226
2227
2228 int OGGTheoraBitrate::handle_event()
2229 {
2230         // TODO: MIN / MAX check
2231         gui->asset->theora_bitrate = atol(get_text());
2232         return 1;
2233 };
2234
2235
2236
2237
2238 OGGTheoraFixedBitrate::OGGTheoraFixedBitrate(int x, int y, OGGConfigVideo *gui)
2239  : BC_Radial(x, y, gui->asset->theora_fix_bitrate, _("Fixed bitrate"))
2240 {
2241         this->gui = gui;
2242 }
2243
2244 int OGGTheoraFixedBitrate::handle_event()
2245 {
2246         update(1);
2247         gui->asset->theora_fix_bitrate = 1;
2248         gui->fixed_quality->update(0);
2249         return 1;
2250 };
2251
2252 OGGTheoraFixedQuality::OGGTheoraFixedQuality(int x, int y, OGGConfigVideo *gui)
2253  : BC_Radial(x, y, !gui->asset->theora_fix_bitrate, _("Fixed quality"))
2254 {
2255         this->gui = gui;
2256 }
2257
2258 int OGGTheoraFixedQuality::handle_event()
2259 {
2260         update(1);
2261         gui->asset->theora_fix_bitrate = 0;
2262         gui->fixed_bitrate->update(0);
2263         return 1;
2264 };
2265
2266 OGGTheoraKeyframeFrequency::OGGTheoraKeyframeFrequency(int x, int y, OGGConfigVideo *gui)
2267  : BC_TumbleTextBox(gui, 
2268         (int64_t)gui->asset->theora_keyframe_frequency, 
2269         (int64_t)1,
2270         (int64_t)500,
2271         x, 
2272         y,
2273         40)
2274 {
2275         this->gui = gui;
2276 }
2277
2278 int OGGTheoraKeyframeFrequency::handle_event()
2279 {
2280         gui->asset->theora_keyframe_frequency = atol(get_text());
2281         return 1;
2282 }
2283
2284 OGGTheoraKeyframeForceFrequency::OGGTheoraKeyframeForceFrequency(int x, int y, OGGConfigVideo *gui)
2285  : BC_TumbleTextBox(gui, 
2286         (int64_t)gui->asset->theora_keyframe_frequency, 
2287         (int64_t)1,
2288         (int64_t)500,
2289         x, 
2290         y,
2291         40)
2292 {
2293         this->gui = gui;
2294 }
2295
2296 int OGGTheoraKeyframeForceFrequency::handle_event()
2297 {
2298         gui->asset->theora_keyframe_frequency = atol(get_text());
2299         return 1;
2300 }
2301
2302
2303 OGGTheoraSharpness::OGGTheoraSharpness(int x, int y, OGGConfigVideo *gui)
2304  : BC_TumbleTextBox(gui, 
2305         (int64_t)gui->asset->theora_sharpness, 
2306         (int64_t)0,
2307         (int64_t)2,
2308         x, 
2309         y,
2310         40)
2311 {
2312         this->gui = gui;
2313 }
2314
2315 int OGGTheoraSharpness::handle_event()
2316 {
2317         gui->asset->theora_sharpness = atol(get_text());
2318         return 1;
2319 }
2320
2321
2322 PackagingEngineOGG::PackagingEngineOGG()
2323 {
2324         packages = 0;
2325         default_asset = 0;
2326 }
2327
2328 PackagingEngineOGG::~PackagingEngineOGG()
2329 {
2330         if(packages)
2331         {
2332                 for(int i = 0; i < total_packages; i++)
2333                         delete packages[i];
2334                 delete [] packages;
2335         }
2336         if (default_asset)
2337                 delete default_asset;
2338 }
2339
2340
2341
2342 int PackagingEngineOGG::create_packages_single_farm(
2343                 EDL *edl,
2344                 Preferences *preferences,
2345                 Asset *default_asset, 
2346                 double total_start, 
2347                 double total_end)
2348 {
2349         this->total_start = total_start;
2350         this->total_end = total_end;
2351         this->edl = edl;
2352
2353         this->preferences = preferences;
2354
2355 // We make A COPY of the asset, because we set audio_data = 0 on local asset which is the same copy as default_asset... 
2356 // Should be taken care of somewhere else actually
2357         this->default_asset = new Asset(*default_asset);
2358
2359         audio_start = Units::to_int64(total_start * default_asset->sample_rate);
2360         video_start = Units::to_int64(total_start * default_asset->frame_rate);
2361         audio_position = audio_start;
2362         video_position = video_start;
2363         audio_end = Units::to_int64(total_end * default_asset->sample_rate);
2364         video_end = Units::to_int64(total_end * default_asset->frame_rate);
2365         current_package = 0;
2366
2367         double total_len = total_end - total_start;
2368 //printf("PackageDispatcher::create_packages: %f / %d = %f\n", total_len, total_packages, package_len);
2369
2370         total_packages = 0;
2371         if (default_asset->audio_data)
2372                 total_packages++;
2373         if (default_asset->video_data)
2374                 total_packages += preferences->renderfarm_job_count;
2375
2376         packages = new RenderPackage*[total_packages];
2377
2378         int local_current_package = 0;
2379         if (default_asset->audio_data)
2380         {
2381                 packages[local_current_package] = new RenderPackage;
2382                 sprintf(packages[current_package]->path, "%s.audio", default_asset->path);
2383                 local_current_package++;
2384         }
2385         
2386         if (default_asset->video_data)
2387         {
2388                 video_package_len = (total_len) / preferences->renderfarm_job_count;
2389                 int current_number;    // The number being injected into the filename.
2390                 int number_start;      // Character in the filename path at which the number begins
2391                 int total_digits;      // Total number of digits including padding the user specified.
2392
2393                 Render::get_starting_number(default_asset->path, 
2394                         current_number,
2395                         number_start, 
2396                         total_digits,
2397                         3);
2398
2399                 for(int i = 0; i < preferences->renderfarm_job_count; i++)
2400                 {
2401                         RenderPackage *package = packages[local_current_package] = new RenderPackage;
2402                         Render::create_filename(package->path, 
2403                                 default_asset->path, 
2404                                 current_number,
2405                                 total_digits,
2406                                 number_start);
2407                         current_number++;
2408                         local_current_package++;
2409                 }
2410         }
2411         return 0;
2412 }
2413
2414 RenderPackage* PackagingEngineOGG::get_package_single_farm(double frames_per_second, 
2415                 int client_number,
2416                 int use_local_rate)
2417 {
2418
2419 //printf("PackageDispatcher::get_package %ld %ld %ld %ld\n", audio_position, video_position, audio_end, video_end);
2420         if (current_package == total_packages)
2421                 return 0;
2422
2423         RenderPackage *result = 0;
2424         if (current_package == 0 && default_asset->audio_data)
2425         {
2426                 result = packages[0];
2427                 result->audio_start = audio_start;
2428                 result->video_start = video_start;
2429                 result->audio_end = audio_end;
2430                 result->video_end = video_end;
2431                 result->audio_do = 1;
2432                 result->video_do = 0;
2433         } else if (default_asset->video_data)
2434         {
2435                 // Do not do any scaling according to node speed, so we know we can get evenly distributed 'forced' keyframes
2436                 result = packages[current_package];
2437                 result->audio_do = 0;
2438                 result->video_do = 1;
2439
2440                 result->audio_start = audio_position;
2441                 result->video_start = video_position;
2442                 result->audio_end = audio_position + 
2443                         Units::round(video_package_len * default_asset->sample_rate);
2444                 result->video_end = video_position + 
2445                         Units::round(video_package_len * default_asset->frame_rate);
2446
2447 // Last package... take it all!
2448                 if (current_package == total_packages -1 ) 
2449                 {
2450                         result->audio_end = audio_end;
2451                         result->video_end = video_end;
2452                 }
2453
2454                 audio_position = result->audio_end;
2455                 video_position = result->video_end;
2456
2457         }
2458         
2459         current_package ++;
2460         return result;
2461
2462 }
2463
2464 void PackagingEngineOGG::get_package_paths(ArrayList<char*> *path_list)
2465 {
2466         for(int i = 0; i < total_packages; i++)
2467         {
2468                 path_list->append(strdup(packages[i]->path));
2469         }
2470 // We will mux to the the final file at the end!
2471         path_list->append(strdup(default_asset->path));
2472         path_list->set_free();
2473 }
2474
2475 int64_t PackagingEngineOGG::get_progress_max()
2476 {
2477         return Units::to_int64(default_asset->sample_rate * 
2478                         (total_end - total_start)) * 2+
2479                 Units::to_int64(preferences->render_preroll * 
2480                         total_packages *
2481                         default_asset->sample_rate);
2482 }
2483
2484 int PackagingEngineOGG::packages_are_done()
2485 {
2486
2487
2488 // Mux audio and video into one file    
2489
2490 // First fix our asset... have to workaround the bug of corruption of local asset
2491 //      Render::check_asset(edl, *default_asset);
2492
2493         Asset *video_asset = 0, *audio_asset = 0;
2494         File *audio_file_gen = 0, *video_file_gen = 0;
2495         FileOGG *video_file = 0, *audio_file = 0;
2496         ogg_stream_state audio_in_stream, video_in_stream;
2497         
2498         int local_current_package = 0;
2499         if (default_asset->audio_data)
2500         {
2501                 audio_asset = new Asset(packages[local_current_package]->path);
2502                 local_current_package++;
2503
2504                 audio_file_gen = new File();
2505                 audio_file_gen->open_file(preferences, audio_asset, 1, 0);
2506                 audio_file = (FileOGG*) audio_file_gen->file;
2507                 ogg_stream_init(&audio_in_stream, audio_file->tf->vo.serialno);
2508                 audio_file->ogg_seek_to_databegin(audio_file->tf->audiosync, audio_file->tf->vo.serialno);
2509         }
2510
2511         if (default_asset->video_data)
2512         {
2513                 video_asset = new Asset(packages[local_current_package]->path);
2514                 local_current_package++;
2515
2516                 video_file_gen = new File();
2517                 video_file_gen->open_file(preferences, video_asset, 1, 0);
2518                 video_file = (FileOGG*) video_file_gen->file;
2519                 ogg_stream_init(&video_in_stream, video_file->tf->to.serialno);
2520                 video_file->ogg_seek_to_databegin(video_file->tf->videosync, video_file->tf->to.serialno);
2521         }
2522
2523 // Output file
2524         File *output_file_gen = new File();
2525         output_file_gen->open_file(preferences, default_asset, 0, 1);
2526         FileOGG *output_file = (FileOGG*) output_file_gen->file;
2527
2528         //ogg_page og;    /* one Ogg bitstream page.  Vorbis packets are inside */
2529         ogg_packet op;  /* one raw packet of data for decode */
2530
2531
2532         int audio_ready = default_asset->audio_data;
2533         int video_ready = default_asset->video_data;
2534         int64_t video_packetno = 1;
2535         int64_t audio_packetno = 1;
2536         int64_t frame_offset = 0;
2537         int64_t current_frame = 0;
2538         while ((default_asset->audio_data && audio_ready) || (default_asset->video_data && video_ready))
2539         {
2540                 if (video_ready)
2541                 {
2542                         while (ogg_stream_packetpeek(&video_in_stream, NULL) != 1) // get as many pages as needed for one package
2543                         {
2544                                 if (!video_file->ogg_get_next_page(video_file->tf->videosync, video_file->tf->to.serialno, &video_file->tf->videopage))
2545                                 {
2546                                         // We are at the end of our file, see if it is more and open more if there is
2547                                         if (local_current_package < total_packages)
2548                                         {
2549                                                 frame_offset = current_frame +1;
2550                                                 ogg_stream_clear(&video_in_stream);
2551                                                 video_file_gen->close_file();
2552                                                 delete video_file_gen;
2553                                                 delete video_asset;
2554                                                 video_asset = new Asset(packages[local_current_package]->path);
2555                                                 local_current_package++;
2556
2557                                                 video_file_gen = new File();
2558                                                 video_file_gen->open_file(preferences, video_asset, 1, 0);
2559                                                 video_file = (FileOGG*) video_file_gen->file;
2560                                                 ogg_stream_init(&video_in_stream, video_file->tf->to.serialno);
2561                                                 video_file->ogg_seek_to_databegin(video_file->tf->videosync, video_file->tf->to.serialno);
2562
2563                                         } else
2564                                                 video_ready = 0;
2565                                         break;
2566                                 }
2567                                 ogg_stream_pagein(&video_in_stream, &video_file->tf->videopage);
2568                         }
2569                         while (ogg_stream_packetpeek(&video_in_stream, NULL) == 1) // get all packets out of the page
2570                         {
2571                                 ogg_stream_packetout(&video_in_stream, &op);
2572                                 if (local_current_package != total_packages) // keep it from closing the stream
2573                                         op.e_o_s = 0;
2574                                 if (video_packetno != 1)                     // if this is not the first video package do not start with b_o_s
2575                                         op.b_o_s = 0;
2576                                 else
2577                                         op.b_o_s = 1;
2578                                 op.packetno = video_packetno;
2579                                 video_packetno ++;
2580                                 int64_t granulepos = op.granulepos;
2581                                 if (granulepos != -1)
2582                                 {
2583                                 // Fix granulepos!      
2584                                         int64_t rel_iframe = granulepos >> video_file->theora_keyframe_granule_shift;
2585                                         int64_t rel_pframe = granulepos - (rel_iframe << video_file->theora_keyframe_granule_shift);
2586                                         int64_t rel_current_frame = rel_iframe + rel_pframe;
2587                                         current_frame = frame_offset + rel_current_frame;
2588                                         int64_t abs_iframe = current_frame - rel_pframe;
2589                                         
2590                                         op.granulepos = (abs_iframe << video_file->theora_keyframe_granule_shift) + rel_pframe;
2591                                         
2592 //                                      printf("iframe: %i, pframe: %i, granulepos: %i, op.packetno %lli, abs_iframe: %i\n", rel_iframe, rel_pframe, granulepos, op.packetno, abs_iframe);                              
2593                                 
2594                                 }
2595                                 ogg_stream_packetin (&output_file->tf->to, &op);
2596                                 output_file->tf->v_pkg++; 
2597                         }
2598                 }
2599                 if (audio_ready)
2600                 {
2601                         while (ogg_stream_packetpeek(&audio_in_stream, NULL) != 1) // get as many pages as needed for one package
2602                         {
2603                                 if (!audio_file->ogg_get_next_page(audio_file->tf->audiosync, audio_file->tf->vo.serialno, &audio_file->tf->audiopage))
2604                                 {
2605                                         audio_ready = 0;
2606                                         break;
2607                                 }
2608                                 ogg_stream_pagein(&audio_in_stream, &audio_file->tf->audiopage);
2609                         }
2610                         while (ogg_stream_packetpeek(&audio_in_stream, NULL) == 1) // get all packets out of the page
2611                         {
2612                                 ogg_stream_packetout(&audio_in_stream, &op);
2613                                 ogg_stream_packetin (&output_file->tf->vo, &op);
2614                                 audio_packetno++;
2615                                 output_file->tf->a_pkg++; 
2616                         }
2617                 }
2618                 
2619                 output_file->flush_ogg(0);
2620                 
2621         
2622         }
2623         
2624 // flush_ogg(1) is called on file closing time...       
2625 //      output_file->flush_ogg(1);
2626
2627 // Just prevent thet write_samples and write_frames are called
2628         output_file->final_write = 0;
2629                 
2630         if (default_asset->audio_data)
2631         {
2632                 ogg_stream_clear(&audio_in_stream);
2633                 audio_file_gen->close_file();
2634                 delete audio_file_gen;
2635                 delete audio_asset;
2636         }
2637         if (default_asset->video_data)
2638         {
2639                 ogg_stream_clear(&video_in_stream);
2640                 video_file_gen->close_file();
2641                 delete video_file_gen;
2642                 delete video_asset;
2643         }
2644
2645         output_file_gen->close_file();
2646         delete output_file_gen;
2647
2648 // Now delete the temp files
2649         for(int i = 0; i < total_packages; i++)
2650                 unlink(packages[i]->path);
2651
2652         return 0;
2653 }
2654
2655
2656