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