4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
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.
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.
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
23 #include "bcsignals.h"
24 #include "byteorder.h"
30 #include "interlacemodes.h"
32 #include "mainerror.h"
34 #include "mwindow.inc"
35 #include "preferences.h"
38 #include "versioninfo.h"
39 #include "videodevice.inc"
41 #include <sys/types.h>
48 #define READ_SIZE 3*66000
50 /* This code was aspired by ffmpeg2theora */
51 /* Special thanks for help on this code goes out to j@v2v.cc */
53 int ogg_ret0, ogg_ret1, ogg_ret2;
55 FileOGG::FileOGG(Asset *asset, File *file)
56 : FileBase(asset, file)
58 if(asset->format == FILE_UNKNOWN)
59 asset->format = FILE_OGG;
60 asset->byte_order = 0;
72 ogg_sync_clear(&tf->videosync->sync);
74 theora_info_clear(&tf->ti);
75 theora_comment_clear(&tf->tc);
79 ogg_sync_clear(&tf->audiosync->sync);
81 vorbis_info_clear(&tf->vi);
82 vorbis_comment_clear(&tf->vc);
90 if (temp_frame) delete temp_frame;
91 if (stream) close_file();
94 for(int i = 0; i < asset->channels; i++)
95 delete [] pcm_history[i];
96 delete [] pcm_history;
99 if (flush_lock) delete flush_lock;
102 void FileOGG::get_parameters(BC_WindowBase *parent_window,
104 BC_WindowBase* &format_window,
110 OGGConfigAudio *window = new OGGConfigAudio(parent_window, asset);
111 format_window = window;
112 window->create_objects();
113 window->run_window();
119 OGGConfigVideo *window = new OGGConfigVideo(parent_window, asset);
120 format_window = window;
121 window->create_objects();
122 window->run_window();
127 int FileOGG::reset_parameters_derived()
138 static int read_buffer(FILE *in, sync_window_t *sw, int buflen)
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);
150 static int read_buffer_at(FILE *in, sync_window_t *sw, int buflen, off_t filepos)
152 // printf("seeking to %lli %lli\n", filepos, sw->file_bufpos);
153 fseeko(in, filepos, SEEK_SET);
154 // if (sw->file_bufpos != filepos)
156 sw->file_bufpos = filepos;
157 sw->file_pagepos = filepos; // this one is not valid until sync_pageseek!
158 ogg_sync_reset(&sw->sync);
161 return read_buffer(in, sw, buflen);
164 static int take_page_out_autoadvance(FILE *in, sync_window_t *sw, ogg_page *og)
168 int ret = ogg_sync_pageout(&sw->sync, og);
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);
179 eprintf(_("FileOGG: Taking page out on nonsynced stream!\n"));
184 // need more data for page
185 if ((ret = read_buffer(in, sw, READ_SIZE)) == 0)
187 printf(_("FileOGG: There is no more data in the file we are reading from\n"));
188 return 0; // No more data
196 // we never need to autoadvance when syncing, since our read chunks are larger than
198 static int sync_and_take_page_out(sync_window_t *sw, ogg_page *page)
200 page->header_len = 0;
204 int ret = ogg_sync_pageseek(&sw->sync, page);
207 sw->file_pagepos -= ret;
211 sw->file_pagepos += ret;
212 // printf("ret: %i %i\n",ret, page->header_len + page->body_len);
217 int FileOGG::open_file(int rd, int wr)
221 tf = new theoraframes_info_t;
222 memset(tf, 0, sizeof(*tf));
230 if((stream = fopen(asset->path, "w+b")) == 0)
232 eprintf(_("Error while opening \"%s\" for writing. %m\n"), asset->path);
236 tf->audio_bytesout = 0;
237 tf->video_bytesout = 0;
243 tf->apage_buffer_length = 0;
244 tf->vpage_buffer_length = 0;
251 /* yayness. Set up Ogg output stream */
254 if(asset->video_data)
256 ogg_stream_init (&tf->to, rand ()); /* oops, add one ot the above */
258 theora_info_init (&tf->ti);
260 tf->ti.frame_width = asset->width;
261 tf->ti.frame_height = asset->height;
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)
267 eprintf(_("WARNING: Encoding theora when width or height are not dividable by 16 is suboptimal\n"));
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;
275 if (asset->aspect_ratio > 0)
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;
283 tf->ti.aspect_numerator = 1000000;
284 tf->ti.aspect_denominator = 1000000;
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;
291 tf->ti.colorspace = OC_CS_UNSPECIFIED;
293 if (asset->theora_fix_bitrate)
295 tf->ti.target_bitrate = asset->theora_bitrate;
299 tf->ti.target_bitrate = 0;
300 tf->ti.quality = asset->theora_quality; // video quality 0-63
302 tf->ti.dropframes_p = 0;
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;
314 if (theora_encode_init (&tf->td, &tf->ti))
316 eprintf(_("(FileOGG:file_open) initialization of theora codec failed\n"));
319 /* init theora done */
321 /* initialize Vorbis too, if we have audio. */
322 if(asset->audio_data)
324 ogg_stream_init (&tf->vo, rand ());
325 vorbis_info_init (&tf->vi);
326 /* Encoding using a VBR quality mode. */
328 if(!asset->vorbis_vbr)
330 ret = vorbis_encode_init(&tf->vi,
333 asset->vorbis_max_bitrate,
334 asset->vorbis_bitrate,
335 asset->vorbis_min_bitrate);
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,
343 asset->vorbis_bitrate,
345 ret |= vorbis_encode_ctl(&tf->vi, OV_ECTL_RATEMANAGE_AVG, NULL);
346 ret |= vorbis_encode_setup_init(&tf->vi);
351 eprintf(_("The Vorbis encoder could not set up a mode according to\n"
352 "the requested quality or bitrate.\n\n"));
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);
365 /* audio init done */
367 /* write the bitstream header packets with proper page interleave */
369 /* first packet will get its own page automatically */
370 if(asset->video_data)
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)
376 eprintf(_("Internal Ogg library error.\n"));
379 fwrite (tf->og.header, 1, tf->og.header_len, stream);
380 fwrite (tf->og.body, 1, tf->og.body_len, stream);
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);
392 if(asset->audio_data)
395 ogg_packet header_comm;
396 ogg_packet header_code;
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)
404 eprintf(_("Internal Ogg library error.\n"));
407 fwrite (tf->og.header, 1, tf->og.header_len, stream);
408 fwrite (tf->og.body, 1, tf->og.body_len, stream);
410 /* remaining vorbis header packets */
411 ogg_stream_packetin (&tf->vo, &header_comm);
412 ogg_stream_packetin (&tf->vo, &header_code);
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)
420 int result = ogg_stream_flush (&tf->to, &tf->og);
424 eprintf(_("Internal Ogg library error.\n"));
429 fwrite (tf->og.header, 1, tf->og.header_len, stream);
430 fwrite (tf->og.body, 1, tf->og.body_len, stream);
432 while (1 && asset->audio_data)
434 int result = ogg_stream_flush (&tf->vo, &tf->og);
438 eprintf(_("Internal Ogg library error.\n"));
443 fwrite (tf->og.header, 1, tf->og.header_len, stream);
444 fwrite (tf->og.body, 1, tf->og.body_len, stream);
446 flush_lock = new Mutex("OGGFile::Flush lock");
447 // printf("End of headers at position: %lli\n", ftello(stream));
452 if((stream = fopen(asset->path, "rb")) == 0)
454 eprintf(_("Error while opening %s for reading. %m\n"), asset->path);
458 /* get file length */
459 struct stat file_stat;
460 stat(asset->path, &file_stat);
461 file_length = file_stat.st_size;
463 /* start up Ogg stream synchronization layer */
464 /* oy is used just here to parse header, we use separate syncs for video and audio*/
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);
471 /* init supporting Vorbis structures needed in header parsing */
472 vorbis_info_init(&tf->vi);
473 vorbis_comment_init(&tf->vc);
476 /* init supporting Theora structures needed in header parsing */
477 theora_comment_init(&tf->tc);
478 theora_info_init(&tf->ti);
482 /* Ogg file open; parse the headers */
483 /* Only interested in Vorbis/Theora streams */
491 // int ret = read_buffer(stream, &oy, 4096);
492 TRACE("FileOGG::open_file 60")
496 while(take_page_out_autoadvance(stream, &oy, &tf->og) > 0)
498 ogg_stream_state test;
500 /* is this a mandated initial header? If not, stop parsing */
501 if(!ogg_page_bos(&tf->og))
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);
512 ogg_stream_init(&test, ogg_page_serialno(&tf->og));
513 ogg_stream_pagein(&test, &tf->og);
514 ogg_stream_packetout(&test, &tf->op);
516 /* identify the codec: try theora */
517 if(!theora_p && theora_decode_header(&tf->ti, &tf->tc, &tf->op)>=0)
520 memcpy(&tf->to, &test, sizeof(test));
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;
527 } else if(!vorbis_p && vorbis_synthesis_headerin(&tf->vi, &tf->vc, &tf->op)>=0)
530 memcpy(&tf->vo, &test, sizeof(test));
534 /* whatever it is, we don't care about it */
535 ogg_stream_clear(&test);
538 /* fall through to non-bos page parsing */
542 /* we're expecting more header packets. */
543 while((theora_p && theora_p < 3) || (vorbis_p && vorbis_p < 3))
547 /* look for further theora headers */
548 while(theora_p && (theora_p < 3) && (ret = ogg_stream_packetout(&tf->to, &tf->op)))
552 eprintf(_("FileOGG: Error parsing Theora stream headers; corrupt stream?\n"));
555 if(theora_decode_header(&tf->ti, &tf->tc, &tf->op))
557 eprintf(_("FileOGG: Error parsing Theora stream headers; corrupt stream?\n"));
565 /* look for more vorbis header packets */
566 while(vorbis_p && (vorbis_p < 3) && (ret = ogg_stream_packetout(&tf->vo, &tf->op)))
570 eprintf(_("FileOGG: Error parsing Vorbis stream headers; corrupt stream?\n"));
573 if (vorbis_synthesis_headerin(&tf->vi, &tf->vc, &tf->op))
575 eprintf(_("FileOGG: Error parsing Vorbis stream headers; corrupt stream?\n"));
583 if ((!vorbis_p || vorbis_p == 3) && (!theora_p || theora_p == 3))
585 /* The header pages/packets will arrive before anything else we
586 care about, or the stream is not obeying spec */
588 if(take_page_out_autoadvance(stream, &oy, &tf->og) > 0)
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);
596 eprintf(_("FileOGG: End of file while searching for codec headers.\n"));
600 // Remember where the real data begins for later seeking purposes
601 filedata_begin = oy.file_pagepos;
605 /* and now we have it all. initialize decoders */
610 // WORKAROUND for bug in alpha4 version of theora:
611 tf->td.internal_encode = 0;
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,
621 Not yet available in alpha4, we assume 420 for now
623 switch(tf->ti.pixelformat)
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;
630 printf(" video\n (UNKNOWN Chroma sampling!)\n");
635 theora_cmodel = BC_YUV420P;
637 if(tf->ti.width!=tf->ti.frame_width || tf->ti.height!=tf->ti.frame_height)
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);
642 tf->videosync = new sync_window_t;
643 ogg_sync_init(&tf->videosync->sync);
644 tf->videosync->wlen = 0;
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);
650 // we have headers already decoded, so just skip them
651 ogg_stream_reset(&tf->to);
652 ogg_stream_pagein(&tf->to, &tf->videopage);
655 while (ogg_stream_packetpeek(&tf->to, NULL) != 1)
657 if (!ogg_get_next_page(tf->videosync, tf->to.serialno, &tf->videopage))
659 printf(_("FileOGG: Cannot find next page while looking for first non-header packet\n"));
662 ogg_stream_pagein(&tf->to, &tf->videopage);
664 ogg_stream_packetout(&tf->to, &op);
665 if (!theora_packet_isheader(&op))
668 // now get to the page of the finish of the first packet
669 while (ogg_page_packets(&tf->videopage) == 0)
671 if (ogg_page_granulepos(&tf->videopage) != -1)
673 printf(_("FileOGG: Broken ogg file - broken page: ogg_page_packets == 0 and granulepos != -1\n"));
676 ogg_get_next_page(tf->videosync, tf->to.serialno, &tf->videopage);
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;
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);
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 = ILACE_MODE_NOTINTERLACED;
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);
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);
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);
720 // report_colorspace(&ti);
721 // dump_comments(&tc);
724 /* tear down the partial theora setup */
725 theora_info_clear(&tf->ti);
726 theora_comment_clear(&tf->tc);
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);
737 /* init audio_sync structure */
738 tf->audiosync = new sync_window_t;
739 ogg_sync_init(&tf->audiosync->sync);
740 tf->audiosync->wlen = 0;
742 ogg_get_first_page(tf->audiosync, tf->vo.serialno, &tf->audiopage);
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;
751 while((result = ogg_stream_packetout(&tf->vo, &op)))
755 long thisblock = vorbis_packet_blocksize(&tf->vi, &op);
757 accumulated += (lastblock + thisblock) >> 2;
758 lastblock = thisblock;
761 start_sample = ogg_page_granulepos(&tf->audiopage) - accumulated;
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));
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;
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);
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));
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);
814 asset->channels = tf->vi.channels;
815 if(!asset->sample_rate)
816 asset->sample_rate = tf->vi.rate;
817 asset->audio_data = 1;
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);
827 /* tear down the partial vorbis setup */
828 vorbis_info_clear(&tf->vi);
829 vorbis_comment_clear(&tf->vc);
832 ogg_sync_clear(&oy.sync);
838 int FileOGG::ogg_get_prev_page(sync_window_t *sw, long serialno, ogg_page *og)
841 off_t filepos = sw->file_pagepos_found - READ_SIZE;
842 int first_page_offset = 0;
844 int read_len = READ_SIZE;
846 // printf("fp: %lli pagepos found: %lli\n", filepos, sw->file_pagepos_found);
851 // read_len = read_len - (filedata_begin - filepos);
852 read_len = read_len + filepos;
857 int have_read = read_buffer_at(stream, sw, read_len, filepos);
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]);
867 // read all pages in the buffer
871 while (first_page || page_length)
873 // if negative, skip bytes
874 while ((page_length = sync_and_take_page_out(sw, &page)) < 0)
876 page_offset -= page_length;
879 // printf("BBBb page_len: %i\n", page_length);
881 // if (filepos == 0 && page_length)
883 // printf("AAAAAAAAAAAAAAAAAAAAAAAAAaaa\n");
884 // printf("pp: %lli %x\n", sw->file_pagepos, ogg_page_serialno(&page));
887 first_page_offset = page_offset;
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)
892 // we will copy every page until last page in this buffer
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));
900 // printf("fpo: %i\n", first_page_offset);
901 filepos += first_page_offset - READ_SIZE;
904 // printf("finished\n");
911 int FileOGG::ogg_get_last_page(sync_window_t *sw, long serialno, ogg_page *og)
914 off_t filepos = file_length - READ_SIZE;
918 int first_page_offset = 0;
920 while (!done && filepos >= 0)
923 read_buffer_at(stream, sw, READ_SIZE, filepos);
925 // read all pages in the buffer
929 while (first_page || page_length)
931 // if negative, skip bytes
932 while ((page_length = sync_and_take_page_out(sw, &page)) < 0)
933 page_offset -= page_length;
935 first_page_offset = page_offset;
937 if (page_length && ogg_page_serialno(&page) == serialno)
939 // we will copy every page until last page in this buffer
941 sw->file_pagepos_found = sw->file_pagepos - page.header_len - page.body_len;
942 memcpy(og, &page, sizeof(page));
945 filepos = filepos + first_page_offset - READ_SIZE;
954 int FileOGG::ogg_get_first_page(sync_window_t *sw, long serialno, ogg_page *og)
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));
962 int FileOGG::ogg_seek_to_databegin(sync_window_t *sw, long serialno)
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
971 int FileOGG::ogg_get_next_page(sync_window_t *sw, long serialno, ogg_page *og)
973 while (take_page_out_autoadvance(stream, sw, og) > 0)
975 if (ogg_page_serialno(og) == serialno)
977 sw->file_pagepos_found = sw->file_pagepos - og->header_len - og->body_len;
984 int FileOGG::ogg_sync_and_get_next_page(sync_window_t *sw, long serialno, ogg_page *og)
986 // TODO: Put better error reporting inhere
988 while ((ret = sync_and_take_page_out(sw, og)) < 0)
994 if (ogg_page_serialno(og) == serialno)
996 sw->file_pagepos_found = sw->file_pagepos - og->header_len - og->body_len;
999 while (ogg_get_next_page(sw, serialno, og))
1000 if (ogg_page_serialno(og) == serialno)
1002 sw->file_pagepos_found = sw->file_pagepos - og->header_len - og->body_len;
1009 // >= 0, number of sample within a page
1011 int FileOGG::ogg_get_page_of_sample(sync_window_t *sw, long serialno, ogg_page *og, int64_t sample)
1013 // First make an educated guess about position
1014 if (sample >= asset->audio_length + start_sample)
1016 printf(_("FileOGG: Illegal seek beyond end of samples\n"));
1019 off_t educated_guess = filedata_begin + (file_length - filedata_begin) * (sample - start_sample) / asset->audio_length - READ_SIZE;
1020 if (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)
1034 while (end_sample <= sample)
1036 ogg_get_next_page(sw, serialno, og);
1037 start_sample = end_sample;
1038 end_sample = ogg_page_granulepos(og);
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);
1046 start_sample = end_sample;
1047 while (start_sample > sample || (ogg_page_continued(og) &&
1048 ogg_page_packets(og) == 1))
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);
1055 // go forward one page at the end
1059 // printf("For sample %lli we need to start decoding on page with granulepos: %lli\n", sample, ogg_page_granulepos(og));
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
1067 int FileOGG::ogg_seek_to_sample(sync_window_t *sw, long serialno, int64_t sample)
1069 // MAYBE FIXME - find out if we really are decoding previous two packets or not
1070 // get to the sample
1073 // printf("Calling get page of sample\n");
1074 if (!ogg_get_page_of_sample(sw, serialno, &og, sample))
1076 eprintf(_("FileOGG: Seeking to sample's page failed\n"));
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);
1084 // printf("seeking to sample : %lli , starting at page with gpos: %lli\n", sample, ogg_page_granulepos(&og));
1086 int64_t current_comming_sample = -1;
1090 // make sure we have a packet ready
1091 while (ogg_stream_packetpeek(&tf->vo, NULL) != 1)
1093 if (!ogg_get_next_page(sw, serialno, &og))
1095 eprintf(_("FileOGG: Cannot find next page while seeking\n"));
1098 ogg_stream_pagein(&tf->vo, &og);
1100 ogg_stream_packetout(&tf->vo, &op);
1104 if(!vorbis_synthesis(&tf->vb, &op))
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)
1111 if (previous_comming_sample > sample)
1113 eprintf(_("Ogg decoding error while seeking sample\n"));
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!
1120 // discard decoded data before current sample
1121 vorbis_synthesis_read(&tf->vd, (current_comming_sample - previous_comming_sample));
1126 if (!sync && op.granulepos >= 0)
1129 current_comming_sample = op.granulepos;
1130 if(!vorbis_synthesis(&tf->vb, &op))
1132 vorbis_synthesis_blockin(&tf->vd, &tf->vb);
1133 if (vorbis_synthesis_pcmout(&tf->vd, NULL) != 0)
1135 eprintf(_("FileOGG: Something wrong while trying to seek\n"));
1148 int FileOGG::ogg_get_page_of_frame(sync_window_t *sw, long serialno, ogg_page *og, int64_t frame)
1150 if (frame >= asset->video_length + start_frame)
1152 eprintf(_("FileOGG: Illegal seek beyond end of frames\n"));
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"));
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)
1175 if (ogg_get_next_page(sw, serialno, og) == 0)
1181 pageend_frame = theora_granule_frame(&tf->td, ogg_page_granulepos(og));
1183 // FIXME - MEDIUM PRIORITY: read back if we've gone too far and no page of our serialno at all can be found
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;
1192 if (pageend_frame <= frame)
1195 while (pageend_frame < frame)
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));
1203 // go back if this frame starts on previous page
1204 if (ogg_page_continued(og) && pageend_frame - ogg_page_packets(og) == frame - 1)
1207 ogg_get_prev_page(sw, serialno, og);
1208 } while (ogg_page_packets(og) == 0 && ogg_page_continued(og));
1210 pageend_frame = theora_granule_frame(&tf->td, ogg_page_granulepos(og));
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)
1219 // printf("get prev page: %lli pagepos:%lli\n", ogg_page_granulepos(og), sw->file_pagepos_found);
1221 ogg_get_prev_page(sw, serialno, og);
1222 } while (ogg_page_packets(og) == 0 && ogg_page_continued(og));
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--;
1230 // printf("Miss plus: %i, miss minus: %i\n", missp, missm);
1231 // printf("last frame of page with frame : %lli\n", pageend_frame);
1236 int FileOGG::ogg_seek_to_keyframe(sync_window_t *sw, long serialno, int64_t frame, int64_t *position)
1238 //printf("seek %jd\n", frame);
1242 if( !ogg_get_page_of_frame(sw, serialno, &og, frame) ) {
1243 eprintf(_("FileOGG: seek to frame failed\n"));
1246 // find a page with packets
1247 while( ogg_page_packets(&og) == 0 ) {
1248 ogg_get_prev_page(sw, serialno, &og);
1250 int64_t granulepos = ogg_page_granulepos(&og);
1251 granulepos &= ~((1<<theora_keyframe_granule_shift)-1);
1252 int64_t iframe = theora_granule_frame(&tf->td, granulepos);
1253 // iframe based on granulepos
1254 if( frame < iframe || !ogg_get_page_of_frame(sw, serialno, &og, iframe) ) {
1255 eprintf(_("FileOGG: seek to iframe failed\n"));
1258 while( ogg_page_packets(&og) == 0 ) {
1259 ogg_get_prev_page(sw, serialno, &og);
1261 int64_t pageend_frame = theora_granule_frame(&tf->td, ogg_page_granulepos(&og));
1262 int64_t frames_on_page = ogg_page_packets(&og);
1263 if( ogg_page_continued(&og) ) --frames_on_page;
1264 // get frame before page with with iframe
1265 int64_t page_frame = pageend_frame - frames_on_page;
1266 if( page_frame < 0 ) page_frame = 0;
1267 //printf("iframe %jd, page_frame %jd, frames_on_page %jd\n", iframe, page_frame, frames_on_page);
1268 ogg_stream_reset(&tf->to);
1269 ogg_stream_pagein(&tf->to, &og);
1271 while( ++page_frame < iframe ) {
1272 while( ogg_stream_packetpeek(&tf->to, NULL) != 1 ) {
1273 if( !ogg_get_next_page(sw, serialno, &og) ) {
1274 eprintf(_("FileOGG: Cannot find next page while seeking\n"));
1277 ogg_stream_pagein(&tf->to, &og);
1279 ogg_stream_packetout(&tf->to, &op);
1282 *position = iframe - 1;
1287 int FileOGG::check_sig(Asset *asset)
1290 FILE *fd = fopen(asset->path, "rb");
1293 fseek(fd, 0, SEEK_SET);
1296 (void)fread(data, 4, 1, fd);
1298 if(data[0] == 'O' &&
1305 // printf("Yay, we have an ogg file\n");
1315 int FileOGG::close_file()
1322 if (asset->audio_data)
1323 write_samples_vorbis(0, 0, 1); // set eos
1324 if (asset->video_data)
1325 write_frames_theora(0, 1, 1); // set eos
1327 flush_ogg(1); // flush all
1329 if (asset->audio_data)
1331 vorbis_block_clear (&tf->vb);
1332 vorbis_dsp_clear (&tf->vd);
1333 vorbis_info_clear (&tf->vi);
1334 ogg_stream_clear (&tf->vo);
1336 if (asset->video_data)
1338 theora_info_clear (&tf->ti);
1339 ogg_stream_clear (&tf->to);
1340 theora_clear (&tf->td);
1343 if (stream) fclose(stream);
1349 if (asset->audio_data)
1351 vorbis_block_clear (&tf->vb);
1352 vorbis_dsp_clear (&tf->vd);
1353 vorbis_comment_clear (&tf->vc);
1354 vorbis_info_clear (&tf->vi);
1355 ogg_stream_clear (&tf->vo);
1357 theora_comment_clear(&tf->tc);
1358 if (asset->video_data)
1360 theora_info_clear (&tf->ti);
1361 theora_comment_clear (&tf->tc);
1362 theora_clear (&tf->td);
1363 ogg_stream_clear (&tf->to);
1367 if (stream) fclose(stream);
1374 int FileOGG::close_file_derived()
1376 //printf("FileOGG::close_file_derived(): 1\n");
1377 if (stream) fclose(stream);
1382 int64_t FileOGG::get_video_position()
1385 return next_frame_position - start_frame;
1388 int64_t FileOGG::get_audio_position()
1390 return next_sample_position - start_sample;
1393 int FileOGG::set_video_position(int64_t x)
1396 // printf("SVP: %lli\n", x);
1398 next_frame_position = x + start_frame;
1403 int FileOGG::colormodel_supported(int colormodel)
1407 if (colormodel == BC_YUV420P)
1412 int FileOGG::get_best_colormodel(Asset *asset, int driver)
1419 int FileOGG::read_frame(VFrame *frame)
1422 if(!stream) return 1;
1425 // skip is cheaper than seek, do it...
1426 int decode_frames = 0;
1427 int expect_keyframe = 0;
1428 if (ogg_frame_position >= 0 &&
1429 next_frame_position >= ogg_frame_position &&
1430 next_frame_position - ogg_frame_position < 32)
1432 decode_frames = next_frame_position - ogg_frame_position;
1434 if (next_frame_position != ogg_frame_position)
1436 if (!ogg_seek_to_keyframe(tf->videosync, tf->to.serialno,
1437 next_frame_position, &ogg_frame_position)) {
1438 eprintf(_("FileOGG:: Error while seeking to frame's keyframe"
1439 " (frame: %jd, keyframe: %jd)\n"),
1440 next_frame_position, ogg_frame_position);
1443 // printf("For frame: %lli, keyframe is: %lli\n", next_frame_position,ogg_frame_position);
1444 // skip frames must be > 0 here
1445 decode_frames = next_frame_position - ogg_frame_position;
1446 if (decode_frames <= 0)
1448 eprintf(_("FileOGG:: Error while seeking to keyframe,"
1449 " wrong keyframe number (frame: %jd, keyframe: %jd)\n"),
1450 next_frame_position, ogg_frame_position);
1454 expect_keyframe = 1;
1457 // printf("Frames to decode: %i\n", decode_frames);
1459 // THIS IS WHAT CAUSES SLOWNESS OF SEEKING, but we can do nothing about it.
1461 while (decode_frames > 0)
1465 while (ogg_stream_packetpeek(&tf->to, NULL) != 1)
1467 if (!ogg_get_next_page(tf->videosync, tf->to.serialno, &og))
1469 eprintf(_("FileOGG: Cannot find next page while seeking\n"));
1472 ogg_stream_pagein(&tf->to, &og);
1474 ogg_stream_packetout(&tf->to, &op);
1475 if( theora_packet_isheader(&op) ) continue;
1476 //printf("frame %jd, key %d\n", ogg_frame_position, theora_packet_iskeyframe(&op));
1477 if (expect_keyframe && !theora_packet_iskeyframe(&op))
1479 eprintf(_("FileOGG: Expecting keyframe, but didn't get it\n"));
1480 // return 1; this is generally not a fatal error
1482 expect_keyframe = 0;
1485 ret = theora_decode_packetin(&tf->td, &op);
1486 //if(ret < 0 )printf("ret = %d\n", ret);
1488 ogg_frame_position ++;
1492 int ret = theora_decode_YUVout (&tf->td, &yuv);
1495 eprintf(_("FileOGG: theora_decode_YUVout failed with code %i\n"), ret);
1499 /* yuv.y += yuv.y_stride * (yuv.y_height - 1);
1500 yuv.u += yuv.uv_stride * (yuv.uv_height - 1);
1501 yuv.v += yuv.uv_stride * (yuv.uv_height - 1);
1502 yuv.y_stride = - yuv.y_stride;
1503 yuv.uv_stride = - yuv.uv_stride;*/
1504 VFrame *temp_frame = new VFrame(yuv.y, -1, 0,
1505 yuv.u - yuv.y, yuv.v - yuv.y, - yuv.y_stride,
1506 yuv.y_height, BC_YUV420P, - yuv.y_stride);
1507 // copy into temp frame...
1509 BC_CModels::transfer(frame->get_rows(),
1510 temp_frame->get_rows(),
1514 temp_frame->get_y(),
1515 temp_frame->get_u(),
1516 temp_frame->get_v(),
1523 yuv.y_width, // temp_frame can be larger than frame if width not dividable by 16
1526 frame->get_color_model(),
1528 -temp_frame->get_w(),
1533 next_frame_position ++;
1540 int FileOGG::ogg_decode_more_samples(sync_window_t *sw, long serialno)
1547 while (ogg_stream_packetpeek(&tf->vo, NULL) != 1)
1549 if (!ogg_get_next_page(sw, serialno, &og))
1551 eprintf(_("FileOGG: Cannot find next page while trying to decode more samples\n"));
1554 ogg_stream_pagein(&tf->vo, &og);
1556 ogg_stream_packetout(&tf->vo, &op);
1557 if(!vorbis_synthesis(&tf->vb, &op))
1560 vorbis_synthesis_blockin(&tf->vd, &tf->vb);
1566 int FileOGG::set_audio_position(int64_t x)
1568 next_sample_position = x + start_sample;
1572 int FileOGG::move_history(int from, int to, int len)
1575 for(int i = 0; i < asset->channels; i++)
1576 memmove(pcm_history[i] + to, pcm_history[i] + from, sizeof(float) * len);
1578 history_start = history_start + from - to;
1579 if( history_start < 0 ) history_start = 0;
1583 int FileOGG::read_samples(double *buffer, int64_t len)
1585 float **vorbis_buffer;
1588 // printf("Reading samples: Channel: %i, number of samples: %lli, reading at :%lli\n", file->current_channel, len, next_sample_position);
1589 // printf("\tnext_sample_position: %lli, length: %i\n", next_sample_position, len);
1590 // printf("\thistory_start: %lli, length: %i\n", history_start, history_size);
1592 if(len > HISTORY_MAX)
1594 eprintf(_("max samples=%d\n"), HISTORY_MAX);
1600 pcm_history = new float*[asset->channels];
1601 for(int i = 0; i < asset->channels; i++)
1602 pcm_history[i] = new float[HISTORY_MAX];
1603 history_start = -100000000; // insane value to trigger reload
1607 int64_t hole_start = -1;
1608 int64_t hole_len = -1;
1609 int64_t hole_absstart = -1;
1610 int64_t hole_fill = 0;
1612 if (history_start < next_sample_position && history_start + history_size > next_sample_position && history_start + history_size < next_sample_position + len)
1616 hole_start = history_start + history_size - next_sample_position;
1617 hole_len = history_size - hole_start;
1618 hole_absstart = next_sample_position + hole_start;
1619 move_history(next_sample_position - history_start,
1624 if (next_sample_position < history_start && history_start < next_sample_position + len)
1629 hole_len = history_start - next_sample_position;
1630 hole_absstart = next_sample_position;
1631 // printf("hs: %lli, histstart: %lli, next_sample_position: %lli\n", history_size, history_start, next_sample_position);
1632 // printf("to: 0, from: %lli, size: %lli\n",
1633 // history_start - next_sample_position,
1634 // history_size - history_start + next_sample_position);
1636 history_start - next_sample_position,
1637 history_size - history_start + next_sample_position);
1640 if (next_sample_position >= history_start + history_size || next_sample_position + len <= history_start)
1645 hole_len = HISTORY_MAX;
1646 hole_absstart = next_sample_position;
1647 history_start = hole_absstart;
1648 history_size = hole_len;
1653 if (hole_start < 0 || hole_len <= 0 || hole_absstart < 0)
1655 eprintf(_("FileOGG: Error at finding out what to read from file\n"));
1659 if (hole_absstart + hole_len > asset->audio_length + start_sample)
1661 hole_len = asset->audio_length + start_sample - hole_absstart;
1662 history_size = asset->audio_length + start_sample - history_start;
1665 history_size = HISTORY_MAX;
1669 // printf("Decode samples at position: %lli, samples to read: %lli\n", hole_absstart, hole_len);
1671 int64_t samples_read = 0;
1672 if (ogg_sample_position != hole_absstart)
1674 ogg_sample_position = hole_absstart;
1675 if (!ogg_seek_to_sample(tf->audiosync, tf->vo.serialno, ogg_sample_position))
1677 eprintf(_("Error while seeking to sample\n"));
1681 // now we have ogg_sample_positon aligned
1682 int64_t samples_to_read = hole_len;
1683 while (samples_read < hole_len)
1685 int64_t waiting_samples = vorbis_synthesis_pcmout(&tf->vd, &vorbis_buffer);
1686 int64_t takeout_samples;
1687 if (waiting_samples > samples_to_read - samples_read)
1688 takeout_samples = samples_to_read - samples_read;
1690 takeout_samples = waiting_samples;
1692 // printf("takeout samples: %lli, samples_read: %lli\n", takeout_samples, samples_read);
1696 for(int i = 0; i < asset->channels; i++)
1698 float *input = vorbis_buffer[i];
1699 float *output = pcm_history[i] + hole_start;
1701 for(int j = 0; j < takeout_samples ; j++)
1703 output[j] = input[j];
1708 vorbis_synthesis_read(&tf->vd, takeout_samples);
1709 samples_read += takeout_samples;
1710 ogg_sample_position += takeout_samples;
1711 hole_start += takeout_samples;
1713 if (samples_read < hole_len)
1714 if (!ogg_decode_more_samples(tf->audiosync, tf->vo.serialno))
1716 ogg_sample_position = -1;
1724 // now we can be sure our history is correct, just copy it out
1725 if (next_sample_position < history_start || next_sample_position + len > history_start + history_size)
1727 printf(_("FileOGG:: History not aligned properly \n"));
1728 printf(_("\tnext_sample_position: %jd, length: %jd\n"), next_sample_position, len);
1729 printf(_("\thistory_start: %jd, length: %jd\n"), history_start, history_size);
1732 float *input = pcm_history[file->current_channel] + next_sample_position - history_start;
1733 for (int i = 0; i < len; i++)
1734 buffer[i] = input[i];
1736 next_sample_position += len;
1741 int FileOGG::write_audio_page()
1745 ret = fwrite(tf->apage, 1, tf->apage_len, stream);
1746 if(ret < tf->apage_len)
1748 eprintf(_("error writing audio page\n"));
1750 tf->apage_valid = 0;
1751 tf->a_pkg -= ogg_page_packets((ogg_page *)&tf->apage);
1755 int FileOGG::write_video_page()
1759 ret = fwrite(tf->vpage, 1, tf->vpage_len, stream);
1760 if(ret < tf->vpage_len)
1762 eprintf(_("error writing video page\n"));
1764 tf->vpage_valid = 0;
1765 tf->v_pkg -= ogg_page_packets((ogg_page *)&tf->vpage);
1769 void FileOGG::flush_ogg (int e_o_s)
1775 /* flush out the ogg pages */
1777 /* Get pages for both streams, if not already present, and if available.*/
1778 if(asset->video_data && !tf->vpage_valid) {
1779 // this way seeking is much better,
1780 // not sure if 23 packets is a good value. it works though
1782 if(tf->v_pkg>22 && ogg_stream_flush(&tf->to, &og) > 0) {
1785 else if(ogg_stream_pageout(&tf->to, &og) > 0) {
1789 len = og.header_len + og.body_len;
1790 if(tf->vpage_buffer_length < len) {
1791 tf->vpage = (unsigned char *)realloc(tf->vpage, len);
1792 tf->vpage_buffer_length = len;
1794 tf->vpage_len = len;
1795 memcpy(tf->vpage, og.header, og.header_len);
1796 memcpy(tf->vpage+og.header_len , og.body, og.body_len);
1798 tf->vpage_valid = 1;
1799 tf->videotime = theora_granule_time (&tf->td,
1800 ogg_page_granulepos(&og));
1803 if(asset->audio_data && !tf->apage_valid) {
1804 // this way seeking is much better,
1805 // not sure if 23 packets is a good value. it works though
1807 if(tf->a_pkg>22 && ogg_stream_flush(&tf->vo, &og) > 0) {
1810 else if(ogg_stream_pageout(&tf->vo, &og) > 0) {
1814 len = og.header_len + og.body_len;
1815 if(tf->apage_buffer_length < len) {
1816 tf->apage = (unsigned char *)realloc(tf->apage, len);
1817 tf->apage_buffer_length = len;
1819 tf->apage_len = len;
1820 memcpy(tf->apage, og.header, og.header_len);
1821 memcpy(tf->apage+og.header_len , og.body, og.body_len);
1823 tf->apage_valid = 1;
1824 tf->audiotime= vorbis_granule_time (&tf->vd,
1825 ogg_page_granulepos(&og));
1829 if(!asset->audio_data && tf->vpage_valid) {
1832 else if(!asset->video_data && tf->apage_valid) {
1835 /* We're using both. We can output only:
1836 * a) If we have valid pages for both
1837 * b) At EOS, for the remaining stream.
1839 else if(tf->vpage_valid && tf->apage_valid) {
1840 /* Make sure they're in the right order. */
1841 if(tf->videotime <= tf->audiotime)
1846 else if(e_o_s && tf->vpage_valid) {
1849 else if(e_o_s && tf->apage_valid) {
1853 break; /* Nothing more writable at the moment */
1856 flush_lock->unlock();
1860 int FileOGG::write_samples_vorbis(double **buffer, int64_t len, int e_o_s)
1862 float **vorbis_buffer;
1863 static int samples = 0;
1867 vorbis_analysis_wrote (&tf->vd, 0);
1870 vorbis_buffer = vorbis_analysis_buffer (&tf->vd, len);
1871 /* double to float conversion */
1872 for(int i = 0; i<asset->channels; i++)
1874 for (int j = 0; j < len; j++)
1876 vorbis_buffer[i][j] = buffer[i][j];
1879 vorbis_analysis_wrote (&tf->vd, len);
1881 while(vorbis_analysis_blockout (&tf->vd, &tf->vb) == 1)
1883 /* analysis, assume we want to use bitrate management */
1884 vorbis_analysis (&tf->vb, NULL);
1885 vorbis_bitrate_addblock (&tf->vb);
1887 /* weld packets into the bitstream */
1888 while (vorbis_bitrate_flushpacket (&tf->vd, &tf->op))
1891 ogg_stream_packetin (&tf->vo, &tf->op);
1893 flush_lock->unlock();
1903 int FileOGG::write_samples(double **buffer, int64_t len)
1906 return write_samples_vorbis(buffer, len, 0);
1910 int FileOGG::write_frames_theora(VFrame ***frames, int len, int e_o_s)
1912 // due to clumsy theora's design we need to delay writing out by one frame
1913 // always stay one frame behind, so we can correctly encode e_o_s
1915 if(!stream) return 0;
1917 for(int j = 0; j < len && !result; j++)
1919 if (temp_frame) // encode previous frame if available
1922 yuv.y_width = tf->ti.width;
1923 yuv.y_height = tf->ti.height;
1924 yuv.y_stride = temp_frame->get_bytes_per_line();
1926 yuv.uv_width = tf->ti.width / 2;
1927 yuv.uv_height = tf->ti.height / 2;
1928 yuv.uv_stride = temp_frame->get_bytes_per_line() /2;
1930 yuv.y = temp_frame->get_y();
1931 yuv.u = temp_frame->get_u();
1932 yuv.v = temp_frame->get_v();
1933 int ret = theora_encode_YUVin (&tf->td, &yuv);
1936 printf(_("FileOGG: theora_encode_YUVin failed with code %i\n"), ret);
1937 printf("yuv_buffer: y_width: %i, y_height: %i, y_stride: %i,"
1938 " uv_width: %i, uv_height: %i, uv_stride: %i\n",
1939 yuv.y_width, yuv.y_height, yuv.y_stride,
1940 yuv.uv_width, yuv.uv_height, yuv.uv_stride);
1942 while(theora_encode_packetout (&tf->td, e_o_s, &tf->op)) {
1944 ogg_stream_packetin (&tf->to, &tf->op);
1946 flush_lock->unlock();
1948 flush_ogg(0); // eos flush is done later at close_file
1950 // If we have e_o_s, don't encode any new frames
1956 temp_frame = new VFrame ( tf->ti.width, tf->ti.height, BC_YUV420P, 0);
1958 VFrame *frame = frames[0][j];
1959 int in_color_model = frame->get_color_model();
1960 if (in_color_model == BC_YUV422P &&
1961 temp_frame->get_w() == frame->get_w() &&
1962 temp_frame->get_h() == frame->get_h() &&
1963 temp_frame->get_bytes_per_line() == frame->get_bytes_per_line())
1965 temp_frame->copy_from(frame);
1969 BC_CModels::transfer(temp_frame->get_rows(),
1971 temp_frame->get_y(),
1972 temp_frame->get_u(),
1973 temp_frame->get_v(),
1983 frame->get_w(), // temp_frame can be larger than frame if width not dividable by 16
1985 frame->get_color_model(),
1989 temp_frame->get_w());
1998 int FileOGG::write_frames(VFrame ***frames, int len)
2001 return write_frames_theora(frames, len, 0);
2004 OGGConfigAudio::OGGConfigAudio(BC_WindowBase *parent_window, Asset *asset)
2005 : BC_Window(_(PROGRAM_NAME ": Audio Compression"),
2006 parent_window->get_abs_cursor_x(1),
2007 parent_window->get_abs_cursor_y(1),
2011 this->parent_window = parent_window;
2012 this->asset = asset;
2015 OGGConfigAudio::~OGGConfigAudio()
2020 void OGGConfigAudio::create_objects()
2022 // add_tool(new BC_Title(10, 10, _("There are no audio options for this format")));
2026 char string[BCTEXTLEN];
2028 lock_window("OGGConfigAudio::create_objects");
2029 add_tool(fixed_bitrate = new OGGVorbisFixedBitrate(x, y, this));
2030 add_tool(variable_bitrate = new OGGVorbisVariableBitrate(x1, y, this));
2033 sprintf(string, "%d", asset->vorbis_min_bitrate);
2034 add_tool(new BC_Title(x, y, _("Min bitrate:")));
2035 add_tool(new OGGVorbisMinBitrate(x1, y, this, string));
2038 add_tool(new BC_Title(x, y, _("Avg bitrate:")));
2039 sprintf(string, "%d", asset->vorbis_bitrate);
2040 add_tool(new OGGVorbisAvgBitrate(x1, y, this, string));
2043 add_tool(new BC_Title(x, y, _("Max bitrate:")));
2044 sprintf(string, "%d", asset->vorbis_max_bitrate);
2045 add_tool(new OGGVorbisMaxBitrate(x1, y, this, string));
2048 add_subwindow(new BC_OKButton(this));
2053 int OGGConfigAudio::close_event()
2059 OGGVorbisFixedBitrate::OGGVorbisFixedBitrate(int x, int y, OGGConfigAudio *gui)
2060 : BC_Radial(x, y, !gui->asset->vorbis_vbr, _("Average bitrate"))
2064 int OGGVorbisFixedBitrate::handle_event()
2066 gui->asset->vorbis_vbr = 0;
2067 gui->variable_bitrate->update(0);
2071 OGGVorbisVariableBitrate::OGGVorbisVariableBitrate(int x, int y, OGGConfigAudio *gui)
2072 : BC_Radial(x, y, gui->asset->vorbis_vbr, _("Variable bitrate"))
2076 int OGGVorbisVariableBitrate::handle_event()
2078 gui->asset->vorbis_vbr = 1;
2079 gui->fixed_bitrate->update(0);
2084 OGGVorbisMinBitrate::OGGVorbisMinBitrate(int x,
2086 OGGConfigAudio *gui,
2088 : BC_TextBox(x, y, 180, 1, text)
2092 int OGGVorbisMinBitrate::handle_event()
2094 gui->asset->vorbis_min_bitrate = atol(get_text());
2100 OGGVorbisMaxBitrate::OGGVorbisMaxBitrate(int x,
2102 OGGConfigAudio *gui,
2104 : BC_TextBox(x, y, 180, 1, text)
2108 int OGGVorbisMaxBitrate::handle_event()
2110 gui->asset->vorbis_max_bitrate = atol(get_text());
2116 OGGVorbisAvgBitrate::OGGVorbisAvgBitrate(int x, int y, OGGConfigAudio *gui, char *text)
2117 : BC_TextBox(x, y, 180, 1, text)
2121 int OGGVorbisAvgBitrate::handle_event()
2123 gui->asset->vorbis_bitrate = atol(get_text());
2131 OGGConfigVideo::OGGConfigVideo(BC_WindowBase *parent_window, Asset *asset)
2132 : BC_Window(_(PROGRAM_NAME ": Video Compression"),
2133 parent_window->get_abs_cursor_x(1),
2134 parent_window->get_abs_cursor_y(1),
2138 this->parent_window = parent_window;
2139 this->asset = asset;
2142 OGGConfigVideo::~OGGConfigVideo()
2147 void OGGConfigVideo::create_objects()
2149 // add_tool(new BC_Title(10, 10, _("There are no video options for this format")));
2154 lock_window("OGGConfigVideo::create_objects");
2155 add_subwindow(new BC_Title(x, y + 5, _("Bitrate:")));
2156 add_subwindow(new OGGTheoraBitrate(x1, y, this));
2157 add_subwindow(fixed_bitrate = new OGGTheoraFixedBitrate(x2, y, this));
2160 add_subwindow(new BC_Title(x, y, _("Quality:")));
2161 add_subwindow(new BC_ISlider(x + 80,
2168 asset->theora_quality,
2171 &asset->theora_quality));
2174 add_subwindow(fixed_quality = new OGGTheoraFixedQuality(x2, y, this));
2177 add_subwindow(new BC_Title(x, y, _("Keyframe frequency:")));
2178 OGGTheoraKeyframeFrequency *keyframe_frequency =
2179 new OGGTheoraKeyframeFrequency(x1 + 60, y, this);
2180 keyframe_frequency->create_objects();
2183 add_subwindow(new BC_Title(x, y, _("Keyframe force frequency:")));
2184 OGGTheoraKeyframeForceFrequency *keyframe_force_frequency =
2185 new OGGTheoraKeyframeForceFrequency(x1 + 60, y, this);
2186 keyframe_force_frequency->create_objects();
2189 add_subwindow(new BC_Title(x, y, _("Sharpness:")));
2190 OGGTheoraSharpness *sharpness =
2191 new OGGTheoraSharpness(x1 + 60, y, this);
2192 sharpness->create_objects();
2196 add_subwindow(new BC_OKButton(this));
2204 int OGGConfigVideo::close_event()
2210 OGGTheoraBitrate::OGGTheoraBitrate(int x, int y, OGGConfigVideo *gui)
2211 : BC_TextBox(x, y, 100, 1, gui->asset->theora_bitrate)
2217 int OGGTheoraBitrate::handle_event()
2219 // TODO: MIN / MAX check
2220 gui->asset->theora_bitrate = atol(get_text());
2227 OGGTheoraFixedBitrate::OGGTheoraFixedBitrate(int x, int y, OGGConfigVideo *gui)
2228 : BC_Radial(x, y, gui->asset->theora_fix_bitrate, _("Fixed bitrate"))
2233 int OGGTheoraFixedBitrate::handle_event()
2236 gui->asset->theora_fix_bitrate = 1;
2237 gui->fixed_quality->update(0);
2241 OGGTheoraFixedQuality::OGGTheoraFixedQuality(int x, int y, OGGConfigVideo *gui)
2242 : BC_Radial(x, y, !gui->asset->theora_fix_bitrate, _("Fixed quality"))
2247 int OGGTheoraFixedQuality::handle_event()
2250 gui->asset->theora_fix_bitrate = 0;
2251 gui->fixed_bitrate->update(0);
2255 OGGTheoraKeyframeFrequency::OGGTheoraKeyframeFrequency(int x, int y, OGGConfigVideo *gui)
2256 : BC_TumbleTextBox(gui,
2257 (int64_t)gui->asset->theora_keyframe_frequency,
2267 int OGGTheoraKeyframeFrequency::handle_event()
2269 gui->asset->theora_keyframe_frequency = atol(get_text());
2273 OGGTheoraKeyframeForceFrequency::OGGTheoraKeyframeForceFrequency(int x, int y, OGGConfigVideo *gui)
2274 : BC_TumbleTextBox(gui,
2275 (int64_t)gui->asset->theora_keyframe_frequency,
2285 int OGGTheoraKeyframeForceFrequency::handle_event()
2287 gui->asset->theora_keyframe_frequency = atol(get_text());
2292 OGGTheoraSharpness::OGGTheoraSharpness(int x, int y, OGGConfigVideo *gui)
2293 : BC_TumbleTextBox(gui,
2294 (int64_t)gui->asset->theora_sharpness,
2304 int OGGTheoraSharpness::handle_event()
2306 gui->asset->theora_sharpness = atol(get_text());
2311 PackagingEngineOGG::PackagingEngineOGG()
2317 PackagingEngineOGG::~PackagingEngineOGG()
2321 for(int i = 0; i < total_packages; i++)
2326 delete default_asset;
2331 int PackagingEngineOGG::create_packages_single_farm(
2333 Preferences *preferences,
2334 Asset *default_asset,
2338 this->total_start = total_start;
2339 this->total_end = total_end;
2342 this->preferences = preferences;
2344 // We make A COPY of the asset, because we set audio_data = 0 on local asset which is the same copy as default_asset...
2345 // Should be taken care of somewhere else actually
2346 this->default_asset = new Asset(*default_asset);
2348 audio_start = Units::to_int64(total_start * default_asset->sample_rate);
2349 video_start = Units::to_int64(total_start * default_asset->frame_rate);
2350 audio_position = audio_start;
2351 video_position = video_start;
2352 audio_end = Units::to_int64(total_end * default_asset->sample_rate);
2353 video_end = Units::to_int64(total_end * default_asset->frame_rate);
2354 current_package = 0;
2356 double total_len = total_end - total_start;
2357 //printf("PackageDispatcher::create_packages: %f / %d = %f\n", total_len, total_packages, package_len);
2360 if (default_asset->audio_data)
2362 if (default_asset->video_data)
2363 total_packages += preferences->renderfarm_job_count;
2365 packages = new RenderPackage*[total_packages];
2367 int local_current_package = 0;
2368 if (default_asset->audio_data)
2370 packages[local_current_package] = new RenderPackage;
2371 snprintf(packages[current_package]->path,
2372 sizeof(packages[current_package]->path),
2373 "%s.audio", default_asset->path);
2374 local_current_package++;
2377 if (default_asset->video_data)
2379 video_package_len = (total_len) / preferences->renderfarm_job_count;
2380 int current_number; // The number being injected into the filename.
2381 int number_start; // Character in the filename path at which the number begins
2382 int total_digits; // Total number of digits including padding the user specified.
2384 Render::get_starting_number(default_asset->path,
2390 for(int i = 0; i < preferences->renderfarm_job_count; i++)
2392 RenderPackage *package = packages[local_current_package] = new RenderPackage;
2393 Render::create_filename(package->path,
2394 default_asset->path,
2399 local_current_package++;
2405 RenderPackage* PackagingEngineOGG::get_package_single_farm(double frames_per_second,
2410 //printf("PackageDispatcher::get_package %ld %ld %ld %ld\n", audio_position, video_position, audio_end, video_end);
2411 if (current_package == total_packages)
2414 RenderPackage *result = 0;
2415 if (current_package == 0 && default_asset->audio_data)
2417 result = packages[0];
2418 result->audio_start = audio_start;
2419 result->video_start = video_start;
2420 result->audio_end = audio_end;
2421 result->video_end = video_end;
2422 result->audio_do = 1;
2423 result->video_do = 0;
2424 } else if (default_asset->video_data)
2426 // Do not do any scaling according to node speed, so we know we can get evenly distributed 'forced' keyframes
2427 result = packages[current_package];
2428 result->audio_do = 0;
2429 result->video_do = 1;
2431 result->audio_start = audio_position;
2432 result->video_start = video_position;
2433 result->audio_end = audio_position +
2434 Units::round(video_package_len * default_asset->sample_rate);
2435 result->video_end = video_position +
2436 Units::round(video_package_len * default_asset->frame_rate);
2438 // Last package... take it all!
2439 if (current_package == total_packages -1 )
2441 result->audio_end = audio_end;
2442 result->video_end = video_end;
2445 audio_position = result->audio_end;
2446 video_position = result->video_end;
2455 void PackagingEngineOGG::get_package_paths(ArrayList<char*> *path_list)
2457 for(int i = 0; i < total_packages; i++)
2459 path_list->append(strdup(packages[i]->path));
2461 // We will mux to the the final file at the end!
2462 path_list->append(strdup(default_asset->path));
2463 path_list->set_free();
2466 int64_t PackagingEngineOGG::get_progress_max()
2468 return Units::to_int64(default_asset->sample_rate *
2469 (total_end - total_start)) * 2+
2470 Units::to_int64(preferences->render_preroll *
2472 default_asset->sample_rate);
2475 int PackagingEngineOGG::packages_are_done()
2479 // Mux audio and video into one file
2481 // First fix our asset... have to workaround the bug of corruption of local asset
2482 // Render::check_asset(edl, *default_asset);
2484 Asset *video_asset = 0, *audio_asset = 0;
2485 File *audio_file_gen = 0, *video_file_gen = 0;
2486 FileOGG *video_file = 0, *audio_file = 0;
2487 ogg_stream_state audio_in_stream, video_in_stream;
2489 int local_current_package = 0;
2490 if (default_asset->audio_data)
2492 audio_asset = new Asset(packages[local_current_package]->path);
2493 local_current_package++;
2495 audio_file_gen = new File();
2496 audio_file_gen->open_file(preferences, audio_asset, 1, 0);
2497 audio_file = (FileOGG*) audio_file_gen->file;
2498 ogg_stream_init(&audio_in_stream, audio_file->tf->vo.serialno);
2499 audio_file->ogg_seek_to_databegin(audio_file->tf->audiosync, audio_file->tf->vo.serialno);
2502 if (default_asset->video_data)
2504 video_asset = new Asset(packages[local_current_package]->path);
2505 local_current_package++;
2507 video_file_gen = new File();
2508 video_file_gen->open_file(preferences, video_asset, 1, 0);
2509 video_file = (FileOGG*) video_file_gen->file;
2510 ogg_stream_init(&video_in_stream, video_file->tf->to.serialno);
2511 video_file->ogg_seek_to_databegin(video_file->tf->videosync, video_file->tf->to.serialno);
2515 File *output_file_gen = new File();
2516 output_file_gen->open_file(preferences, default_asset, 0, 1);
2517 FileOGG *output_file = (FileOGG*) output_file_gen->file;
2519 //ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */
2520 ogg_packet op; /* one raw packet of data for decode */
2523 int audio_ready = default_asset->audio_data;
2524 int video_ready = default_asset->video_data;
2525 int64_t video_packetno = 1;
2526 int64_t audio_packetno = 1;
2527 int64_t frame_offset = 0;
2528 int64_t current_frame = 0;
2529 while ((default_asset->audio_data && audio_ready) || (default_asset->video_data && video_ready))
2533 while (ogg_stream_packetpeek(&video_in_stream, NULL) != 1) // get as many pages as needed for one package
2535 if (!video_file->ogg_get_next_page(video_file->tf->videosync, video_file->tf->to.serialno, &video_file->tf->videopage))
2537 // We are at the end of our file, see if it is more and open more if there is
2538 if (local_current_package < total_packages)
2540 frame_offset = current_frame +1;
2541 ogg_stream_clear(&video_in_stream);
2542 video_file_gen->close_file();
2543 delete video_file_gen;
2545 video_asset = new Asset(packages[local_current_package]->path);
2546 local_current_package++;
2548 video_file_gen = new File();
2549 video_file_gen->open_file(preferences, video_asset, 1, 0);
2550 video_file = (FileOGG*) video_file_gen->file;
2551 ogg_stream_init(&video_in_stream, video_file->tf->to.serialno);
2552 video_file->ogg_seek_to_databegin(video_file->tf->videosync, video_file->tf->to.serialno);
2558 ogg_stream_pagein(&video_in_stream, &video_file->tf->videopage);
2560 while (ogg_stream_packetpeek(&video_in_stream, NULL) == 1) // get all packets out of the page
2562 ogg_stream_packetout(&video_in_stream, &op);
2563 if (local_current_package != total_packages) // keep it from closing the stream
2565 if (video_packetno != 1) // if this is not the first video package do not start with b_o_s
2569 op.packetno = video_packetno;
2571 int64_t granulepos = op.granulepos;
2572 if (granulepos != -1)
2575 int64_t rel_iframe = granulepos >> video_file->theora_keyframe_granule_shift;
2576 int64_t rel_pframe = granulepos - (rel_iframe << video_file->theora_keyframe_granule_shift);
2577 int64_t rel_current_frame = rel_iframe + rel_pframe;
2578 current_frame = frame_offset + rel_current_frame;
2579 int64_t abs_iframe = current_frame - rel_pframe;
2581 op.granulepos = (abs_iframe << video_file->theora_keyframe_granule_shift) + rel_pframe;
2583 // printf("iframe: %i, pframe: %i, granulepos: %i, op.packetno %lli, abs_iframe: %i\n", rel_iframe, rel_pframe, granulepos, op.packetno, abs_iframe);
2586 ogg_stream_packetin (&output_file->tf->to, &op);
2587 output_file->tf->v_pkg++;
2592 while (ogg_stream_packetpeek(&audio_in_stream, NULL) != 1) // get as many pages as needed for one package
2594 if (!audio_file->ogg_get_next_page(audio_file->tf->audiosync, audio_file->tf->vo.serialno, &audio_file->tf->audiopage))
2599 ogg_stream_pagein(&audio_in_stream, &audio_file->tf->audiopage);
2601 while (ogg_stream_packetpeek(&audio_in_stream, NULL) == 1) // get all packets out of the page
2603 ogg_stream_packetout(&audio_in_stream, &op);
2604 ogg_stream_packetin (&output_file->tf->vo, &op);
2606 output_file->tf->a_pkg++;
2610 output_file->flush_ogg(0);
2615 // flush_ogg(1) is called on file closing time...
2616 // output_file->flush_ogg(1);
2618 // Just prevent thet write_samples and write_frames are called
2619 output_file->final_write = 0;
2621 if (default_asset->audio_data)
2623 ogg_stream_clear(&audio_in_stream);
2624 audio_file_gen->close_file();
2625 delete audio_file_gen;
2628 if (default_asset->video_data)
2630 ogg_stream_clear(&video_in_stream);
2631 video_file_gen->close_file();
2632 delete video_file_gen;
2636 output_file_gen->close_file();
2637 delete output_file_gen;
2639 // Now delete the temp files
2640 for(int i = 0; i < total_packages; i++)
2641 unlink(packages[i]->path);