11 #include "mwindow.inc"
12 #include "quicktime.h"
14 #include "videodevice.inc"
15 #include "cmodel_permutation.h"
16 #include "interlacemodes.h"
18 #include <sys/types.h>
25 // Needed for packaging engine
26 #include "preferences.h"
29 #define READ_SIZE 66000
31 /* This code was aspired by ffmpeg2theora */
32 /* Special thanks for help on this code goes out to j@v2v.cc */
35 FileOGG::FileOGG(Asset *asset, File *file)
36 : FileBase(asset, file)
38 if(asset->format == FILE_UNKNOWN)
39 asset->format = FILE_OGG;
40 asset->byte_order = 0;
52 ogg_sync_clear(&tf->videosync->sync);
54 theora_info_clear(&tf->ti);
55 theora_comment_clear(&tf->tc);
59 ogg_sync_clear(&tf->audiosync->sync);
61 vorbis_info_clear(&tf->vi);
62 vorbis_comment_clear(&tf->vc);
66 if (temp_frame) delete temp_frame;
67 if (stream) close_file();
70 for(int i = 0; i < asset->channels; i++)
71 delete [] pcm_history[i];
72 delete [] pcm_history;
75 if (flush_lock) delete flush_lock;
78 void FileOGG::get_parameters(BC_WindowBase *parent_window,
80 BC_WindowBase* &format_window,
86 OGGConfigAudio *window = new OGGConfigAudio(parent_window, asset);
87 format_window = window;
88 window->create_objects();
95 OGGConfigVideo *window = new OGGConfigVideo(parent_window, asset);
96 format_window = window;
97 window->create_objects();
103 int FileOGG::reset_parameters_derived()
113 int read_buffer(FILE *in, sync_window_t *sw, int buflen)
115 char *buffer = ogg_sync_buffer(&sw->sync, buflen);
116 // printf("reading range: %lli - %lli\n", sw->file_bufpos, sw->file_bufpos + buflen);
117 sw->wlen = fread(buffer, 1, buflen, in);
118 ogg_sync_wrote(&sw->sync, sw->wlen);
119 // printf("XX data: %c %c %c %c\n", sw->sync.data[0], sw->sync.data[1], sw->sync.data[2], sw->sync.data[3]);
120 sw->file_bufpos += sw->wlen;
121 // printf("sb: %i\n",buffer);
125 int read_buffer_at(FILE *in, sync_window_t *sw, int buflen, off_t filepos)
127 // printf("seeking to %lli %lli\n", filepos, sw->file_bufpos);
128 fseeko(in, filepos, SEEK_SET);
129 // if (sw->file_bufpos != filepos)
131 sw->file_bufpos = filepos;
132 sw->file_pagepos = filepos; // this one is not valid until sync_pageseek!
133 ogg_sync_reset(&sw->sync);
136 return read_buffer(in, sw, buflen);
139 int take_page_out_autoadvance(FILE *in, sync_window_t *sw, ogg_page *og)
143 int ret = ogg_sync_pageout(&sw->sync, og);
146 // printf("fpa: %lli\n", sw->file_pagepos);
147 sw->file_pagepos += og->header_len + og->body_len; // advance 'virtual' position
148 // printf("ret2: %i %i\n",ret, og->header_len + og->body_len);
153 printf("FileOGG: Taking page out on nonsynced stream!\n");
158 // need more data for page
159 if (read_buffer(in, sw, READ_SIZE) == 0)
161 // FIXME We should report that just in some situations... sometimes we go to the end
162 // printf("FileOGG: There is no more data in the file we are reading from\n");
163 return 0; // No more data
171 // we never need to autoadvance when syncing, since our read chunks are larger than
173 int sync_and_take_page_out(sync_window_t *sw, ogg_page *page)
175 page->header_len = 0;
179 int ret = ogg_sync_pageseek(&sw->sync, page);
182 sw->file_pagepos -= ret;
186 sw->file_pagepos += ret;
187 // printf("ret: %i %i\n",ret, page->header_len + page->body_len);
193 int FileOGG::open_file(int rd, int wr)
199 tf = new theoraframes_info_t;
204 TRACE("FileOGG::open_file 10")
207 TRACE("FileOGG::open_file 20")
209 if((stream = fopen(asset->path, "w+b")) == 0)
211 perror(_("FileOGG::open_file rdwr"));
215 tf->audio_bytesout = 0;
216 tf->video_bytesout = 0;
222 tf->apage_buffer_length = 0;
223 tf->vpage_buffer_length = 0;
229 /* yayness. Set up Ogg output stream */
232 if(asset->video_data)
234 ogg_stream_init (&tf->to, rand ()); /* oops, add one ot the above */
236 theora_info_init (&tf->ti);
238 tf->ti.frame_width = asset->width;
239 tf->ti.frame_height = asset->height;
241 tf->ti.width = ((asset->width + 15) >>4)<<4; // round up to the nearest multiple of 16
242 tf->ti.height = ((asset->height + 15) >>4)<<4; // round up to the nearest multiple of 16
243 if (tf->ti.width != tf->ti.frame_width || tf->ti.height != tf->ti.frame_height)
244 printf("FileOGG: WARNING: Encoding theora when width or height are not dividable by 16 is suboptimal\n");
247 tf->ti.offset_y = tf->ti.height - tf->ti.frame_height;
248 tf->ti.fps_numerator = (unsigned int)(asset->frame_rate * 1000000);
249 tf->ti.fps_denominator = 1000000;
251 if (asset->aspect_ratio > 0)
253 // Cinelerra uses frame aspect ratio, theora uses pixel aspect ratio
254 float pixel_aspect = asset->aspect_ratio / asset->width * asset->height;
255 tf->ti.aspect_numerator = (unsigned int)(pixel_aspect * 1000000);
256 tf->ti.aspect_denominator = 1000000;
259 tf->ti.aspect_numerator = 1000000;
260 tf->ti.aspect_denominator = 1000000;
262 if(EQUIV(asset->frame_rate, 25) || EQUIV(asset->frame_rate, 50))
263 tf->ti.colorspace = OC_CS_ITU_REC_470BG;
264 else if((asset->frame_rate > 29 && asset->frame_rate < 31) || (asset->frame_rate > 59 && asset->frame_rate < 61) )
265 tf->ti.colorspace = OC_CS_ITU_REC_470M;
267 tf->ti.colorspace = OC_CS_UNSPECIFIED;
269 if (asset->theora_fix_bitrate)
271 tf->ti.target_bitrate = asset->theora_bitrate;
275 tf->ti.target_bitrate = 0;
276 tf->ti.quality = asset->theora_quality; // video quality 0-63
278 tf->ti.dropframes_p = 0;
280 tf->ti.keyframe_auto_p = 1;
281 tf->ti.keyframe_frequency = asset->theora_keyframe_frequency;
282 tf->ti.keyframe_frequency_force = asset->theora_keyframe_force_frequency;
283 tf->ti.keyframe_data_target_bitrate = (unsigned int) (tf->ti.target_bitrate * 1.5) ;
284 tf->ti.keyframe_auto_threshold = 80;
285 tf->ti.keyframe_mindistance = 8;
286 tf->ti.noise_sensitivity = 1;
287 tf->ti.sharpness = 2;
290 if (theora_encode_init (&tf->td, &tf->ti))
292 printf("FileOGG: initialization of theora codec failed\n");
295 /* init theora done */
297 /* initialize Vorbis too, if we have audio. */
298 if(asset->audio_data)
300 ogg_stream_init (&tf->vo, rand ());
301 vorbis_info_init (&tf->vi);
302 /* Encoding using a VBR quality mode. */
304 if(!asset->vorbis_vbr)
306 ret = vorbis_encode_init(&tf->vi,
309 asset->vorbis_max_bitrate,
310 asset->vorbis_bitrate,
311 asset->vorbis_min_bitrate);
314 // Set true VBR as demonstrated by http://svn.xiph.org/trunk/vorbis/doc/vorbisenc/examples.html
315 ret = vorbis_encode_setup_managed(&tf->vi,
319 asset->vorbis_bitrate,
321 ret |= vorbis_encode_ctl(&tf->vi, OV_ECTL_RATEMANAGE_AVG, NULL);
322 ret |= vorbis_encode_setup_init(&tf->vi);
328 "The Vorbis encoder could not set up a mode according to\n"
329 "the requested quality or bitrate.\n\n");
335 vorbis_comment_init (&tf->vc); // comment is cleared lateron
336 vorbis_comment_add_tag (&tf->vc, "ENCODER", PACKAGE_STRING);
337 /* set up the analysis state and auxiliary encoding storage */
338 vorbis_analysis_init (&tf->vd, &tf->vi);
339 vorbis_block_init (&tf->vd, &tf->vb);
342 /* audio init done */
344 /* write the bitstream header packets with proper page interleave */
346 /* first packet will get its own page automatically */
347 if(asset->video_data)
349 theora_encode_header (&tf->td, &tf->op);
350 ogg_stream_packetin (&tf->to, &tf->op);
351 if (ogg_stream_pageout (&tf->to, &tf->og) != 1)
353 fprintf (stderr, "Internal Ogg library error.\n");
356 fwrite (tf->og.header, 1, tf->og.header_len, stream);
357 fwrite (tf->og.body, 1, tf->og.body_len, stream);
359 /* create the remaining theora headers */
360 theora_comment_init (&tf->tc);
361 theora_comment_add_tag (&tf->tc, "ENCODER", PACKAGE_STRING);
362 theora_encode_comment (&tf->tc, &tf->op);
363 ogg_stream_packetin (&tf->to, &tf->op);
364 theora_comment_clear(&tf->tc);
365 theora_encode_tables (&tf->td, &tf->op);
366 ogg_stream_packetin (&tf->to, &tf->op);
368 if(asset->audio_data)
371 ogg_packet header_comm;
372 ogg_packet header_code;
374 vorbis_analysis_headerout (&tf->vd, &tf->vc, &header,
375 &header_comm, &header_code);
376 ogg_stream_packetin (&tf->vo, &header); /* automatically placed in its own page */
377 vorbis_comment_clear(&tf->vc);
378 if (ogg_stream_pageout (&tf->vo, &tf->og) != 1)
380 fprintf (stderr, "Internal Ogg library error.\n");
383 fwrite (tf->og.header, 1, tf->og.header_len, stream);
384 fwrite (tf->og.body, 1, tf->og.body_len, stream);
386 /* remaining vorbis header packets */
387 ogg_stream_packetin (&tf->vo, &header_comm);
388 ogg_stream_packetin (&tf->vo, &header_code);
391 /* Flush the rest of our headers. This ensures
392 * the actual data in each stream will start
393 * on a new page, as per spec. */
394 while (1 && asset->video_data)
396 int result = ogg_stream_flush (&tf->to, &tf->og);
400 fprintf (stderr, "Internal Ogg library error.\n");
405 fwrite (tf->og.header, 1, tf->og.header_len, stream);
406 fwrite (tf->og.body, 1, tf->og.body_len, stream);
408 while (1 && asset->audio_data)
410 int result = ogg_stream_flush (&tf->vo, &tf->og);
414 fprintf (stderr, "Internal Ogg library error.\n");
419 fwrite (tf->og.header, 1, tf->og.header_len, stream);
420 fwrite (tf->og.body, 1, tf->og.body_len, stream);
422 flush_lock = new Mutex("OGGFile::Flush lock");
423 // printf("End of headers at position: %lli\n", ftello(stream));
427 TRACE("FileOGG::open_file 30")
428 if((stream = fopen(asset->path, "rb")) == 0)
430 perror(_("FileOGG::open_file rdwr"));
433 /* get file length */
434 struct stat file_stat;
435 stat(asset->path, &file_stat);
436 file_length = file_stat.st_size;
437 /* start up Ogg stream synchronization layer */
438 /* oy is used just here to parse header, we use separate syncs for video and audio*/
440 ogg_sync_init(&oy.sync);
441 // make sure we init the position structures to zero
442 read_buffer_at(stream, &oy, READ_SIZE, 0);
444 /* init supporting Vorbis structures needed in header parsing */
445 vorbis_info_init(&tf->vi);
446 vorbis_comment_init(&tf->vc);
448 /* init supporting Theora structures needed in header parsing */
449 theora_comment_init(&tf->tc);
450 theora_info_init(&tf->ti);
452 TRACE("FileOGG::open_file 40")
454 /* Ogg file open; parse the headers */
455 /* Only interested in Vorbis/Theora streams */
461 // TRACE("FileOGG::open_file 50")
463 // int ret = read_buffer(stream, &oy, 4096);
464 TRACE("FileOGG::open_file 60")
468 while(take_page_out_autoadvance(stream, &oy, &tf->og) > 0)
470 ogg_stream_state test;
472 /* is this a mandated initial header? If not, stop parsing */
473 if(!ogg_page_bos(&tf->og))
475 /* don't leak the page; get it into the appropriate stream */
476 // queue_page(&tf->og);
477 if(theora_p)ogg_stream_pagein(&tf->to, &tf->og);
478 if(vorbis_p)ogg_stream_pagein(&tf->vo, &tf->og);
484 ogg_stream_init(&test, ogg_page_serialno(&tf->og));
485 ogg_stream_pagein(&test, &tf->og);
486 ogg_stream_packetout(&test, &tf->op);
488 /* identify the codec: try theora */
489 if(!theora_p && theora_decode_header(&tf->ti, &tf->tc, &tf->op)>=0)
492 memcpy(&tf->to, &test, sizeof(test));
494 // find out granule shift - from liboggz's oggz_auto.c
495 unsigned char * header = tf->op.packet;
496 theora_keyframe_granule_shift = (char) ((header[40] & 0x03) << 3);
497 theora_keyframe_granule_shift |= (header[41] & 0xe0) >> 5;
499 } else if(!vorbis_p && vorbis_synthesis_headerin(&tf->vi, &tf->vc, &tf->op)>=0)
502 memcpy(&tf->vo, &test, sizeof(test));
506 /* whatever it is, we don't care about it */
507 ogg_stream_clear(&test);
510 /* fall through to non-bos page parsing */
513 /* we're expecting more header packets. */
514 while((theora_p && theora_p < 3) || (vorbis_p && vorbis_p < 3))
518 /* look for further theora headers */
519 while(theora_p && (theora_p < 3) && (ret = ogg_stream_packetout(&tf->to, &tf->op)))
523 fprintf(stderr,"FileOGG: Error parsing Theora stream headers; corrupt stream?\n");
526 if(theora_decode_header(&tf->ti, &tf->tc, &tf->op))
528 printf("FileOGG: Error parsing Theora stream headers; corrupt stream?\n");
536 /* look for more vorbis header packets */
537 while(vorbis_p && (vorbis_p < 3) && (ret = ogg_stream_packetout(&tf->vo, &tf->op)))
541 fprintf(stderr,"FileOGG: Error parsing Vorbis stream headers; corrupt stream?\n");
544 if (vorbis_synthesis_headerin(&tf->vi, &tf->vc, &tf->op))
546 fprintf(stderr,"FileOGG: Error parsing Vorbis stream headers; corrupt stream?\n");
554 if ((!vorbis_p || vorbis_p == 3) && (!theora_p || theora_p == 3))
556 /* The header pages/packets will arrive before anything else we
557 care about, or the stream is not obeying spec */
559 if(take_page_out_autoadvance(stream, &oy, &tf->og) > 0)
561 // queue_page(&tf->og); /* demux into the appropriate stream */
562 if(theora_p) ogg_stream_pagein(&tf->to, &tf->og);
563 if(vorbis_p) ogg_stream_pagein(&tf->vo, &tf->og);
567 fprintf(stderr,"FileOGG: End of file while searching for codec headers.\n");
571 // Remember where the real data begins for later seeking purposes
572 filedata_begin = oy.file_pagepos;
574 //printf("FileOGG::Data pages begin at %lli\n", filedata_begin);
576 /* and now we have it all. initialize decoders */
581 // WORKAROUND for bug in alpha4 version of theora:
582 tf->td.internal_encode = 0;
584 ret = theora_decode_init(&tf->td, &tf->ti);
585 double fps = (double)tf->ti.fps_numerator/tf->ti.fps_denominator;
586 /* printf("FileOGG: Ogg logical stream %x is Theora %dx%d %.02f fps\n",
587 (unsigned int)tf->to.serialno, tf->ti.width, tf->ti.height,
591 Not yet available in alpha4, we assume 420 for now
593 switch(tf->ti.pixelformat)
595 case OC_PF_420: printf(" 4:2:0 video\n"); break;
596 case OC_PF_422: printf(" 4:2:2 video\n"); break;
597 case OC_PF_444: printf(" 4:4:4 video\n"); break;
600 printf(" video\n (UNKNOWN Chroma sampling!)\n");
605 theora_cmodel = BC_YUV420P;
607 if(tf->ti.width!=tf->ti.frame_width || tf->ti.height!=tf->ti.frame_height)
608 printf("FileOGG:: Frame content is %dx%d with offset (%d,%d), We do not support this yet.\n",
609 tf->ti.frame_width, tf->ti.frame_height, tf->ti.offset_x, tf->ti.offset_y);
611 tf->videosync = new sync_window_t;
612 ogg_sync_init(&tf->videosync->sync);
613 tf->videosync->wlen = 0;
615 ret = ogg_get_first_page(tf->videosync, tf->to.serialno, &tf->videopage);
618 // we have headers already decoded, so just skip them
619 ogg_stream_reset(&tf->to);
620 ogg_stream_pagein(&tf->to, &tf->videopage);
623 while (ogg_stream_packetpeek(&tf->to, NULL) != 1)
625 if (!ogg_get_next_page(tf->videosync, tf->to.serialno, &tf->videopage))
627 printf("FileOGG: Cannot find next page while looking for first non-header packet\n");
630 ogg_stream_pagein(&tf->to, &tf->videopage);
632 ogg_stream_packetout(&tf->to, &op);
633 if (!theora_packet_isheader(&op))
636 // now get to the page of the finish of the first packet
637 while (ogg_page_packets(&tf->videopage) == 0)
639 if (ogg_page_granulepos(&tf->videopage) != -1)
641 printf("FileOGG: Broken ogg file - broken page: ogg_page_packets == 0 and granulepos != -1\n");
644 ogg_get_next_page(tf->videosync, tf->to.serialno, &tf->videopage);
646 // FIXME - LOW PRIORITY - start counting at first decodable keyframe!
647 // but then we have to fix a/v sync somehow
648 start_frame = (int64_t) (theora_granule_frame (&tf->td, ogg_page_granulepos(&tf->videopage)) - ogg_page_packets(&tf->videopage)) + 1;
650 ret = ogg_get_last_page(tf->videosync, tf->to.serialno, &tf->videopage);
651 last_frame = (int64_t) (theora_granule_frame (&tf->td, ogg_page_granulepos(&tf->videopage)));
652 asset->video_length = last_frame - start_frame + 1;
653 // printf("FileOGG:: first frame: %lli, last frame: %lli, video length: %lli\n", start_frame, last_frame, asset->video_length);
656 // FIXME - LOW PRIORITY Cinelerra does not honor the frame_width and frame_height
657 asset->width = tf->ti.width;
658 asset->height = tf->ti.height;
659 // Don't want a user configured frame rate to get destroyed
660 if(!asset->frame_rate)
661 asset->frame_rate = fps;
662 // All theora material is noninterlaced by definition
663 if(!asset->interlace_mode)
664 asset->interlace_mode = BC_ILACE_MODE_NOTINTERLACED;
666 /* ogg_get_page_of_frame(tf->videosync, tf->to.serialno, &og, 0 +start_frame);
667 ogg_get_page_of_frame(tf->videosync, tf->to.serialno, &og, 1 +start_frame);
668 ogg_get_page_of_frame(tf->videosync, tf->to.serialno, &og, 5 +start_frame);
669 ogg_get_page_of_frame(tf->videosync, tf->to.serialno, &og, 206 +start_frame);
670 ogg_get_page_of_frame(tf->videosync, tf->to.serialno, &og, 207 +start_frame);
671 ogg_get_page_of_frame(tf->videosync, tf->to.serialno, &og, 208 +start_frame);
674 ogg_seek_to_keyframe(tf->videosync, tf->to.serialno, 0 + start_frame, &kf);
675 ogg_seek_to_keyframe(tf->videosync, tf->to.serialno, 1 + start_frame, &kf);
676 ogg_seek_to_keyframe(tf->videosync, tf->to.serialno, 5 + start_frame, &kf);
677 ogg_seek_to_keyframe(tf->videosync, tf->to.serialno, 66 + start_frame, &kf);
678 //printf("Keyframe: %lli\n", kf);
679 ogg_seek_to_keyframe(tf->videosync, tf->to.serialno, 1274 + start_frame, &kf);
682 set_video_position(0); // make sure seeking is done to the first sample
683 ogg_frame_position = -10;
684 asset->video_data = 1;
685 strncpy(asset->vcodec, "theo", 4);
688 // report_colorspace(&ti);
689 // dump_comments(&tc);
692 /* tear down the partial theora setup */
693 theora_info_clear(&tf->ti);
694 theora_comment_clear(&tf->tc);
698 vorbis_synthesis_init(&tf->vd, &tf->vi);
699 vorbis_block_init(&tf->vd, &tf->vb);
700 /* fprintf(stderr,"FileOGG: Ogg logical stream %x is Vorbis %d channel %d Hz audio.\n",
701 (unsigned int)tf->vo.serialno, tf->vi.channels, (int)tf->vi.rate);
703 /* init audio_sync structure */
704 tf->audiosync = new sync_window_t;
705 ogg_sync_init(&tf->audiosync->sync);
706 tf->audiosync->wlen = 0;
708 int ret2 = ogg_get_first_page(tf->audiosync, tf->vo.serialno, &tf->audiopage);
711 ogg_stream_reset(&tf->vo);
712 // FIXME - LOW PRIORITY should be getting pages until one has granulepos, probably never happens in pracitce
713 ogg_stream_pagein(&tf->vo, &tf->audiopage);
714 ogg_int64_t accumulated = 0;
716 while((result = ogg_stream_packetout(&tf->vo, &op)))
720 long thisblock = vorbis_packet_blocksize(&tf->vi, &op);
722 accumulated += (lastblock + thisblock) >> 2;
723 lastblock = thisblock;
726 start_sample = ogg_page_granulepos(&tf->audiopage) - accumulated;
728 printf("Begin: %lli, To byte: %lli, granule: %lli, serialno: %x\n",
729 tf->audiosync->file_pagepos_found,
730 tf->audiosync->file_pagepos_found + tf->audiopage.body_len + tf->audiopage.header_len,
731 ogg_page_granulepos(&tf->audiopage),
732 ogg_page_serialno(&tf->audiopage));
733 while (ogg_get_next_page(tf->audiosync, tf->vo.serialno, &tf->audiopage))
734 printf("At byte: %lli, To byte: %lli, granule: %lli, serialno: %x\n",
735 tf->audiosync->file_pagepos_found,
736 tf->audiosync->file_pagepos_found + tf->audiopage.body_len + tf->audiopage.header_len,
737 ogg_page_granulepos(&tf->audiopage),
738 ogg_page_serialno(&tf->audiopage));
741 int ret = ogg_get_last_page(tf->audiosync, tf->vo.serialno, &tf->audiopage);
742 last_sample = ogg_page_granulepos(&tf->audiopage);
743 asset->audio_length = last_sample - start_sample;
745 /* printf("FileOGG:: First sample: %lli, last_sample: %lli\n", start_sample, last_sample);
746 printf("FileOGG:: audio length: samples: %lli, playing time: %f\n", asset->audio_length, 1.0 * asset->audio_length / tf->vi.rate);
748 /* printf("End: %lli, To byte: %lli, granule: %lli, serialno: %x\n",
749 tf->audiosync->file_pagepos_found,
750 tf->audiosync->file_pagepos_found + tf->audiopage.body_len + tf->audiopage.header_len,
751 ogg_page_granulepos(&tf->audiopage),
752 ogg_page_serialno(&tf->audiopage));
753 while (ogg_get_prev_page(tf->audiosync, tf->vo.serialno, &tf->audiopage))
754 printf("At byte: %lli, To byte: %lli, granule: %lli, serialno: %x\n",
755 tf->audiosync->file_pagepos_found,
756 tf->audiosync->file_pagepos_found + tf->audiopage.body_len + tf->audiopage.header_len,
757 ogg_page_granulepos(&tf->audiopage),
758 ogg_page_serialno(&tf->audiopage));
761 /* ogg_get_page_of_sample(tf->audiosync, tf->vo.serialno, &tf->audiopage, 0);
762 ogg_get_page_of_sample(tf->audiosync, tf->vo.serialno, &tf->audiopage, 1);
763 ogg_get_page_of_sample(tf->audiosync, tf->vo.serialno, &tf->audiopage, 50);
764 ogg_get_page_of_sample(tf->audiosync, tf->vo.serialno, &tf->audiopage, 5000);
765 ogg_get_page_of_sample(tf->audiosync, tf->vo.serialno, &tf->audiopage, 30000);
766 ogg_get_page_of_sample(tf->audiosync, tf->vo.serialno, &tf->audiopage, 50000);
767 ogg_get_page_of_sample(tf->audiosync, tf->vo.serialno, &tf->audiopage, 90000);
768 ogg_get_page_of_sample(tf->audiosync, tf->vo.serialno, &tf->audiopage, 95999);
769 ogg_get_page_of_sample(tf->audiosync, tf->vo.serialno, &tf->audiopage, 96000);
770 ogg_seek_to_sample(tf->audiosync, tf->vo.serialno, 0);
771 ogg_seek_to_sample(tf->audiosync, tf->vo.serialno, 1);
772 ogg_seek_to_sample(tf->audiosync, tf->vo.serialno, 5000);
773 ogg_seek_to_sample(tf->audiosync, tf->vo.serialno, 30000);
774 ogg_seek_to_sample(tf->audiosync, tf->vo.serialno, 50000);
775 ogg_seek_to_sample(tf->audiosync, tf->vo.serialno, 90000);
776 ogg_seek_to_sample(tf->audiosync, tf->vo.serialno, 95999);
777 ogg_seek_to_sample(tf->audiosync, tf->vo.serialno, 96000);
779 asset->channels = tf->vi.channels;
780 if(!asset->sample_rate)
781 asset->sample_rate = tf->vi.rate;
782 asset->audio_data = 1;
785 ogg_sample_position = -10;
786 set_audio_position(0); // make sure seeking is done to the first sample
787 strncpy(asset->acodec, "vorb", 4);
792 /* tear down the partial vorbis setup */
793 vorbis_info_clear(&tf->vi);
794 vorbis_comment_clear(&tf->vc);
796 ogg_sync_clear(&oy.sync);
801 int FileOGG::ogg_get_prev_page(sync_window_t *sw, long serialno, ogg_page *og)
805 off_t filepos = sw->file_pagepos_found - READ_SIZE;
806 int first_page_offset = 0;
808 int read_len = READ_SIZE;
810 // printf("fp: %lli pagepos found: %lli\n", filepos, sw->file_pagepos_found);
815 // read_len = read_len - (filedata_begin - filepos);
816 read_len = read_len + filepos;
821 int have_read = read_buffer_at(stream, sw, read_len, filepos);
823 // 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);
824 // printf("Buffer position: %lli\n", sw->file_bufpos);
825 // printf("SS: storage: %i, fill: %i, returned: %i\n", sw->sync.storage, sw->sync.fill, sw->sync.returned);
826 // printf("US: unsynced%i, headrebytes: %i, bodybyes: %i\n", sw->sync.unsynced, sw->sync.headerbytes, sw->sync.bodybytes);
827 // printf("data: %c %c %c %c\n", sw->sync.data[0], sw->sync.data[1], sw->sync.data[2], sw->sync.data[3]);
831 // read all pages in the buffer
835 while (first_page || page_length)
837 // if negative, skip bytes
838 while ((page_length = sync_and_take_page_out(sw, &page)) < 0)
840 page_offset -= page_length;
843 // printf("BBBb page_len: %i\n", page_length);
845 // if (filepos == 0 && page_length)
847 // printf("AAAAAAAAAAAAAAAAAAAAAAAAAaaa\n");
848 // printf("pp: %lli %x\n", sw->file_pagepos, ogg_page_serialno(&page));
851 first_page_offset = page_offset;
853 // printf("pl: %i, serial: %x iscem: %x\n", page_length, ogg_page_serialno(&page), serialno);
854 if (page_length && ogg_page_serialno(&page) == serialno)
856 // we will copy every page until last page in this buffer
859 sw->file_pagepos_found = sw->file_pagepos - page.header_len - page.body_len;
860 // printf("got it : %lli %i %i\n", sw->file_pagepos, page.header_len, page.body_len);
861 memcpy(og, &page, sizeof(page));
864 off_t old_filepos = filepos;
865 // printf("fpo: %i\n", first_page_offset);
866 filepos = filepos + first_page_offset - READ_SIZE;
869 // printf("finished\n");
876 int FileOGG::ogg_get_last_page(sync_window_t *sw, long serialno, ogg_page *og)
880 off_t filepos = file_length - READ_SIZE;
884 int first_page_offset = 0;
886 while (!done && filepos >= 0)
889 readlen = read_buffer_at(stream, sw, READ_SIZE, filepos);
891 // read all pages in the buffer
895 while (first_page || page_length)
897 // if negative, skip bytes
898 while ((page_length = sync_and_take_page_out(sw, &page)) < 0)
899 page_offset -= page_length;
901 first_page_offset = page_offset;
903 if (page_length && ogg_page_serialno(&page) == serialno)
905 // we will copy every page until last page in this buffer
907 sw->file_pagepos_found = sw->file_pagepos - page.header_len - page.body_len;
908 memcpy(og, &page, sizeof(page));
911 filepos = filepos + first_page_offset - READ_SIZE;
920 int FileOGG::ogg_get_first_page(sync_window_t *sw, long serialno, ogg_page *og)
922 // printf("FileOGG:: Seeking to first page at %lli\n", filedata_begin);
923 read_buffer_at(stream, sw, READ_SIZE, 0);
924 // we don't even need to sync since we _know_ it is right
925 return (ogg_get_next_page(sw, serialno, og));
928 int FileOGG::ogg_seek_to_databegin(sync_window_t *sw, long serialno)
931 // printf("FileOGG:: Seeking to first page at %lli\n", filedata_begin);
932 read_buffer_at(stream, sw, READ_SIZE, filedata_begin);
933 // we don't even need to sync since we _know_ it is right
937 int FileOGG::ogg_get_next_page(sync_window_t *sw, long serialno, ogg_page *og)
939 while (take_page_out_autoadvance(stream, sw, og) > 0)
941 if (ogg_page_serialno(og) == serialno)
943 sw->file_pagepos_found = sw->file_pagepos - og->header_len - og->body_len;
950 int FileOGG::ogg_sync_and_get_next_page(sync_window_t *sw, long serialno, ogg_page *og)
952 // TODO: Put better error reporting inhere
954 while ((ret = sync_and_take_page_out(sw, og)) < 0)
960 if (ogg_page_serialno(og) == serialno)
962 sw->file_pagepos_found = sw->file_pagepos - og->header_len - og->body_len;
965 while (ogg_get_next_page(sw, serialno, og))
966 if (ogg_page_serialno(og) == serialno)
968 sw->file_pagepos_found = sw->file_pagepos - og->header_len - og->body_len;
975 // >= 0, number of sample within a page
977 int FileOGG::ogg_get_page_of_sample(sync_window_t *sw, long serialno, ogg_page *og, int64_t sample)
979 // First make an educated guess about position
980 if (sample >= asset->audio_length + start_sample)
982 printf("FileOGG: Illegal seek beyond end of samples\n");
985 off_t educated_guess = filedata_begin + (file_length - filedata_begin) * (sample - start_sample) / asset->audio_length - READ_SIZE;
986 if (educated_guess < 0)
988 // printf("My educated guess: %lli\n", educated_guess);
990 read_buffer_at(stream, sw, READ_SIZE, educated_guess);
991 ogg_sync_and_get_next_page(sw, serialno, og);
992 int64_t end_sample = ogg_page_granulepos(og);
993 // linear seek to the sample
994 int64_t start_sample = 0;
995 // TODO: Use bisection also
996 // printf("Next page granulepos: %lli, pagepos: %lli\n", end_sample, sw->file_pagepos_found);
997 if (end_sample <= sample)
1000 while (end_sample <= sample)
1002 ogg_get_next_page(sw, serialno, og);
1003 start_sample = end_sample;
1004 end_sample = ogg_page_granulepos(og);
1006 ogg_get_prev_page(sw, serialno, og);
1007 while (ogg_page_continued(og) && ogg_page_packets(og) == 1)
1008 ogg_get_prev_page(sw, serialno, og);
1012 start_sample = end_sample;
1013 while (start_sample > sample || (ogg_page_continued(og) && ogg_page_packets(og) == 1))
1015 // printf("get prev page: %lli pagepos:%lli\n", ogg_page_granulepos(og), sw->file_pagepos_found);
1016 ogg_get_prev_page(sw, serialno, og);
1017 end_sample = start_sample;
1018 start_sample = ogg_page_granulepos(og);
1020 // go forward one page at the end
1024 // printf("For sample %lli we need to start decoding on page with granulepos: %lli\n", sample, ogg_page_granulepos(og));
1028 // seeks, so next sample returned will be the correct one
1029 // sample here is still the vorbis sample number (= cinelerra sample number + start_sample)
1030 // reinits the decoding engine
1032 int FileOGG::ogg_seek_to_sample(sync_window_t *sw, long serialno, int64_t sample)
1034 // MAYBE FIXME - find out if we really are decoding previous two packets or not
1035 // get to the sample
1038 // printf("Calling get page of sample\n");
1039 if (!ogg_get_page_of_sample(sw, serialno, &og, sample))
1041 printf("FileOGG: Seeking to sample's page failed\n");
1044 // printf("Pagepos: %lli\n", sw->file_pagepos);
1045 vorbis_synthesis_restart(&tf->vd);
1046 ogg_stream_reset(&tf->vo);
1047 ogg_stream_pagein(&tf->vo, &og);
1049 // printf("seeking to sample : %lli , starting at page with gpos: %lli\n", sample, ogg_page_granulepos(&og));
1051 int64_t current_comming_sample = -1;
1055 // make sure we have a packet ready
1056 while (ogg_stream_packetpeek(&tf->vo, NULL) != 1)
1058 if (!ogg_get_next_page(sw, serialno, &og))
1060 printf("FileOGG: Cannot find next page while seeking\n");
1063 ogg_stream_pagein(&tf->vo, &og);
1065 ogg_stream_packetout(&tf->vo, &op);
1069 if(!vorbis_synthesis(&tf->vb, &op))
1071 int ret= vorbis_synthesis_blockin(&tf->vd, &tf->vb);
1072 int64_t previous_comming_sample = current_comming_sample;
1073 current_comming_sample += vorbis_synthesis_pcmout(&tf->vd, NULL);
1074 if (current_comming_sample > sample)
1076 if (previous_comming_sample > sample)
1077 printf("Ogg decoding error while seeking sample\n");
1078 vorbis_synthesis_read(&tf->vd, (sample - previous_comming_sample));
1079 // printf("WE GOT IT, samples already decoded: %li\n", vorbis_synthesis_pcmout(&tf->vd,NULL));
1080 return 1; // YAY next sample read is going to be ours, sexy!
1083 // discard decoded data before current sample
1084 vorbis_synthesis_read(&tf->vd, (current_comming_sample - previous_comming_sample));
1089 if (!sync && op.granulepos >= 0)
1092 current_comming_sample = op.granulepos;
1093 if(!vorbis_synthesis(&tf->vb, &op))
1095 vorbis_synthesis_blockin(&tf->vd, &tf->vb);
1096 if (vorbis_synthesis_pcmout(&tf->vd, NULL) != 0)
1098 printf("FileOGG: Something wrong while trying to seek\n");
1111 int FileOGG::ogg_get_page_of_frame(sync_window_t *sw, long serialno, ogg_page *og, int64_t frame)
1113 if (frame >= asset->video_length + start_frame)
1115 printf("FileOGG: Illegal seek beyond end of frames\n");
1118 // printf("frame: %lli start frame: %lli\n", frame, start_frame);
1119 // printf("file_length: %lli filedata_begin: %lli\n", file_length, filedata_begin);
1120 off_t educated_guess = filedata_begin + (file_length - filedata_begin) * (frame - start_frame) / asset->video_length - READ_SIZE/2;
1121 // educated_guess += 100000;
1122 if (educated_guess > file_length - READ_SIZE)
1123 educated_guess = file_length - READ_SIZE;
1124 if (educated_guess < filedata_begin)
1125 educated_guess = filedata_begin;
1126 // printf("My educated guess: %lli\n", educated_guess);
1127 // now see if we won
1128 read_buffer_at(stream, sw, READ_SIZE, educated_guess);
1129 ogg_sync_and_get_next_page(sw, serialno, og);
1130 int64_t pageend_frame;
1132 // find the page with "real" ending
1133 while ((pageend_frame = ogg_page_granulepos(og)) == -1)
1135 if (ogg_get_next_page(sw, serialno, og) == 0)
1141 pageend_frame = theora_granule_frame(&tf->td, ogg_page_granulepos(og));
1143 // FIXME - MEDIUM PRIORITY: read back if we've gone too far and no page of our serialno at all can be found
1146 // linear seek to the sample
1147 int64_t start_frame = 0;
1148 // TODO: Use bisection also
1149 // printf("Next page granulepos: %lli, pagepos: %lli\n", end_sample, sw->file_pagepos_found);
1150 int discard_packets = 0;
1153 if (pageend_frame <= frame)
1156 while (pageend_frame < frame)
1159 ogg_get_next_page(sw, serialno, og);
1160 } while (ogg_page_packets(og) == 0);
1161 pageend_frame = theora_granule_frame(&tf->td, ogg_page_granulepos(og));
1164 // go back if this frame starts on previous page
1165 if (ogg_page_continued(og) && pageend_frame - ogg_page_packets(og) == frame - 1)
1168 ogg_get_prev_page(sw, serialno, og);
1169 } while (ogg_page_packets(og) == 0 && ogg_page_continued(og));
1171 pageend_frame = theora_granule_frame(&tf->td, ogg_page_granulepos(og));
1175 int64_t first_frame_on_page = theora_granule_frame(&tf->td, ogg_page_granulepos(og)) - ogg_page_packets(og) + 2;
1176 if (!ogg_page_continued(og))
1177 first_frame_on_page--;
1178 while (first_frame_on_page > frame)
1180 // printf("get prev page: %lli pagepos:%lli\n", ogg_page_granulepos(og), sw->file_pagepos_found);
1182 ogg_get_prev_page(sw, serialno, og);
1183 } while (ogg_page_packets(og) == 0 && ogg_page_continued(og));
1185 // pageend_frame = theora_granule_frame(&tf->td, ogg_page_granulepos(og));
1186 first_frame_on_page = theora_granule_frame(&tf->td, ogg_page_granulepos(og)) - ogg_page_packets(og) + 2;
1187 if (!ogg_page_continued(og))
1188 first_frame_on_page--;
1191 // printf("Miss plus: %i, miss minus: %i\n", missp, missm);
1192 // printf("last frame of page with frame : %lli\n", pageend_frame);
1197 int FileOGG::ogg_seek_to_keyframe(sync_window_t *sw, long serialno, int64_t frame, int64_t *keyframe_number)
1201 // printf("Searching for the proper position to start decoding frame %lli\n", frame);
1202 if (!ogg_get_page_of_frame(sw, serialno, &og, frame))
1204 printf("FileOGG: Seeking to frame failed\n");
1207 // TODO: if the frame we are looking for continoues on the next page, we don't need to do this
1208 // Now go to previous page in order to find out the granulepos
1209 // Don't do it in case this is the first page.
1210 // printf("GP: %lli\n", ogg_page_granulepos(&og));
1211 int64_t granulepos, iframe, pframe;
1212 granulepos = ogg_page_granulepos(&og);
1213 iframe = granulepos >> theora_keyframe_granule_shift;
1214 pframe = granulepos - (iframe << theora_keyframe_granule_shift);
1215 // check if maybe iframe is known from this page already
1216 if (granulepos != -1 && iframe <= frame)
1218 // optimisation, iframe is already known from this page
1221 // get previous page so we will get the iframe number
1223 ogg_get_prev_page(sw, serialno, &og);
1224 } while (ogg_page_packets(&og) == 0);
1226 granulepos = ogg_page_granulepos(&og);
1227 iframe = granulepos >> theora_keyframe_granule_shift;
1228 pframe = granulepos - (iframe << theora_keyframe_granule_shift);
1230 int64_t first_frame_on_page = theora_granule_frame(&tf->td, ogg_page_granulepos(&og)) - ogg_page_packets(&og) + 2;
1231 if (!ogg_page_continued(&og))
1232 first_frame_on_page--;
1233 if (first_frame_on_page <= iframe)
1235 // optimisation, happens mainly in low-bitrate streams, it spares us one seek
1238 // get the page where keyframe starts
1239 if (!ogg_get_page_of_frame(sw, serialno, &og, iframe))
1241 printf("FileOGG: Seeking to keyframe failed\n");
1245 // printf("looking for frame: %lli, last frame of the page: %lli, last keyframe: %lli\n", frame, pframe+iframe, iframe);
1246 ogg_stream_reset(&tf->to);
1247 ogg_stream_pagein(&tf->to, &og);
1248 // Read until one frame before keyframe
1249 // printf("c: %i\n", ogg_page_continued(&og));
1250 int numread = iframe - (theora_granule_frame(&tf->td, ogg_page_granulepos(&og)) - ogg_page_packets(&og)) - 1;
1251 if (ogg_page_continued(&og))
1253 // printf("numread: %i\n", numread);
1254 // printf("FileOGG:: Proper position: %lli\n", theora_granule_frame(&tf->td, ogg_page_granulepos(&og)) + numread - ogg_page_packets(&og));
1257 while (ogg_stream_packetpeek(&tf->to, NULL) != 1)
1259 if (!ogg_get_next_page(sw, serialno, &og))
1261 printf("FileOGG: Cannot find next page while seeking\n");
1264 ogg_stream_pagein(&tf->to, &og);
1266 ogg_stream_packetout(&tf->to, &op);
1269 *keyframe_number = iframe;
1274 int FileOGG::check_sig(Asset *asset)
1276 FILE *fd = fopen(asset->path, "rb");
1278 fseek(fd, 0, SEEK_SET);
1280 fread(data, 4, 1, fd);
1281 if(data[0] == 'O' &&
1287 // printf("Yay, we have an ogg file\n");
1295 int FileOGG::close_file()
1302 if (asset->audio_data)
1303 write_samples_vorbis(0, 0, 1); // set eos
1304 if (asset->video_data)
1305 write_frames_theora(0, 1, 1); // set eos
1307 flush_ogg(1); // flush all
1309 if (asset->audio_data)
1311 vorbis_block_clear (&tf->vb);
1312 vorbis_dsp_clear (&tf->vd);
1313 vorbis_info_clear (&tf->vi);
1314 ogg_stream_clear (&tf->vo);
1316 if (asset->video_data)
1318 theora_info_clear (&tf->ti);
1319 ogg_stream_clear (&tf->to);
1320 theora_clear (&tf->td);
1323 if (stream) fclose(stream);
1327 if (asset->audio_data)
1329 vorbis_block_clear (&tf->vb);
1330 vorbis_dsp_clear (&tf->vd);
1331 vorbis_comment_clear (&tf->vc);
1332 vorbis_info_clear (&tf->vi);
1333 ogg_stream_clear (&tf->vo);
1335 theora_comment_clear(&tf->tc);
1336 if (asset->video_data)
1338 theora_info_clear (&tf->ti);
1339 theora_comment_clear (&tf->tc);
1340 theora_clear (&tf->td);
1341 ogg_stream_clear (&tf->to);
1345 if (stream) fclose(stream);
1351 int FileOGG::close_file_derived()
1353 //printf("FileOGG::close_file_derived(): 1\n");
1354 if (stream) fclose(stream);
1358 int64_t FileOGG::get_video_position()
1361 return next_frame_position - start_frame;
1364 int64_t FileOGG::get_audio_position()
1366 return next_sample_position - start_sample;
1369 int FileOGG::set_video_position(int64_t x)
1372 // printf("SVP: %lli\n", x);
1374 next_frame_position = x + start_frame;
1379 int FileOGG::colormodel_supported(int colormodel)
1383 if (colormodel == BC_YUV420P)
1388 int FileOGG::get_best_colormodel(Asset *asset, int driver)
1395 int FileOGG::read_frame(VFrame *frame)
1398 if(!stream) return 1;
1401 // skip is cheaper than seek, do it...
1402 int decode_frames = 0;
1403 int expect_keyframe = 0;
1404 if (ogg_frame_position >= 0 &&
1405 next_frame_position >= ogg_frame_position &&
1406 next_frame_position - ogg_frame_position < 32)
1408 decode_frames = next_frame_position - ogg_frame_position;
1410 if (next_frame_position != ogg_frame_position)
1412 if (!ogg_seek_to_keyframe(tf->videosync, tf->to.serialno, next_frame_position, &ogg_frame_position))
1414 printf("FileOGG:: Error while seeking to frame's keyframe (frame: %lli, keyframe: %lli)\n", next_frame_position, ogg_frame_position);
1417 // printf("For frame: %lli, keyframe is: %lli\n", next_frame_position,ogg_frame_position);
1418 // skip frames must be > 0 here
1419 decode_frames = next_frame_position - ogg_frame_position + 1;
1420 ogg_frame_position --; // ogg_frame_position is at last decoded frame, so it will point right
1421 if (decode_frames <= 0)
1423 printf("FileOGG:: Error while seeking to keyframe, wrong keyframe number (frame: %lli, keyframe: %lli)\n", next_frame_position, ogg_frame_position);
1427 expect_keyframe = 1;
1430 // printf("Frames to decode: %i\n", decode_frames);
1432 // THIS IS WHAT CAUSES SLOWNESS OF SEEKING, but we can do nothing about it.
1433 while (decode_frames > 0)
1437 while (ogg_stream_packetpeek(&tf->to, NULL) != 1)
1439 if (!ogg_get_next_page(tf->videosync, tf->to.serialno, &og))
1441 printf("FileOGG: Cannot find next page while seeking\n");
1444 ogg_stream_pagein(&tf->to, &og);
1446 ogg_stream_packetout(&tf->to, &op);
1447 if (expect_keyframe && !theora_packet_iskeyframe(&op))
1449 printf("FileOGG: Expecting keyframe, but didn't get it\n");
1450 // return 1; this is generally not a fatal error
1452 expect_keyframe = 0;
1455 theora_decode_packetin(&tf->td, &op);
1458 ogg_frame_position ++;
1462 int ret = theora_decode_YUVout (&tf->td, &yuv);
1465 printf("FileOGG: theora_decode_YUVout failed with code %i\n", ret);
1469 /* yuv.y += yuv.y_stride * (yuv.y_height - 1);
1470 yuv.u += yuv.uv_stride * (yuv.uv_height - 1);
1471 yuv.v += yuv.uv_stride * (yuv.uv_height - 1);
1472 yuv.y_stride = - yuv.y_stride;
1473 yuv.uv_stride = - yuv.uv_stride;*/
1474 VFrame *temp_frame = new VFrame(yuv.y,
1482 // copy into temp frame...
1484 cmodel_transfer(frame->get_rows(),
1485 temp_frame->get_rows(),
1489 temp_frame->get_y(),
1490 temp_frame->get_u(),
1491 temp_frame->get_v(),
1498 yuv.y_width, // temp_frame can be larger than frame if width not dividable by 16
1501 frame->get_color_model(),
1503 -temp_frame->get_w(),
1508 next_frame_position ++;
1515 int FileOGG::ogg_decode_more_samples(sync_window_t *sw, long serialno)
1522 while (ogg_stream_packetpeek(&tf->vo, NULL) != 1)
1524 if (!ogg_get_next_page(sw, serialno, &og))
1526 printf("FileOGG: Cannot find next page while trying to decode more samples\n");
1529 ogg_stream_pagein(&tf->vo, &og);
1531 ogg_stream_packetout(&tf->vo, &op);
1532 if(!vorbis_synthesis(&tf->vb, &op))
1535 vorbis_synthesis_blockin(&tf->vd, &tf->vb);
1541 int FileOGG::set_audio_position(int64_t x)
1543 next_sample_position = x + start_sample;
1547 int FileOGG::move_history(int from, int to, int len)
1549 for(int i = 0; i < asset->channels; i++)
1550 memmove(pcm_history[i] + to, pcm_history[i] + from, sizeof(float) * len);
1551 history_start = history_start + from - to;
1555 int FileOGG::read_samples(double *buffer, int64_t len)
1557 float **vorbis_buffer;
1560 // printf("Reading samples: Channel: %i, number of samples: %lli, reading at :%lli\n", file->current_channel, len, next_sample_position);
1561 // printf("\tnext_sample_position: %lli, length: %i\n", next_sample_position, len);
1562 // printf("\thistory_start: %lli, length: %i\n", history_start, history_size);
1564 if(len > HISTORY_MAX)
1566 printf("FileOGG::read_samples max samples=%d\n", HISTORY_MAX);
1572 pcm_history = new float*[asset->channels];
1573 for(int i = 0; i < asset->channels; i++)
1574 pcm_history[i] = new float[HISTORY_MAX];
1575 history_start = -100000000; // insane value to trigger reload
1579 int64_t hole_start = -1;
1580 int64_t hole_len = -1;
1581 int64_t hole_absstart = -1;
1582 int64_t hole_fill = 0;
1584 if (history_start < next_sample_position && history_start + history_size > next_sample_position && history_start + history_size < next_sample_position + len)
1588 hole_start = history_start + history_size - next_sample_position;
1589 hole_len = history_size - hole_start;
1590 hole_absstart = next_sample_position + hole_start;
1591 move_history(next_sample_position - history_start,
1596 if (next_sample_position < history_start && history_start < next_sample_position + len)
1601 hole_len = history_start - next_sample_position;
1602 hole_absstart = next_sample_position;
1603 // printf("hs: %lli, histstart: %lli, next_sample_position: %lli\n", history_size, history_start, next_sample_position);
1604 // printf("to: 0, from: %lli, size: %lli\n",
1605 // history_start - next_sample_position,
1606 // history_size - history_start + next_sample_position);
1608 history_start - next_sample_position,
1609 history_size - history_start + next_sample_position);
1612 if (next_sample_position >= history_start + history_size || next_sample_position + len <= history_start)
1617 hole_len = HISTORY_MAX;
1618 hole_absstart = next_sample_position;
1619 history_start = hole_absstart;
1620 history_size = hole_len;
1625 if (hole_start < 0 || hole_len <= 0 || hole_absstart < 0)
1627 printf("FileOGG: Error at finding out what to read from file\n");
1631 if (hole_absstart + hole_len > asset->audio_length + start_sample)
1633 hole_len = asset->audio_length + start_sample - hole_absstart;
1634 history_size = asset->audio_length + start_sample - history_start;
1637 history_size = HISTORY_MAX;
1641 // printf("Decode samples at position: %lli, samples to read: %lli\n", hole_absstart, hole_len);
1643 int64_t samples_read = 0;
1644 if (ogg_sample_position != hole_absstart)
1646 ogg_sample_position = hole_absstart;
1647 if (!ogg_seek_to_sample(tf->audiosync, tf->vo.serialno, ogg_sample_position))
1649 printf("FileOGG:: Error while seeking to sample\n");
1653 // now we have ogg_sample_positon aligned
1654 int64_t samples_to_read = hole_len;
1655 while (samples_read < hole_len)
1657 int64_t waiting_samples = vorbis_synthesis_pcmout(&tf->vd, &vorbis_buffer);
1658 int64_t takeout_samples;
1659 if (waiting_samples > samples_to_read - samples_read)
1660 takeout_samples = samples_to_read - samples_read;
1662 takeout_samples = waiting_samples;
1665 // printf("takeout samples: %lli, samples_read: %lli\n", takeout_samples, samples_read);
1666 for(int i = 0; i < asset->channels; i++)
1668 float *input = vorbis_buffer[i];
1669 float *output = pcm_history[i] + hole_start;
1671 for(int j = 0; j < takeout_samples ; j++)
1673 output[j] = input[j];
1677 vorbis_synthesis_read(&tf->vd, takeout_samples);
1678 samples_read += takeout_samples;
1679 ogg_sample_position += takeout_samples;
1680 hole_start += takeout_samples;
1682 if (samples_read < hole_len)
1683 if (!ogg_decode_more_samples(tf->audiosync, tf->vo.serialno))
1685 ogg_sample_position = -1;
1693 // now we can be sure our history is correct, just copy it out
1694 if (next_sample_position < history_start || next_sample_position + len > history_start + history_size)
1696 printf("FileOGG:: History not aligned properly \n");
1697 printf("\tnext_sample_position: %lli, length: %i\n", next_sample_position, len);
1698 printf("\thistory_start: %lli, length: %i\n", history_start, history_size);
1702 float *input = pcm_history[file->current_channel] + next_sample_position - history_start;
1703 for (int i = 0; i < len; i++)
1704 buffer[i] = input[i];
1706 next_sample_position += len;
1711 int FileOGG::write_audio_page()
1715 ret = fwrite(tf->apage, 1, tf->apage_len, stream);
1716 if(ret < tf->apage_len) {
1717 fprintf(stderr,"error writing audio page\n");
1719 tf->apage_valid = 0;
1720 tf->a_pkg -= ogg_page_packets((ogg_page *)&tf->apage);
1724 int FileOGG::write_video_page()
1728 ret = fwrite(tf->vpage, 1, tf->vpage_len, stream);
1729 if(ret < tf->vpage_len) {
1730 fprintf(stderr,"error writing video page\n");
1732 tf->vpage_valid = 0;
1733 tf->v_pkg -= ogg_page_packets((ogg_page *)&tf->vpage);
1737 void FileOGG::flush_ogg (int e_o_s)
1743 /* flush out the ogg pages */
1745 /* Get pages for both streams, if not already present, and if available.*/
1746 if(asset->video_data && !tf->vpage_valid) {
1747 // this way seeking is much better,
1748 // not sure if 23 packets is a good value. it works though
1750 if(tf->v_pkg>22 && ogg_stream_flush(&tf->to, &og) > 0) {
1753 else if(ogg_stream_pageout(&tf->to, &og) > 0) {
1757 len = og.header_len + og.body_len;
1758 if(tf->vpage_buffer_length < len) {
1759 tf->vpage = (unsigned char *)realloc(tf->vpage, len);
1760 tf->vpage_buffer_length = len;
1762 tf->vpage_len = len;
1763 memcpy(tf->vpage, og.header, og.header_len);
1764 memcpy(tf->vpage+og.header_len , og.body, og.body_len);
1766 tf->vpage_valid = 1;
1767 tf->videotime = theora_granule_time (&tf->td,
1768 ogg_page_granulepos(&og));
1771 if(asset->audio_data && !tf->apage_valid) {
1772 // this way seeking is much better,
1773 // not sure if 23 packets is a good value. it works though
1775 if(tf->a_pkg>22 && ogg_stream_flush(&tf->vo, &og) > 0) {
1778 else if(ogg_stream_pageout(&tf->vo, &og) > 0) {
1782 len = og.header_len + og.body_len;
1783 if(tf->apage_buffer_length < len) {
1784 tf->apage = (unsigned char *)realloc(tf->apage, len);
1785 tf->apage_buffer_length = len;
1787 tf->apage_len = len;
1788 memcpy(tf->apage, og.header, og.header_len);
1789 memcpy(tf->apage+og.header_len , og.body, og.body_len);
1791 tf->apage_valid = 1;
1792 tf->audiotime= vorbis_granule_time (&tf->vd,
1793 ogg_page_granulepos(&og));
1797 if(!asset->audio_data && tf->vpage_valid) {
1800 else if(!asset->video_data && tf->apage_valid) {
1803 /* We're using both. We can output only:
1804 * a) If we have valid pages for both
1805 * b) At EOS, for the remaining stream.
1807 else if(tf->vpage_valid && tf->apage_valid) {
1808 /* Make sure they're in the right order. */
1809 if(tf->videotime <= tf->audiotime)
1814 else if(e_o_s && tf->vpage_valid) {
1817 else if(e_o_s && tf->apage_valid) {
1821 break; /* Nothing more writable at the moment */
1824 flush_lock->unlock();
1828 int FileOGG::write_samples_vorbis(double **buffer, int64_t len, int e_o_s)
1831 float **vorbis_buffer;
1832 static int samples = 0;
1836 vorbis_analysis_wrote (&tf->vd, 0);
1839 vorbis_buffer = vorbis_analysis_buffer (&tf->vd, len);
1840 /* double to float conversion */
1841 for(i = 0; i<asset->channels; i++)
1843 for (j = 0; j < len; j++)
1845 vorbis_buffer[i][j] = buffer[i][j];
1848 vorbis_analysis_wrote (&tf->vd, len);
1850 while(vorbis_analysis_blockout (&tf->vd, &tf->vb) == 1)
1852 /* analysis, assume we want to use bitrate management */
1853 vorbis_analysis (&tf->vb, NULL);
1854 vorbis_bitrate_addblock (&tf->vb);
1856 /* weld packets into the bitstream */
1857 while (vorbis_bitrate_flushpacket (&tf->vd, &tf->op))
1860 ogg_stream_packetin (&tf->vo, &tf->op);
1862 flush_lock->unlock();
1872 int FileOGG::write_samples(double **buffer, int64_t len)
1875 return write_samples_vorbis(buffer, len, 0);
1879 int FileOGG::write_frames_theora(VFrame ***frames, int len, int e_o_s)
1881 // due to clumsy theora's design we need to delay writing out by one frame
1882 // always stay one frame behind, so we can correctly encode e_o_s
1884 int i, j, result = 0;
1886 if(!stream) return 0;
1889 for(j = 0; j < len && !result; j++)
1891 if (temp_frame) // encode previous frame if available
1894 yuv.y_width = tf->ti.width;
1895 yuv.y_height = tf->ti.height;
1896 yuv.y_stride = temp_frame->get_bytes_per_line();
1898 yuv.uv_width = tf->ti.width / 2;
1899 yuv.uv_height = tf->ti.height / 2;
1900 yuv.uv_stride = temp_frame->get_bytes_per_line() /2;
1902 yuv.y = temp_frame->get_y();
1903 yuv.u = temp_frame->get_u();
1904 yuv.v = temp_frame->get_v();
1905 int ret = theora_encode_YUVin (&tf->td, &yuv);
1908 printf("FileOGG: theora_encode_YUVin failed with code %i\n", ret);
1909 printf("yuv_buffer: y_width: %i, y_height: %i, y_stride: %i, uv_width: %i, uv_height: %i, uv_stride: %i\n",
1917 while(theora_encode_packetout (&tf->td, e_o_s, &tf->op)) {
1919 ogg_stream_packetin (&tf->to, &tf->op);
1921 flush_lock->unlock();
1923 flush_ogg(0); // eos flush is done later at close_file
1925 // If we have e_o_s, don't encode any new frames
1931 temp_frame = new VFrame (0,
1936 VFrame *frame = frames[0][j];
1937 int in_color_model = frame->get_color_model();
1938 if (in_color_model == BC_YUV422P &&
1939 temp_frame->get_w() == frame->get_w() &&
1940 temp_frame->get_h() == frame->get_h() &&
1941 temp_frame->get_bytes_per_line() == frame->get_bytes_per_line())
1943 temp_frame->copy_from(frame);
1947 cmodel_transfer(temp_frame->get_rows(),
1949 temp_frame->get_y(),
1950 temp_frame->get_u(),
1951 temp_frame->get_v(),
1961 frame->get_w(), // temp_frame can be larger than frame if width not dividable by 16
1963 frame->get_color_model(),
1967 temp_frame->get_w());
1976 int FileOGG::write_frames(VFrame ***frames, int len)
1979 return write_frames_theora(frames, len, 0);
1982 OGGConfigAudio::OGGConfigAudio(BC_WindowBase *parent_window, Asset *asset)
1983 : BC_Window(PROGRAM_NAME ": Audio Compression",
1984 parent_window->get_abs_cursor_x(1),
1985 parent_window->get_abs_cursor_y(1),
1989 this->parent_window = parent_window;
1990 this->asset = asset;
1993 OGGConfigAudio::~OGGConfigAudio()
1998 int OGGConfigAudio::create_objects()
2000 // add_tool(new BC_Title(10, 10, _("There are no audio options for this format")));
2004 char string[BCTEXTLEN];
2006 add_tool(fixed_bitrate = new OGGVorbisFixedBitrate(x, y, this));
2007 add_tool(variable_bitrate = new OGGVorbisVariableBitrate(x1, y, this));
2010 sprintf(string, "%d", asset->vorbis_min_bitrate);
2011 add_tool(new BC_Title(x, y, _("Min bitrate:")));
2012 add_tool(new OGGVorbisMinBitrate(x1, y, this, string));
2015 add_tool(new BC_Title(x, y, _("Avg bitrate:")));
2016 sprintf(string, "%d", asset->vorbis_bitrate);
2017 add_tool(new OGGVorbisAvgBitrate(x1, y, this, string));
2020 add_tool(new BC_Title(x, y, _("Max bitrate:")));
2021 sprintf(string, "%d", asset->vorbis_max_bitrate);
2022 add_tool(new OGGVorbisMaxBitrate(x1, y, this, string));
2025 add_subwindow(new BC_OKButton(this));
2034 int OGGConfigAudio::close_event()
2040 OGGVorbisFixedBitrate::OGGVorbisFixedBitrate(int x, int y, OGGConfigAudio *gui)
2041 : BC_Radial(x, y, !gui->asset->vorbis_vbr, _("Average bitrate"))
2045 int OGGVorbisFixedBitrate::handle_event()
2047 gui->asset->vorbis_vbr = 0;
2048 gui->variable_bitrate->update(0);
2052 OGGVorbisVariableBitrate::OGGVorbisVariableBitrate(int x, int y, OGGConfigAudio *gui)
2053 : BC_Radial(x, y, gui->asset->vorbis_vbr, _("Variable bitrate"))
2057 int OGGVorbisVariableBitrate::handle_event()
2059 gui->asset->vorbis_vbr = 1;
2060 gui->fixed_bitrate->update(0);
2065 OGGVorbisMinBitrate::OGGVorbisMinBitrate(int x,
2067 OGGConfigAudio *gui,
2069 : BC_TextBox(x, y, 180, 1, text)
2073 int OGGVorbisMinBitrate::handle_event()
2075 gui->asset->vorbis_min_bitrate = atol(get_text());
2081 OGGVorbisMaxBitrate::OGGVorbisMaxBitrate(int x,
2083 OGGConfigAudio *gui,
2085 : BC_TextBox(x, y, 180, 1, text)
2089 int OGGVorbisMaxBitrate::handle_event()
2091 gui->asset->vorbis_max_bitrate = atol(get_text());
2097 OGGVorbisAvgBitrate::OGGVorbisAvgBitrate(int x, int y, OGGConfigAudio *gui, char *text)
2098 : BC_TextBox(x, y, 180, 1, text)
2102 int OGGVorbisAvgBitrate::handle_event()
2104 gui->asset->vorbis_bitrate = atol(get_text());
2112 OGGConfigVideo::OGGConfigVideo(BC_WindowBase *parent_window, Asset *asset)
2113 : BC_Window(PROGRAM_NAME ": Video Compression",
2114 parent_window->get_abs_cursor_x(1),
2115 parent_window->get_abs_cursor_y(1),
2119 this->parent_window = parent_window;
2120 this->asset = asset;
2123 OGGConfigVideo::~OGGConfigVideo()
2128 int OGGConfigVideo::create_objects()
2130 // add_tool(new BC_Title(10, 10, _("There are no video options for this format")));
2135 add_subwindow(new BC_Title(x, y + 5, _("Bitrate:")));
2136 add_subwindow(new OGGTheoraBitrate(x1, y, this));
2137 add_subwindow(fixed_bitrate = new OGGTheoraFixedBitrate(x2, y, this));
2140 add_subwindow(new BC_Title(x, y, _("Quality:")));
2141 add_subwindow(new BC_ISlider(x + 80,
2148 asset->theora_quality,
2151 &asset->theora_quality));
2154 add_subwindow(fixed_quality = new OGGTheoraFixedQuality(x2, y, this));
2157 add_subwindow(new BC_Title(x, y, _("Keyframe frequency:")));
2158 OGGTheoraKeyframeFrequency *keyframe_frequency =
2159 new OGGTheoraKeyframeFrequency(x1 + 60, y, this);
2160 keyframe_frequency->create_objects();
2163 add_subwindow(new BC_Title(x, y, _("Keyframe force frequency:")));
2164 OGGTheoraKeyframeForceFrequency *keyframe_force_frequency =
2165 new OGGTheoraKeyframeForceFrequency(x1 + 60, y, this);
2166 keyframe_force_frequency->create_objects();
2169 add_subwindow(new BC_Title(x, y, _("Sharpness:")));
2170 OGGTheoraSharpness *sharpness =
2171 new OGGTheoraSharpness(x1 + 60, y, this);
2172 sharpness->create_objects();
2176 add_subwindow(new BC_OKButton(this));
2183 int OGGConfigVideo::close_event()
2189 OGGTheoraBitrate::OGGTheoraBitrate(int x, int y, OGGConfigVideo *gui)
2190 : BC_TextBox(x, y, 100, 1, gui->asset->theora_bitrate)
2196 int OGGTheoraBitrate::handle_event()
2198 // TODO: MIN / MAX check
2199 gui->asset->theora_bitrate = atol(get_text());
2206 OGGTheoraFixedBitrate::OGGTheoraFixedBitrate(int x, int y, OGGConfigVideo *gui)
2207 : BC_Radial(x, y, gui->asset->theora_fix_bitrate, _("Fixed bitrate"))
2212 int OGGTheoraFixedBitrate::handle_event()
2215 gui->asset->theora_fix_bitrate = 1;
2216 gui->fixed_quality->update(0);
2220 OGGTheoraFixedQuality::OGGTheoraFixedQuality(int x, int y, OGGConfigVideo *gui)
2221 : BC_Radial(x, y, !gui->asset->theora_fix_bitrate, _("Fixed quality"))
2226 int OGGTheoraFixedQuality::handle_event()
2229 gui->asset->theora_fix_bitrate = 0;
2230 gui->fixed_bitrate->update(0);
2234 OGGTheoraKeyframeFrequency::OGGTheoraKeyframeFrequency(int x, int y, OGGConfigVideo *gui)
2235 : BC_TumbleTextBox(gui,
2236 (int64_t)gui->asset->theora_keyframe_frequency,
2246 int OGGTheoraKeyframeFrequency::handle_event()
2248 gui->asset->theora_keyframe_frequency = atol(get_text());
2252 OGGTheoraKeyframeForceFrequency::OGGTheoraKeyframeForceFrequency(int x, int y, OGGConfigVideo *gui)
2253 : BC_TumbleTextBox(gui,
2254 (int64_t)gui->asset->theora_keyframe_frequency,
2264 int OGGTheoraKeyframeForceFrequency::handle_event()
2266 gui->asset->theora_keyframe_frequency = atol(get_text());
2271 OGGTheoraSharpness::OGGTheoraSharpness(int x, int y, OGGConfigVideo *gui)
2272 : BC_TumbleTextBox(gui,
2273 (int64_t)gui->asset->theora_sharpness,
2283 int OGGTheoraSharpness::handle_event()
2285 gui->asset->theora_sharpness = atol(get_text());
2290 PackagingEngineOGG::PackagingEngineOGG()
2296 PackagingEngineOGG::~PackagingEngineOGG()
2300 for(int i = 0; i < total_packages; i++)
2305 delete default_asset;
2310 int PackagingEngineOGG::create_packages_single_farm(
2312 Preferences *preferences,
2313 Asset *default_asset,
2317 this->total_start = total_start;
2318 this->total_end = total_end;
2321 this->preferences = preferences;
2323 // We make A COPY of the asset, because we set audio_data = 0 on local asset which is the same copy as default_asset...
2324 // Should be taken care of somewhere else actually
2325 this->default_asset = new Asset(*default_asset);
2327 audio_start = Units::to_int64(total_start * default_asset->sample_rate);
2328 video_start = Units::to_int64(total_start * default_asset->frame_rate);
2329 audio_position = audio_start;
2330 video_position = video_start;
2331 audio_end = Units::to_int64(total_end * default_asset->sample_rate);
2332 video_end = Units::to_int64(total_end * default_asset->frame_rate);
2333 current_package = 0;
2335 double total_len = total_end - total_start;
2336 //printf("PackageDispatcher::create_packages: %f / %d = %f\n", total_len, total_packages, package_len);
2339 if (default_asset->audio_data)
2341 if (default_asset->video_data)
2342 total_packages += preferences->renderfarm_job_count;
2344 packages = new RenderPackage*[total_packages];
2346 int local_current_package = 0;
2347 if (default_asset->audio_data)
2349 packages[local_current_package] = new RenderPackage;
2350 sprintf(packages[current_package]->path, "%s.audio", default_asset->path);
2351 local_current_package++;
2354 if (default_asset->video_data)
2356 video_package_len = (total_len) / preferences->renderfarm_job_count;
2357 int current_number; // The number being injected into the filename.
2358 int number_start; // Character in the filename path at which the number begins
2359 int total_digits; // Total number of digits including padding the user specified.
2361 Render::get_starting_number(default_asset->path,
2367 for(int i = 0; i < preferences->renderfarm_job_count; i++)
2369 RenderPackage *package = packages[local_current_package] = new RenderPackage;
2370 Render::create_filename(package->path,
2371 default_asset->path,
2376 local_current_package++;
2381 RenderPackage* PackagingEngineOGG::get_package_single_farm(double frames_per_second,
2386 //printf("PackageDispatcher::get_package %ld %ld %ld %ld\n", audio_position, video_position, audio_end, video_end);
2387 if (current_package == total_packages)
2390 RenderPackage *result = 0;
2391 if (current_package == 0 && default_asset->audio_data)
2393 result = packages[0];
2394 result->audio_start = audio_start;
2395 result->video_start = video_start;
2396 result->audio_end = audio_end;
2397 result->video_end = video_end;
2398 result->audio_do = 1;
2399 result->video_do = 0;
2400 } else if (default_asset->video_data)
2402 // Do not do any scaling according to node speed, so we know we can get evenly distributed 'forced' keyframes
2403 result = packages[current_package];
2404 result->audio_do = 0;
2405 result->video_do = 1;
2407 result->audio_start = audio_position;
2408 result->video_start = video_position;
2409 result->audio_end = audio_position +
2410 Units::round(video_package_len * default_asset->sample_rate);
2411 result->video_end = video_position +
2412 Units::round(video_package_len * default_asset->frame_rate);
2414 // Last package... take it all!
2415 if (current_package == total_packages -1 )
2417 result->audio_end = audio_end;
2418 result->video_end = video_end;
2421 audio_position = result->audio_end;
2422 video_position = result->video_end;
2431 void PackagingEngineOGG::get_package_paths(ArrayList<char*> *path_list)
2433 for(int i = 0; i < total_packages; i++)
2435 path_list->append(strdup(packages[i]->path));
2437 // We will mux to the the final file at the end!
2438 path_list->append(strdup(default_asset->path));
2441 int64_t PackagingEngineOGG::get_progress_max()
2443 return Units::to_int64(default_asset->sample_rate *
2444 (total_end - total_start)) * 2+
2445 Units::to_int64(preferences->render_preroll *
2447 default_asset->sample_rate);
2450 int PackagingEngineOGG::packages_are_done()
2454 // Mux audio and video into one file
2456 // First fix our asset... have to workaround the bug of corruption of local asset
2457 // Render::check_asset(edl, *default_asset);
2459 Asset *video_asset, *audio_asset;
2460 File *audio_file_gen, *video_file_gen;
2461 FileOGG *video_file, *audio_file;
2462 ogg_stream_state audio_in_stream, video_in_stream;
2464 int local_current_package = 0;
2465 if (default_asset->audio_data)
2467 audio_asset = new Asset(packages[local_current_package]->path);
2468 local_current_package++;
2470 audio_file_gen = new File();
2471 audio_file_gen->open_file(preferences,
2475 0, //base sample rate
2476 0); // base_frame rate
2477 audio_file = (FileOGG*) audio_file_gen->file;
2478 ogg_stream_init(&audio_in_stream, audio_file->tf->vo.serialno);
2479 audio_file->ogg_seek_to_databegin(audio_file->tf->audiosync, audio_file->tf->vo.serialno);
2482 if (default_asset->video_data)
2484 video_asset = new Asset(packages[local_current_package]->path);
2485 local_current_package++;
2487 video_file_gen = new File();
2488 video_file_gen->open_file(preferences,
2492 0, //base sample rate
2493 0); // base_frame rate
2494 video_file = (FileOGG*) video_file_gen->file;
2495 ogg_stream_init(&video_in_stream, video_file->tf->to.serialno);
2496 video_file->ogg_seek_to_databegin(video_file->tf->videosync, video_file->tf->to.serialno);
2500 File *output_file_gen = new File();
2501 output_file_gen->open_file(preferences,
2505 default_asset->sample_rate,
2506 default_asset->frame_rate);
2507 FileOGG *output_file = (FileOGG*) output_file_gen->file;
2509 ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */
2510 ogg_packet op; /* one raw packet of data for decode */
2513 int audio_ready = default_asset->audio_data;
2514 int video_ready = default_asset->video_data;
2515 int64_t video_packetno = 1;
2516 int64_t audio_packetno = 1;
2517 int64_t frame_offset = 0;
2518 int64_t current_frame = 0;
2519 while ((default_asset->audio_data && audio_ready) || (default_asset->video_data && video_ready))
2523 while (ogg_stream_packetpeek(&video_in_stream, NULL) != 1) // get as many pages as needed for one package
2525 if (!video_file->ogg_get_next_page(video_file->tf->videosync, video_file->tf->to.serialno, &video_file->tf->videopage))
2527 // We are at the end of our file, see if it is more and open more if there is
2528 if (local_current_package < total_packages)
2530 frame_offset = current_frame +1;
2531 ogg_stream_clear(&video_in_stream);
2532 video_file_gen->close_file();
2533 delete video_file_gen;
2535 video_asset = new Asset(packages[local_current_package]->path);
2536 local_current_package++;
2538 video_file_gen = new File();
2539 video_file_gen->open_file(preferences,
2543 0, //base sample rate
2544 0); // base_frame rate
2545 video_file = (FileOGG*) video_file_gen->file;
2546 ogg_stream_init(&video_in_stream, video_file->tf->to.serialno);
2548 video_file->ogg_seek_to_databegin(video_file->tf->videosync, video_file->tf->to.serialno);
2554 ogg_stream_pagein(&video_in_stream, &video_file->tf->videopage);
2556 while (ogg_stream_packetpeek(&video_in_stream, NULL) == 1) // get all packets out of the page
2558 ogg_stream_packetout(&video_in_stream, &op);
2559 if (local_current_package != total_packages) // keep it from closing the stream
2561 if (video_packetno != 1) // if this is not the first video package do not start with b_o_s
2565 op.packetno = video_packetno;
2567 int64_t granulepos = op.granulepos;
2568 if (granulepos != -1)
2571 int64_t rel_iframe = granulepos >> video_file->theora_keyframe_granule_shift;
2572 int64_t rel_pframe = granulepos - (rel_iframe << video_file->theora_keyframe_granule_shift);
2573 int64_t rel_current_frame = rel_iframe + rel_pframe;
2574 current_frame = frame_offset + rel_current_frame;
2575 int64_t abs_iframe = current_frame - rel_pframe;
2577 op.granulepos = (abs_iframe << video_file->theora_keyframe_granule_shift) + rel_pframe;
2579 // printf("iframe: %i, pframe: %i, granulepos: %i, op.packetno %lli, abs_iframe: %i\n", rel_iframe, rel_pframe, granulepos, op.packetno, abs_iframe);
2582 ogg_stream_packetin (&output_file->tf->to, &op);
2583 output_file->tf->v_pkg++;
2588 while (ogg_stream_packetpeek(&audio_in_stream, NULL) != 1) // get as many pages as needed for one package
2590 if (!audio_file->ogg_get_next_page(audio_file->tf->audiosync, audio_file->tf->vo.serialno, &audio_file->tf->audiopage))
2595 ogg_stream_pagein(&audio_in_stream, &audio_file->tf->audiopage);
2597 while (ogg_stream_packetpeek(&audio_in_stream, NULL) == 1) // get all packets out of the page
2599 ogg_stream_packetout(&audio_in_stream, &op);
2600 ogg_stream_packetin (&output_file->tf->vo, &op);
2602 output_file->tf->a_pkg++;
2606 output_file->flush_ogg(0);
2611 // flush_ogg(1) is called on file closing time...
2612 // output_file->flush_ogg(1);
2614 // Just prevent thet write_samples and write_frames are called
2615 output_file->final_write = 0;
2617 if (default_asset->audio_data)
2619 ogg_stream_clear(&audio_in_stream);
2620 audio_file_gen->close_file();
2621 delete audio_file_gen;
2624 if (default_asset->video_data)
2626 ogg_stream_clear(&video_in_stream);
2627 video_file_gen->close_file();
2628 delete video_file_gen;
2632 output_file_gen->close_file();
2633 delete output_file_gen;
2635 // Now delete the temp files
2636 for(int i = 0; i < total_packages; i++)
2637 unlink(packages[i]->path);