00001 #include "asset.h"
00002 #include "bcsignals.h"
00003 #include "byteorder.h"
00004 #include "clip.h"
00005 #include "edit.h"
00006 #include "file.h"
00007 #include "fileogg.h"
00008 #include "guicast.h"
00009 #include "language.h"
00010 #include "mutex.h"
00011 #include "mwindow.inc"
00012 #include "quicktime.h"
00013 #include "vframe.h"
00014 #include "videodevice.inc"
00015 #include "cmodel_permutation.h"
00016 #include "interlacemodes.h"
00017 #include "mainerror.h"
00018
00019 #include <sys/types.h>
00020 #include <sys/stat.h>
00021 #include <fcntl.h>
00022 #include <unistd.h>
00023 #include <string.h>
00024 #include <errno.h>
00025
00026
00027 #include "preferences.h"
00028 #include "render.h"
00029
00030 #define READ_SIZE 66000
00031
00032
00033
00034
00035
00036 FileOGG::FileOGG(Asset *asset, File *file)
00037 : FileBase(asset, file)
00038 {
00039 if(asset->format == FILE_UNKNOWN)
00040 asset->format = FILE_OGG;
00041 asset->byte_order = 0;
00042 reset_parameters();
00043 final_write = 1;
00044 }
00045
00046 FileOGG::~FileOGG()
00047 {
00048 if (tf)
00049 {
00050
00051 if (tf->videosync)
00052 {
00053 ogg_sync_clear(&tf->videosync->sync);
00054 delete tf->videosync;
00055 theora_info_clear(&tf->ti);
00056 theora_comment_clear(&tf->tc);
00057 }
00058 if (tf->audiosync)
00059 {
00060 ogg_sync_clear(&tf->audiosync->sync);
00061 delete tf->audiosync;
00062 vorbis_info_clear(&tf->vi);
00063 vorbis_comment_clear(&tf->vc);
00064 }
00065 if (tf->vpage)
00066 free(tf->vpage);
00067 if (tf->apage)
00068 free(tf->apage);
00069 delete tf;
00070 }
00071 if (temp_frame) delete temp_frame;
00072 if (stream) close_file();
00073 if(pcm_history)
00074 {
00075 for(int i = 0; i < asset->channels; i++)
00076 delete [] pcm_history[i];
00077 delete [] pcm_history;
00078 }
00079
00080 if (flush_lock) delete flush_lock;
00081 }
00082
00083 void FileOGG::get_parameters(BC_WindowBase *parent_window,
00084 Asset *asset,
00085 BC_WindowBase* &format_window,
00086 int audio_options,
00087 int video_options)
00088 {
00089 if(audio_options)
00090 {
00091 OGGConfigAudio *window = new OGGConfigAudio(parent_window, asset);
00092 format_window = window;
00093 window->create_objects();
00094 window->run_window();
00095 delete window;
00096 }
00097 else
00098 if(video_options)
00099 {
00100 OGGConfigVideo *window = new OGGConfigVideo(parent_window, asset);
00101 format_window = window;
00102 window->create_objects();
00103 window->run_window();
00104 delete window;
00105 }
00106 }
00107
00108 int FileOGG::reset_parameters_derived()
00109 {
00110 tf = 0;
00111 temp_frame = 0;
00112 stream = 0;
00113 flush_lock = 0;
00114 pcm_history = 0;
00115
00116 }
00117
00118 static int read_buffer(FILE *in, sync_window_t *sw, int buflen)
00119 {
00120 char *buffer = ogg_sync_buffer(&sw->sync, buflen);
00121
00122 sw->wlen = fread(buffer, 1, buflen, in);
00123 ogg_sync_wrote(&sw->sync, sw->wlen);
00124
00125 sw->file_bufpos += sw->wlen;
00126
00127 return (sw->wlen);
00128 }
00129
00130 static int read_buffer_at(FILE *in, sync_window_t *sw, int buflen, off_t filepos)
00131 {
00132
00133 fseeko(in, filepos, SEEK_SET);
00134
00135
00136 sw->file_bufpos = filepos;
00137 sw->file_pagepos = filepos;
00138 ogg_sync_reset(&sw->sync);
00139
00140
00141 return read_buffer(in, sw, buflen);
00142 }
00143
00144 static int take_page_out_autoadvance(FILE *in, sync_window_t *sw, ogg_page *og)
00145 {
00146 while (1)
00147 {
00148 int ret = ogg_sync_pageout(&sw->sync, og);
00149 if (ret > 0)
00150 {
00151
00152
00153 sw->file_pagepos += og->header_len + og->body_len;
00154
00155 return ret;
00156 }
00157 else if (ret < 0)
00158 {
00159 eprintf("FileOGG: Taking page out on nonsynced stream!\n");
00160 return ret;
00161
00162 } else
00163 {
00164
00165 if (read_buffer(in, sw, READ_SIZE) == 0)
00166 {
00167
00168
00169 return 0;
00170 }
00171 }
00172 }
00173 return 1;
00174 }
00175
00176
00177
00178
00179 static int sync_and_take_page_out(sync_window_t *sw, ogg_page *page)
00180 {
00181 page->header_len = 0;
00182 page->body_len = 0;
00183 page->header = 0;
00184 page->body = 0;
00185 int ret = ogg_sync_pageseek(&sw->sync, page);
00186 if (ret < 0)
00187 {
00188 sw->file_pagepos -= ret;
00189 }
00190 else if (ret > 0)
00191 {
00192 sw->file_pagepos += ret;
00193
00194 }
00195 return ret;
00196 }
00197
00198
00199 int FileOGG::open_file(int rd, int wr)
00200 {
00201 this->rd = rd;
00202 this->wr = wr;
00203 if (!tf)
00204 {
00205 tf = new theoraframes_info_t;
00206 memset(tf, 0, sizeof(*tf));
00207 }
00208
00209
00210 if(wr)
00211 {
00212
00213
00214 if((stream = fopen(asset->path, "w+b")) == 0)
00215 {
00216 eprintf("Error while opening \"%s\" for writing. %m\n", asset->path);
00217 return 1;
00218 }
00219
00220 tf->audio_bytesout = 0;
00221 tf->video_bytesout = 0;
00222 tf->videotime = 0;
00223 tf->audiotime = 0;
00224
00225 tf->vpage_valid = 0;
00226 tf->apage_valid = 0;
00227 tf->apage_buffer_length = 0;
00228 tf->vpage_buffer_length = 0;
00229 tf->apage = NULL;
00230 tf->vpage = NULL;
00231 tf->v_pkg=0;
00232 tf->a_pkg=0;
00233
00234
00235
00236 srand (time (NULL));
00237
00238 if(asset->video_data)
00239 {
00240 ogg_stream_init (&tf->to, rand ());
00241
00242 theora_info_init (&tf->ti);
00243
00244 tf->ti.frame_width = asset->width;
00245 tf->ti.frame_height = asset->height;
00246
00247 tf->ti.width = ((asset->width + 15) >>4)<<4;
00248 tf->ti.height = ((asset->height + 15) >>4)<<4;
00249 if (tf->ti.width != tf->ti.frame_width || tf->ti.height != tf->ti.frame_height)
00250 {
00251 eprintf("WARNING: Encoding theora when width or height are not dividable by 16 is suboptimal\n");
00252 }
00253
00254 tf->ti.offset_x = 0;
00255 tf->ti.offset_y = tf->ti.height - tf->ti.frame_height;
00256 tf->ti.fps_numerator = (unsigned int)(asset->frame_rate * 1000000);
00257 tf->ti.fps_denominator = 1000000;
00258
00259 if (asset->aspect_ratio > 0)
00260 {
00261
00262 float pixel_aspect = asset->aspect_ratio / asset->width * asset->height;
00263 tf->ti.aspect_numerator = (unsigned int)(pixel_aspect * 1000000);
00264 tf->ti.aspect_denominator = 1000000;
00265 } else
00266 {
00267 tf->ti.aspect_numerator = 1000000;
00268 tf->ti.aspect_denominator = 1000000;
00269 }
00270 if(EQUIV(asset->frame_rate, 25) || EQUIV(asset->frame_rate, 50))
00271 tf->ti.colorspace = OC_CS_ITU_REC_470BG;
00272 else if((asset->frame_rate > 29 && asset->frame_rate < 31) || (asset->frame_rate > 59 && asset->frame_rate < 61) )
00273 tf->ti.colorspace = OC_CS_ITU_REC_470M;
00274 else
00275 tf->ti.colorspace = OC_CS_UNSPECIFIED;
00276
00277 if (asset->theora_fix_bitrate)
00278 {
00279 tf->ti.target_bitrate = asset->theora_bitrate;
00280 tf->ti.quality = 0;
00281 } else
00282 {
00283 tf->ti.target_bitrate = 0;
00284 tf->ti.quality = asset->theora_quality;
00285 }
00286 tf->ti.dropframes_p = 0;
00287 tf->ti.quick_p = 1;
00288 tf->ti.keyframe_auto_p = 1;
00289 tf->ti.keyframe_frequency = asset->theora_keyframe_frequency;
00290 tf->ti.keyframe_frequency_force = asset->theora_keyframe_force_frequency;
00291 tf->ti.keyframe_data_target_bitrate = (unsigned int) (tf->ti.target_bitrate * 1.5) ;
00292 tf->ti.keyframe_auto_threshold = 80;
00293 tf->ti.keyframe_mindistance = 8;
00294 tf->ti.noise_sensitivity = 1;
00295 tf->ti.sharpness = 2;
00296
00297
00298 if (theora_encode_init (&tf->td, &tf->ti))
00299 {
00300 eprintf("(FileOGG:file_open) initialization of theora codec failed\n");
00301 }
00302 }
00303
00304
00305
00306 if(asset->audio_data)
00307 {
00308 ogg_stream_init (&tf->vo, rand ());
00309 vorbis_info_init (&tf->vi);
00310
00311 int ret;
00312 if(!asset->vorbis_vbr)
00313 {
00314 ret = vorbis_encode_init(&tf->vi,
00315 asset->channels,
00316 asset->sample_rate,
00317 asset->vorbis_max_bitrate,
00318 asset->vorbis_bitrate,
00319 asset->vorbis_min_bitrate);
00320 } else
00321 {
00322
00323 ret = vorbis_encode_setup_managed(&tf->vi,
00324 asset->channels,
00325 asset->sample_rate,
00326 -1,
00327 asset->vorbis_bitrate,
00328 -1);
00329 ret |= vorbis_encode_ctl(&tf->vi, OV_ECTL_RATEMANAGE_AVG, NULL);
00330 ret |= vorbis_encode_setup_init(&tf->vi);
00331 }
00332
00333 if (ret)
00334 {
00335 eprintf("The Vorbis encoder could not set up a mode according to\n"
00336 "the requested quality or bitrate.\n\n");
00337
00338 fclose (stream);
00339 stream = 0;
00340 return 1;
00341 }
00342
00343 vorbis_comment_init (&tf->vc);
00344 vorbis_comment_add_tag (&tf->vc, "ENCODER", PACKAGE_STRING);
00345
00346 vorbis_analysis_init (&tf->vd, &tf->vi);
00347 vorbis_block_init (&tf->vd, &tf->vb);
00348
00349 }
00350
00351
00352
00353
00354
00355 if(asset->video_data)
00356 {
00357 theora_encode_header (&tf->td, &tf->op);
00358 ogg_stream_packetin (&tf->to, &tf->op);
00359 if (ogg_stream_pageout (&tf->to, &tf->og) != 1)
00360 {
00361 eprintf("Internal Ogg library error.\n");
00362 return 1;
00363 }
00364 fwrite (tf->og.header, 1, tf->og.header_len, stream);
00365 fwrite (tf->og.body, 1, tf->og.body_len, stream);
00366
00367
00368 theora_comment_init (&tf->tc);
00369 theora_comment_add_tag (&tf->tc, "ENCODER", PACKAGE_STRING);
00370 theora_encode_comment (&tf->tc, &tf->op);
00371 ogg_stream_packetin (&tf->to, &tf->op);
00372 theora_comment_clear(&tf->tc);
00373 theora_encode_tables (&tf->td, &tf->op);
00374 ogg_stream_packetin (&tf->to, &tf->op);
00375 }
00376 if(asset->audio_data)
00377 {
00378 ogg_packet header;
00379 ogg_packet header_comm;
00380 ogg_packet header_code;
00381
00382 vorbis_analysis_headerout (&tf->vd, &tf->vc, &header,
00383 &header_comm, &header_code);
00384 ogg_stream_packetin (&tf->vo, &header);
00385 vorbis_comment_clear(&tf->vc);
00386 if (ogg_stream_pageout (&tf->vo, &tf->og) != 1)
00387 {
00388 eprintf("Internal Ogg library error.\n");
00389 return 1;
00390 }
00391 fwrite (tf->og.header, 1, tf->og.header_len, stream);
00392 fwrite (tf->og.body, 1, tf->og.body_len, stream);
00393
00394
00395 ogg_stream_packetin (&tf->vo, &header_comm);
00396 ogg_stream_packetin (&tf->vo, &header_code);
00397 }
00398
00399
00400
00401
00402 while (1 && asset->video_data)
00403 {
00404 int result = ogg_stream_flush (&tf->to, &tf->og);
00405 if (result < 0)
00406 {
00407
00408 eprintf("Internal Ogg library error.\n");
00409 return 1;
00410 }
00411 if (result == 0)
00412 break;
00413 fwrite (tf->og.header, 1, tf->og.header_len, stream);
00414 fwrite (tf->og.body, 1, tf->og.body_len, stream);
00415 }
00416 while (1 && asset->audio_data)
00417 {
00418 int result = ogg_stream_flush (&tf->vo, &tf->og);
00419 if (result < 0)
00420 {
00421
00422 eprintf("Internal Ogg library error.\n");
00423 return 1;
00424 }
00425 if (result == 0)
00426 break;
00427 fwrite (tf->og.header, 1, tf->og.header_len, stream);
00428 fwrite (tf->og.body, 1, tf->og.body_len, stream);
00429 }
00430 flush_lock = new Mutex("OGGFile::Flush lock");
00431
00432 } else
00433 if (rd)
00434 {
00435
00436 if((stream = fopen(asset->path, "rb")) == 0)
00437 {
00438 eprintf("Error while opening %s for reading. %m\n", asset->path);
00439 return 1;
00440 }
00441
00442
00443 struct stat file_stat;
00444 stat(asset->path, &file_stat);
00445 file_length = file_stat.st_size;
00446
00447
00448
00449 sync_window_t oy;
00450 ogg_sync_init(&oy.sync);
00451
00452 read_buffer_at(stream, &oy, READ_SIZE, 0);
00453
00454
00455
00456 vorbis_info_init(&tf->vi);
00457 vorbis_comment_init(&tf->vc);
00458
00459
00460
00461 theora_comment_init(&tf->tc);
00462 theora_info_init(&tf->ti);
00463
00464
00465
00466
00467
00468 int stateflag = 0;
00469 int theora_p = 0;
00470 int vorbis_p = 0;
00471 while(!stateflag)
00472 {
00473
00474
00475
00476 TRACE("FileOGG::open_file 60")
00477
00478
00479
00480 while(take_page_out_autoadvance(stream, &oy, &tf->og) > 0)
00481 {
00482 ogg_stream_state test;
00483
00484
00485 if(!ogg_page_bos(&tf->og))
00486 {
00487
00488
00489 if(theora_p)ogg_stream_pagein(&tf->to, &tf->og);
00490 if(vorbis_p)ogg_stream_pagein(&tf->vo, &tf->og);
00491
00492 stateflag = 1;
00493 break;
00494 }
00495
00496 ogg_stream_init(&test, ogg_page_serialno(&tf->og));
00497 ogg_stream_pagein(&test, &tf->og);
00498 ogg_stream_packetout(&test, &tf->op);
00499
00500
00501 if(!theora_p && theora_decode_header(&tf->ti, &tf->tc, &tf->op)>=0)
00502 {
00503
00504 memcpy(&tf->to, &test, sizeof(test));
00505 theora_p = 1;
00506
00507 unsigned char * header = tf->op.packet;
00508 theora_keyframe_granule_shift = (char) ((header[40] & 0x03) << 3);
00509 theora_keyframe_granule_shift |= (header[41] & 0xe0) >> 5;
00510
00511 } else if(!vorbis_p && vorbis_synthesis_headerin(&tf->vi, &tf->vc, &tf->op)>=0)
00512 {
00513
00514 memcpy(&tf->vo, &test, sizeof(test));
00515 vorbis_p = 1;
00516 } else
00517 {
00518
00519 ogg_stream_clear(&test);
00520 }
00521 }
00522
00523 }
00524
00525
00526
00527 while((theora_p && theora_p < 3) || (vorbis_p && vorbis_p < 3))
00528 {
00529 int ret;
00530
00531
00532 while(theora_p && (theora_p < 3) && (ret = ogg_stream_packetout(&tf->to, &tf->op)))
00533 {
00534 if(ret < 0)
00535 {
00536 eprintf("Error parsing Theora stream headers; corrupt stream?\n");
00537 return 1;
00538 }
00539 if(theora_decode_header(&tf->ti, &tf->tc, &tf->op))
00540 {
00541 eprintf("Error parsing Theora stream headers; corrupt stream?\n");
00542 return 1;
00543 }
00544 theora_p++;
00545 if(theora_p == 3)
00546 break;
00547 }
00548
00549
00550 while(vorbis_p && (vorbis_p < 3) && (ret = ogg_stream_packetout(&tf->vo, &tf->op)))
00551 {
00552 if(ret<0)
00553 {
00554 eprintf("Error parsing Vorbis stream headers; corrupt stream?\n");
00555 return 1;
00556 }
00557 if (vorbis_synthesis_headerin(&tf->vi, &tf->vc, &tf->op))
00558 {
00559 eprintf("Error parsing Vorbis stream headers; corrupt stream?\n");
00560 return 1;
00561 }
00562 vorbis_p++;
00563 if (vorbis_p == 3)
00564 break;
00565 }
00566
00567 if ((!vorbis_p || vorbis_p == 3) && (!theora_p || theora_p == 3))
00568 break;
00569
00570
00571
00572 if(take_page_out_autoadvance(stream, &oy, &tf->og) > 0)
00573 {
00574
00575 if(theora_p) ogg_stream_pagein(&tf->to, &tf->og);
00576 if(vorbis_p) ogg_stream_pagein(&tf->vo, &tf->og);
00577
00578 } else
00579 {
00580 eprintf("End of file while searching for codec headers.\n");
00581 return 1;
00582 }
00583 }
00584
00585 filedata_begin = oy.file_pagepos;
00586
00587
00588
00589
00590 if(theora_p)
00591 {
00592 int ret;
00593
00594
00595 tf->td.internal_encode = 0;
00596
00597 ret = theora_decode_init(&tf->td, &tf->ti);
00598 double fps = (double)tf->ti.fps_numerator/tf->ti.fps_denominator;
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618 theora_cmodel = BC_YUV420P;
00619
00620 if(tf->ti.width!=tf->ti.frame_width || tf->ti.height!=tf->ti.frame_height)
00621 {
00622 eprintf("Frame content is %dx%d with offset (%d,%d), We do not support this yet. You will get black border.\n",
00623 tf->ti.frame_width, tf->ti.frame_height, tf->ti.offset_x, tf->ti.offset_y);
00624 }
00625 tf->videosync = new sync_window_t;
00626 ogg_sync_init(&tf->videosync->sync);
00627 tf->videosync->wlen = 0;
00628
00629 ret = ogg_get_first_page(tf->videosync, tf->to.serialno, &tf->videopage);
00630 ogg_packet op;
00631
00632
00633 ogg_stream_reset(&tf->to);
00634 ogg_stream_pagein(&tf->to, &tf->videopage);
00635 while (1)
00636 {
00637 while (ogg_stream_packetpeek(&tf->to, NULL) != 1)
00638 {
00639 if (!ogg_get_next_page(tf->videosync, tf->to.serialno, &tf->videopage))
00640 {
00641 eprintf("Cannot find next page while looking for first non-header packet\n");
00642 return 1;
00643 }
00644 ogg_stream_pagein(&tf->to, &tf->videopage);
00645 }
00646 ogg_stream_packetout(&tf->to, &op);
00647 if (!theora_packet_isheader(&op))
00648 break;
00649 }
00650
00651 while (ogg_page_packets(&tf->videopage) == 0)
00652 {
00653 if (ogg_page_granulepos(&tf->videopage) != -1)
00654 {
00655 eprintf("Broken ogg file - broken page: ogg_page_packets == 0 and granulepos != -1\n");
00656 return 1;
00657 }
00658 ogg_get_next_page(tf->videosync, tf->to.serialno, &tf->videopage);
00659 }
00660
00661
00662 start_frame = (int64_t) (theora_granule_frame (&tf->td, ogg_page_granulepos(&tf->videopage)) - ogg_page_packets(&tf->videopage)) + 1;
00663
00664 ret = ogg_get_last_page(tf->videosync, tf->to.serialno, &tf->videopage);
00665 last_frame = (int64_t) (theora_granule_frame (&tf->td, ogg_page_granulepos(&tf->videopage)));
00666 asset->video_length = last_frame - start_frame + 1;
00667
00668
00669 asset->layers = 1;
00670
00671 asset->width = tf->ti.width;
00672 asset->height = tf->ti.height;
00673
00674 if(!asset->frame_rate)
00675 asset->frame_rate = fps;
00676
00677 if(!asset->interlace_mode)
00678 asset->interlace_mode = BC_ILACE_MODE_NOTINTERLACED;
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696 set_video_position(0);
00697 ogg_frame_position = -10;
00698 asset->video_data = 1;
00699 strncpy(asset->vcodec, "theo", 4);
00700
00701
00702
00703
00704 } else
00705 {
00706
00707 theora_info_clear(&tf->ti);
00708 theora_comment_clear(&tf->tc);
00709 }
00710
00711
00712 if(vorbis_p)
00713 {
00714 vorbis_synthesis_init(&tf->vd, &tf->vi);
00715 vorbis_block_init(&tf->vd, &tf->vb);
00716
00717
00718
00719
00720 tf->audiosync = new sync_window_t;
00721 ogg_sync_init(&tf->audiosync->sync);
00722 tf->audiosync->wlen = 0;
00723
00724 int ret2 = ogg_get_first_page(tf->audiosync, tf->vo.serialno, &tf->audiopage);
00725 int result;
00726 ogg_packet op;
00727 ogg_stream_reset(&tf->vo);
00728
00729 ogg_stream_pagein(&tf->vo, &tf->audiopage);
00730 ogg_int64_t accumulated = 0;
00731 long lastblock = -1;
00732 while((result = ogg_stream_packetout(&tf->vo, &op)))
00733 {
00734 if(result > 0)
00735 {
00736 long thisblock = vorbis_packet_blocksize(&tf->vi, &op);
00737 if(lastblock != -1)
00738 accumulated += (lastblock + thisblock) >> 2;
00739 lastblock = thisblock;
00740 }
00741 }
00742 start_sample = ogg_page_granulepos(&tf->audiopage) - accumulated;
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757 int ret = ogg_get_last_page(tf->audiosync, tf->vo.serialno, &tf->audiopage);
00758 last_sample = ogg_page_granulepos(&tf->audiopage);
00759 asset->audio_length = last_sample - start_sample;
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795 asset->channels = tf->vi.channels;
00796 if(!asset->sample_rate)
00797 asset->sample_rate = tf->vi.rate;
00798 asset->audio_data = 1;
00799
00800
00801 ogg_sample_position = -10;
00802 set_audio_position(0);
00803 strncpy(asset->acodec, "vorb", 4);
00804
00805
00806 } else
00807 {
00808
00809 vorbis_info_clear(&tf->vi);
00810 vorbis_comment_clear(&tf->vc);
00811 }
00812
00813 ogg_sync_clear(&oy.sync);
00814
00815 }
00816 return 0;
00817 }
00818
00819 int FileOGG::ogg_get_prev_page(sync_window_t *sw, long serialno, ogg_page *og)
00820 {
00821 char *buffer;
00822 ogg_page page;
00823 off_t filepos = sw->file_pagepos_found - READ_SIZE;
00824 int first_page_offset = 0;
00825 int done = 0;
00826 int read_len = READ_SIZE;
00827
00828
00829 while (!done)
00830 {
00831 if (filepos < 0)
00832 {
00833
00834 read_len = read_len + filepos;
00835 filepos = 0;
00836 }
00837 if (read_len <= 0)
00838 return 0;
00839 int have_read = read_buffer_at(stream, sw, read_len, filepos);
00840
00841
00842
00843
00844
00845
00846 if (!have_read)
00847 return 0;
00848
00849
00850 int page_offset = 0;
00851 int page_length = 0;
00852 int first_page = 1;
00853 while (first_page || page_length)
00854 {
00855
00856 while ((page_length = sync_and_take_page_out(sw, &page)) < 0)
00857 {
00858 page_offset -= page_length;
00859
00860
00861
00862 }
00863
00864
00865
00866
00867
00868 if (first_page)
00869 first_page_offset = page_offset;
00870 first_page = 0;
00871
00872 if (page_length && ogg_page_serialno(&page) == serialno)
00873 {
00874
00875 done = 1;
00876
00877 sw->file_pagepos_found = sw->file_pagepos - page.header_len - page.body_len;
00878
00879 memcpy(og, &page, sizeof(page));
00880 }
00881 }
00882 off_t old_filepos = filepos;
00883
00884 filepos = filepos + first_page_offset - READ_SIZE;
00885 }
00886
00887
00888 if (done)
00889 return 1;
00890 else
00891 return 0;
00892 }
00893
00894 int FileOGG::ogg_get_last_page(sync_window_t *sw, long serialno, ogg_page *og)
00895 {
00896 char *buffer;
00897 ogg_page page;
00898 off_t filepos = file_length - READ_SIZE;
00899 if (filepos < 0)
00900 filepos = 0;
00901
00902 int first_page_offset = 0;
00903 int done = 0;
00904 while (!done && filepos >= 0)
00905 {
00906 int readlen;
00907 readlen = read_buffer_at(stream, sw, READ_SIZE, filepos);
00908
00909
00910 int page_offset = 0;
00911 int page_length = 0;
00912 int first_page = 1;
00913 while (first_page || page_length)
00914 {
00915
00916 while ((page_length = sync_and_take_page_out(sw, &page)) < 0)
00917 page_offset -= page_length;
00918 if (first_page)
00919 first_page_offset = page_offset;
00920 first_page = 0;
00921 if (page_length && ogg_page_serialno(&page) == serialno)
00922 {
00923
00924 done = 1;
00925 sw->file_pagepos_found = sw->file_pagepos - page.header_len - page.body_len;
00926 memcpy(og, &page, sizeof(page));
00927 }
00928 }
00929 filepos = filepos + first_page_offset - READ_SIZE;
00930 }
00931
00932 if (done)
00933 return 1;
00934 else
00935 return 0;
00936 }
00937
00938 int FileOGG::ogg_get_first_page(sync_window_t *sw, long serialno, ogg_page *og)
00939 {
00940
00941 read_buffer_at(stream, sw, READ_SIZE, 0);
00942
00943 return (ogg_get_next_page(sw, serialno, og));
00944 }
00945
00946 int FileOGG::ogg_seek_to_databegin(sync_window_t *sw, long serialno)
00947 {
00948
00949
00950 read_buffer_at(stream, sw, READ_SIZE, filedata_begin);
00951
00952 return (0);
00953 }
00954
00955 int FileOGG::ogg_get_next_page(sync_window_t *sw, long serialno, ogg_page *og)
00956 {
00957 while (take_page_out_autoadvance(stream, sw, og) > 0)
00958 {
00959 if (ogg_page_serialno(og) == serialno)
00960 {
00961 sw->file_pagepos_found = sw->file_pagepos - og->header_len - og->body_len;
00962 return 1;
00963 }
00964 }
00965 return 0;
00966 }
00967
00968 int FileOGG::ogg_sync_and_get_next_page(sync_window_t *sw, long serialno, ogg_page *og)
00969 {
00970
00971 int ret;
00972 while ((ret = sync_and_take_page_out(sw, og)) < 0)
00973 {
00974
00975 }
00976 if (ret == 0)
00977 return 0;
00978 if (ogg_page_serialno(og) == serialno)
00979 {
00980 sw->file_pagepos_found = sw->file_pagepos - og->header_len - og->body_len;
00981 return 1;
00982 }
00983 while (ogg_get_next_page(sw, serialno, og))
00984 if (ogg_page_serialno(og) == serialno)
00985 {
00986 sw->file_pagepos_found = sw->file_pagepos - og->header_len - og->body_len;
00987 return 1;
00988 }
00989
00990 return 0;
00991 }
00992
00993
00994
00995 int FileOGG::ogg_get_page_of_sample(sync_window_t *sw, long serialno, ogg_page *og, int64_t sample)
00996 {
00997
00998 if (sample >= asset->audio_length + start_sample)
00999 {
01000 eprintf("Illegal seek beyond end of samples\n");
01001 return 0;
01002 }
01003 off_t educated_guess = filedata_begin + (file_length - filedata_begin) * (sample - start_sample) / asset->audio_length - READ_SIZE;
01004 if (educated_guess < 0)
01005 educated_guess = 0;
01006
01007
01008 read_buffer_at(stream, sw, READ_SIZE, educated_guess);
01009 ogg_sync_and_get_next_page(sw, serialno, og);
01010 int64_t end_sample = ogg_page_granulepos(og);
01011
01012 int64_t start_sample = 0;
01013
01014
01015 if (end_sample <= sample)
01016 {
01017
01018 while (end_sample <= sample)
01019 {
01020 ogg_get_next_page(sw, serialno, og);
01021 start_sample = end_sample;
01022 end_sample = ogg_page_granulepos(og);
01023 }
01024 ogg_get_prev_page(sw, serialno, og);
01025 while (ogg_page_continued(og) && ogg_page_packets(og) == 1)
01026 ogg_get_prev_page(sw, serialno, og);
01027 } else
01028 {
01029
01030 start_sample = end_sample;
01031 while (start_sample > sample || (ogg_page_continued(og) &&
01032 ogg_page_packets(og) == 1))
01033 {
01034
01035 ogg_get_prev_page(sw, serialno, og);
01036 end_sample = start_sample;
01037 start_sample = ogg_page_granulepos(og);
01038 }
01039
01040
01041 }
01042
01043
01044 return 1;
01045 }
01046
01047
01048
01049
01050
01051 int FileOGG::ogg_seek_to_sample(sync_window_t *sw, long serialno, int64_t sample)
01052 {
01053
01054
01055 ogg_page og;
01056 ogg_packet op;
01057
01058 if (!ogg_get_page_of_sample(sw, serialno, &og, sample))
01059 {
01060 eprintf("Seeking to sample's page failed\n");
01061
01062 return 0;
01063 }
01064
01065 vorbis_synthesis_restart(&tf->vd);
01066 ogg_stream_reset(&tf->vo);
01067 ogg_stream_pagein(&tf->vo, &og);
01068 int sync = 0;
01069
01070
01071 int64_t current_comming_sample = -1;
01072 while (1)
01073 {
01074
01075
01076 while (ogg_stream_packetpeek(&tf->vo, NULL) != 1)
01077 {
01078 if (!ogg_get_next_page(sw, serialno, &og))
01079 {
01080 eprintf("Cannot find next page while seeking\n");
01081 return 0;
01082 }
01083 ogg_stream_pagein(&tf->vo, &og);
01084 }
01085 ogg_stream_packetout(&tf->vo, &op);
01086 if (sync)
01087 {
01088
01089 if(!vorbis_synthesis(&tf->vb, &op))
01090 {
01091 int ret= vorbis_synthesis_blockin(&tf->vd, &tf->vb);
01092 int64_t previous_comming_sample = current_comming_sample;
01093 current_comming_sample += vorbis_synthesis_pcmout(&tf->vd, NULL);
01094 if (current_comming_sample > sample)
01095 {
01096 if (previous_comming_sample > sample)
01097 {
01098 eprintf("Ogg decoding error while seeking sample\n");
01099 }
01100 vorbis_synthesis_read(&tf->vd, (sample - previous_comming_sample));
01101
01102 return 1;
01103 } else
01104 {
01105
01106 vorbis_synthesis_read(&tf->vd, (current_comming_sample - previous_comming_sample));
01107
01108 }
01109 }
01110 }
01111 if (!sync && op.granulepos >= 0)
01112 {
01113 sync = 1;
01114 current_comming_sample = op.granulepos;
01115 if(!vorbis_synthesis(&tf->vb, &op))
01116 {
01117 vorbis_synthesis_blockin(&tf->vd, &tf->vb);
01118 if (vorbis_synthesis_pcmout(&tf->vd, NULL) != 0)
01119 {
01120 eprintf("Something wrong while trying to seek\n");
01121 return 0;
01122 }
01123
01124 }
01125
01126 }
01127 }
01128
01129
01130 return 0;
01131 }
01132
01133 int FileOGG::ogg_get_page_of_frame(sync_window_t *sw, long serialno, ogg_page *og, int64_t frame)
01134 {
01135 if (frame >= asset->video_length + start_frame)
01136 {
01137 eprintf("Illegal seek beyond end of frames\n");
01138 return 0;
01139 }
01140
01141
01142 off_t educated_guess = filedata_begin + (file_length - filedata_begin) * (frame - start_frame) / asset->video_length - READ_SIZE/2;
01143
01144 if (educated_guess > file_length - READ_SIZE)
01145 educated_guess = file_length - READ_SIZE;
01146 if (educated_guess < filedata_begin)
01147 educated_guess = filedata_begin;
01148
01149
01150 read_buffer_at(stream, sw, READ_SIZE, educated_guess);
01151 ogg_sync_and_get_next_page(sw, serialno, og);
01152 int64_t pageend_frame;
01153 int read_back = 0;
01154
01155 while ((pageend_frame = ogg_page_granulepos(og)) == -1)
01156 {
01157 if (ogg_get_next_page(sw, serialno, og) == 0)
01158 {
01159 read_back = 1;
01160 break;
01161 }
01162 }
01163 pageend_frame = theora_granule_frame(&tf->td, ogg_page_granulepos(og));
01164
01165
01166
01167
01168
01169 int64_t start_frame = 0;
01170
01171
01172 int discard_packets = 0;
01173 int missp = 0;
01174 int missm = 0;
01175 if (pageend_frame <= frame)
01176 {
01177
01178 while (pageend_frame < frame)
01179 {
01180 do {
01181 ogg_get_next_page(sw, serialno, og);
01182 } while (ogg_page_packets(og) == 0);
01183 pageend_frame = theora_granule_frame(&tf->td, ogg_page_granulepos(og));
01184 missp++;
01185 }
01186
01187 if (ogg_page_continued(og) && pageend_frame - ogg_page_packets(og) == frame - 1)
01188 {
01189 do {
01190 ogg_get_prev_page(sw, serialno, og);
01191 } while (ogg_page_packets(og) == 0 && ogg_page_continued(og));
01192 }
01193 pageend_frame = theora_granule_frame(&tf->td, ogg_page_granulepos(og));
01194 } else
01195 {
01196
01197 int64_t first_frame_on_page = theora_granule_frame(&tf->td, ogg_page_granulepos(og)) - ogg_page_packets(og) + 2;
01198 if (!ogg_page_continued(og))
01199 first_frame_on_page--;
01200 while (first_frame_on_page > frame)
01201 {
01202
01203 do {
01204 ogg_get_prev_page(sw, serialno, og);
01205 } while (ogg_page_packets(og) == 0 && ogg_page_continued(og));
01206 missm++;
01207
01208 first_frame_on_page = theora_granule_frame(&tf->td, ogg_page_granulepos(og)) - ogg_page_packets(og) + 2;
01209 if (!ogg_page_continued(og))
01210 first_frame_on_page--;
01211 }
01212 }
01213
01214
01215 return 1;
01216 }
01217
01218
01219 int FileOGG::ogg_seek_to_keyframe(sync_window_t *sw, long serialno, int64_t frame, int64_t *keyframe_number)
01220 {
01221 ogg_page og;
01222 ogg_packet op;
01223
01224 if (!ogg_get_page_of_frame(sw, serialno, &og, frame))
01225 {
01226 eprintf("Seeking to frame failed\n");
01227 return 0;
01228 }
01229
01230
01231
01232
01233 int64_t granulepos, iframe, pframe;
01234 granulepos = ogg_page_granulepos(&og);
01235 iframe = granulepos >> theora_keyframe_granule_shift;
01236 pframe = granulepos - (iframe << theora_keyframe_granule_shift);
01237
01238 if (granulepos != -1 && iframe <= frame)
01239 {
01240
01241 } else
01242 {
01243
01244 do {
01245 ogg_get_prev_page(sw, serialno, &og);
01246 } while (ogg_page_packets(&og) == 0);
01247
01248 granulepos = ogg_page_granulepos(&og);
01249 iframe = granulepos >> theora_keyframe_granule_shift;
01250 pframe = granulepos - (iframe << theora_keyframe_granule_shift);
01251 }
01252 int64_t first_frame_on_page = theora_granule_frame(&tf->td, ogg_page_granulepos(&og)) - ogg_page_packets(&og) + 2;
01253 if (!ogg_page_continued(&og))
01254 first_frame_on_page--;
01255 if (first_frame_on_page <= iframe)
01256 {
01257
01258 } else
01259 {
01260
01261 if (!ogg_get_page_of_frame(sw, serialno, &og, iframe))
01262 {
01263 eprintf("Seeking to frame failed\n");
01264 return 0;
01265 }
01266 }
01267
01268 ogg_stream_reset(&tf->to);
01269 ogg_stream_pagein(&tf->to, &og);
01270
01271
01272 int numread = iframe - (theora_granule_frame(&tf->td, ogg_page_granulepos(&og)) - ogg_page_packets(&og)) - 1;
01273 if (ogg_page_continued(&og))
01274 numread--;
01275
01276
01277 while (numread > 0)
01278 {
01279 while (ogg_stream_packetpeek(&tf->to, NULL) != 1)
01280 {
01281 if (!ogg_get_next_page(sw, serialno, &og))
01282 {
01283 eprintf("Cannot find next page while seeking\n");
01284 return 0;
01285 }
01286 ogg_stream_pagein(&tf->to, &og);
01287 }
01288 ogg_stream_packetout(&tf->to, &op);
01289 numread --;
01290 }
01291 *keyframe_number = iframe;
01292 return 1;
01293 }
01294
01295
01296 int FileOGG::check_sig(Asset *asset)
01297 {
01298
01299 FILE *fd = fopen(asset->path, "rb");
01300
01301
01302 fseek(fd, 0, SEEK_SET);
01303 char data[4];
01304
01305 fread(data, 4, 1, fd);
01306
01307 if(data[0] == 'O' &&
01308 data[1] == 'g' &&
01309 data[2] == 'g' &&
01310 data[3] == 'S')
01311 {
01312
01313 fclose(fd);
01314
01315
01316 return 1;
01317 }
01318
01319 fclose(fd);
01320
01321 return 0;
01322
01323 }
01324
01325 int FileOGG::close_file()
01326 {
01327
01328 if (wr)
01329 {
01330 if (final_write)
01331 {
01332 if (asset->audio_data)
01333 write_samples_vorbis(0, 0, 1);
01334 if (asset->video_data)
01335 write_frames_theora(0, 1, 1);
01336 }
01337 flush_ogg(1);
01338
01339 if (asset->audio_data)
01340 {
01341 vorbis_block_clear (&tf->vb);
01342 vorbis_dsp_clear (&tf->vd);
01343 vorbis_info_clear (&tf->vi);
01344 ogg_stream_clear (&tf->vo);
01345 }
01346 if (asset->video_data)
01347 {
01348 theora_info_clear (&tf->ti);
01349 ogg_stream_clear (&tf->to);
01350 theora_clear (&tf->td);
01351 }
01352
01353 if (stream) fclose(stream);
01354 stream = 0;
01355 } else if (rd)
01356 {
01357 if (asset->audio_data)
01358 {
01359 vorbis_block_clear (&tf->vb);
01360 vorbis_dsp_clear (&tf->vd);
01361 vorbis_comment_clear (&tf->vc);
01362 vorbis_info_clear (&tf->vi);
01363 ogg_stream_clear (&tf->vo);
01364 }
01365 theora_comment_clear(&tf->tc);
01366 if (asset->video_data)
01367 {
01368 theora_info_clear (&tf->ti);
01369 theora_comment_clear (&tf->tc);
01370 theora_clear (&tf->td);
01371 ogg_stream_clear (&tf->to);
01372 }
01373
01374
01375 if (stream) fclose(stream);
01376 stream = 0;
01377
01378 }
01379 }
01380
01381 int FileOGG::close_file_derived()
01382 {
01383
01384 if (stream) fclose(stream);
01385 stream = 0;
01386 }
01387
01388 int64_t FileOGG::get_video_position()
01389 {
01390
01391 return next_frame_position - start_frame;
01392 }
01393
01394 int64_t FileOGG::get_audio_position()
01395 {
01396 return next_sample_position - start_sample;
01397 }
01398
01399 int FileOGG::set_video_position(int64_t x)
01400 {
01401
01402
01403
01404 next_frame_position = x + start_frame;
01405 return 1;
01406 }
01407
01408
01409 int FileOGG::colormodel_supported(int colormodel)
01410 {
01411
01412
01413 if (colormodel == BC_YUV420P)
01414 return BC_YUV420P;
01415 else
01416 return colormodel;
01417 }
01418 int FileOGG::get_best_colormodel(Asset *asset, int driver)
01419 {
01420
01421 return BC_YUV420P;
01422 }
01423
01424
01425 int FileOGG::read_frame(VFrame *frame)
01426 {
01427
01428 if(!stream) return 1;
01429
01430
01431
01432 int decode_frames = 0;
01433 int expect_keyframe = 0;
01434 if (ogg_frame_position >= 0 &&
01435 next_frame_position >= ogg_frame_position &&
01436 next_frame_position - ogg_frame_position < 32)
01437 {
01438 decode_frames = next_frame_position - ogg_frame_position;
01439 } else
01440 if (next_frame_position != ogg_frame_position)
01441 {
01442 if (!ogg_seek_to_keyframe(tf->videosync, tf->to.serialno, next_frame_position, &ogg_frame_position))
01443 {
01444 eprintf("Error while seeking to frame's keyframe (frame: %lli, keyframe: %lli)\n", next_frame_position, ogg_frame_position);
01445 return 1;
01446 }
01447
01448
01449 decode_frames = next_frame_position - ogg_frame_position + 1;
01450 ogg_frame_position --;
01451 if (decode_frames <= 0)
01452 {
01453 eprintf("Error while seeking to keyframe, wrong keyframe number (frame: %lli, keyframe: %lli)\n", next_frame_position, ogg_frame_position);
01454 return 1;
01455
01456 }
01457 expect_keyframe = 1;
01458 }
01459
01460
01461
01462
01463 while (decode_frames > 0)
01464 {
01465 ogg_page og;
01466 ogg_packet op;
01467 while (ogg_stream_packetpeek(&tf->to, NULL) != 1)
01468 {
01469 if (!ogg_get_next_page(tf->videosync, tf->to.serialno, &og))
01470 {
01471 eprintf("Cannot find next page while seeking\n");
01472 return 1;
01473 }
01474 ogg_stream_pagein(&tf->to, &og);
01475 }
01476 ogg_stream_packetout(&tf->to, &op);
01477 if (expect_keyframe && !theora_packet_iskeyframe(&op))
01478 {
01479 eprintf("Expecting a keyframe, but didn't get it\n");
01480
01481 }
01482 expect_keyframe = 0;
01483
01484
01485 theora_decode_packetin(&tf->td, &op);
01486
01487 decode_frames --;
01488 ogg_frame_position ++;
01489 }
01490 {
01491 yuv_buffer yuv;
01492 int ret = theora_decode_YUVout (&tf->td, &yuv);
01493 if (ret)
01494 {
01495 eprintf("theora_decode_YUVout() failed with code %i\n", ret);
01496 }
01497
01498
01499
01500
01501
01502
01503
01504 VFrame *temp_frame = new VFrame(yuv.y,
01505 0,
01506 yuv.u - yuv.y,
01507 yuv.v - yuv.y,
01508 - yuv.y_stride,
01509 yuv.y_height,
01510 BC_YUV420P,
01511 - yuv.y_stride);
01512
01513
01514 cmodel_transfer(frame->get_rows(),
01515 temp_frame->get_rows(),
01516 frame->get_y(),
01517 frame->get_u(),
01518 frame->get_v(),
01519 temp_frame->get_y(),
01520 temp_frame->get_u(),
01521 temp_frame->get_v(),
01522 0,
01523 0,
01524 yuv.y_width,
01525 yuv.y_height,
01526 0,
01527 0,
01528 yuv.y_width,
01529 yuv.y_height,
01530 BC_YUV420P,
01531 frame->get_color_model(),
01532 0,
01533 -temp_frame->get_w(),
01534 frame->get_w());
01535 delete temp_frame;
01536 }
01537
01538 next_frame_position ++;
01539
01540 return 0;
01541 }
01542
01543
01544
01545 int FileOGG::ogg_decode_more_samples(sync_window_t *sw, long serialno)
01546 {
01547 ogg_page og;
01548 ogg_packet op;
01549 int done = 0;
01550 while (!done)
01551 {
01552 while (ogg_stream_packetpeek(&tf->vo, NULL) != 1)
01553 {
01554 if (!ogg_get_next_page(sw, serialno, &og))
01555 {
01556 eprintf("Cannot find next page while trying to decode more samples\n");
01557 return 0;
01558 }
01559 ogg_stream_pagein(&tf->vo, &og);
01560 }
01561 ogg_stream_packetout(&tf->vo, &op);
01562 if(!vorbis_synthesis(&tf->vb, &op))
01563 {
01564 done = 1;
01565 vorbis_synthesis_blockin(&tf->vd, &tf->vb);
01566 }
01567 }
01568 return 1;
01569 }
01570
01571 int FileOGG::set_audio_position(int64_t x)
01572 {
01573 next_sample_position = x + start_sample;
01574 return 0;
01575 }
01576
01577 int FileOGG::move_history(int from, int to, int len)
01578 {
01579 for(int i = 0; i < asset->channels; i++)
01580 memmove(pcm_history[i] + to, pcm_history[i] + from, sizeof(float) * len);
01581 history_start = history_start + from - to;
01582 return 0;
01583 }
01584
01585 int FileOGG::read_samples(double *buffer, int64_t len)
01586 {
01587 float **vorbis_buffer;
01588 if (len <= 0)
01589 return 0;
01590
01591
01592
01593
01594 if(len > HISTORY_MAX)
01595 {
01596 eprintf("max samples=%d\n", HISTORY_MAX);
01597 return 1;
01598 }
01599
01600 if(!pcm_history)
01601 {
01602 pcm_history = new float*[asset->channels];
01603 for(int i = 0; i < asset->channels; i++)
01604 pcm_history[i] = new float[HISTORY_MAX];
01605 history_start = -100000000;
01606 history_size = 0;
01607 }
01608
01609 int64_t hole_start = -1;
01610 int64_t hole_len = -1;
01611 int64_t hole_absstart = -1;
01612 int64_t hole_fill = 0;
01613
01614 if (history_start < next_sample_position && history_start + history_size > next_sample_position && history_start + history_size < next_sample_position + len)
01615 {
01616
01617 hole_fill = 1;
01618 hole_start = history_start + history_size - next_sample_position;
01619 hole_len = history_size - hole_start;
01620 hole_absstart = next_sample_position + hole_start;
01621 move_history(next_sample_position - history_start,
01622 0,
01623 hole_start);
01624
01625 } else
01626 if (next_sample_position < history_start && history_start < next_sample_position + len)
01627 {
01628
01629 hole_fill = 1;
01630 hole_start = 0;
01631 hole_len = history_start - next_sample_position;
01632 hole_absstart = next_sample_position;
01633
01634
01635
01636
01637 move_history(0,
01638 history_start - next_sample_position,
01639 history_size - history_start + next_sample_position);
01640
01641 } else
01642 if (next_sample_position >= history_start + history_size || next_sample_position + len <= history_start)
01643 {
01644
01645 hole_fill = 1;
01646 hole_start = 0;
01647 hole_len = HISTORY_MAX;
01648 hole_absstart = next_sample_position;
01649 history_start = hole_absstart;
01650 history_size = hole_len;
01651 }
01652
01653 if (hole_fill)
01654 {
01655 if (hole_start < 0 || hole_len <= 0 || hole_absstart < 0)
01656 {
01657 eprintf("Error at finding out which range to read from file\n");
01658 return 1;
01659 }
01660
01661 if (hole_absstart + hole_len > asset->audio_length + start_sample)
01662 {
01663 hole_len = asset->audio_length + start_sample - hole_absstart;
01664 history_size = asset->audio_length + start_sample - history_start;
01665 } else
01666 {
01667 history_size = HISTORY_MAX;
01668 }
01669
01670
01671
01672
01673 int64_t samples_read = 0;
01674 if (ogg_sample_position != hole_absstart)
01675 {
01676 ogg_sample_position = hole_absstart;
01677 if (!ogg_seek_to_sample(tf->audiosync, tf->vo.serialno, ogg_sample_position))
01678 {
01679 eprintf("Error while seeking to sample\n");
01680 return 1;
01681 }
01682 }
01683
01684 int64_t samples_to_read = hole_len;
01685 while (samples_read < hole_len)
01686 {
01687 int64_t waiting_samples = vorbis_synthesis_pcmout(&tf->vd, &vorbis_buffer);
01688 int64_t takeout_samples;
01689 if (waiting_samples > samples_to_read - samples_read)
01690 takeout_samples = samples_to_read - samples_read;
01691 else
01692 takeout_samples = waiting_samples;
01693
01694 int i, j;
01695
01696 for(int i = 0; i < asset->channels; i++)
01697 {
01698 float *input = vorbis_buffer[i];
01699 float *output = pcm_history[i] + hole_start;
01700
01701 for(int j = 0; j < takeout_samples ; j++)
01702 {
01703 output[j] = input[j];
01704 }
01705 }
01706
01707 vorbis_synthesis_read(&tf->vd, takeout_samples);
01708 samples_read += takeout_samples;
01709 ogg_sample_position += takeout_samples;
01710 hole_start += takeout_samples;
01711
01712 if (samples_read < hole_len)
01713 if (!ogg_decode_more_samples(tf->audiosync, tf->vo.serialno))
01714 {
01715 ogg_sample_position = -1;
01716 return 1;
01717 }
01718
01719
01720 }
01721 }
01722
01723
01724 if (next_sample_position < history_start || next_sample_position + len > history_start + history_size)
01725 {
01726 eprintf("History not aligned properly \n\tnext_sample_position: %lli, length: %i\n\thistory_start: %lli, length: %i\n", next_sample_position, len, history_start, history_size);
01727 return 1;
01728 }
01729 float *input = pcm_history[file->current_channel] + next_sample_position - history_start;
01730 for (int i = 0; i < len; i++)
01731 buffer[i] = input[i];
01732
01733 next_sample_position += len;
01734 return 0;
01735 }
01736
01737
01738 int FileOGG::write_audio_page()
01739 {
01740 int ret;
01741
01742 ret = fwrite(tf->apage, 1, tf->apage_len, stream);
01743 if(ret < tf->apage_len)
01744 {
01745 eprintf("error writing audio page\n");
01746 }
01747 tf->apage_valid = 0;
01748 tf->a_pkg -= ogg_page_packets((ogg_page *)&tf->apage);
01749 return ret;
01750 }
01751
01752 int FileOGG::write_video_page()
01753 {
01754 int ret;
01755
01756 ret = fwrite(tf->vpage, 1, tf->vpage_len, stream);
01757 if(ret < tf->vpage_len)
01758 {
01759 eprintf("error writing video page\n");
01760 }
01761 tf->vpage_valid = 0;
01762 tf->v_pkg -= ogg_page_packets((ogg_page *)&tf->vpage);
01763 return ret;
01764 }
01765
01766 void FileOGG::flush_ogg (int e_o_s)
01767 {
01768 int len;
01769 ogg_page og;
01770
01771 flush_lock->lock();
01772
01773 while(1) {
01774
01775 if(asset->video_data && !tf->vpage_valid) {
01776
01777
01778 int v_next=0;
01779 if(tf->v_pkg>22 && ogg_stream_flush(&tf->to, &og) > 0) {
01780 v_next=1;
01781 }
01782 else if(ogg_stream_pageout(&tf->to, &og) > 0) {
01783 v_next=1;
01784 }
01785 if(v_next) {
01786 len = og.header_len + og.body_len;
01787 if(tf->vpage_buffer_length < len) {
01788 tf->vpage = (unsigned char *)realloc(tf->vpage, len);
01789 tf->vpage_buffer_length = len;
01790 }
01791 tf->vpage_len = len;
01792 memcpy(tf->vpage, og.header, og.header_len);
01793 memcpy(tf->vpage+og.header_len , og.body, og.body_len);
01794
01795 tf->vpage_valid = 1;
01796 tf->videotime = theora_granule_time (&tf->td,
01797 ogg_page_granulepos(&og));
01798 }
01799 }
01800 if(asset->audio_data && !tf->apage_valid) {
01801
01802
01803 int a_next=0;
01804 if(tf->a_pkg>22 && ogg_stream_flush(&tf->vo, &og) > 0) {
01805 a_next=1;
01806 }
01807 else if(ogg_stream_pageout(&tf->vo, &og) > 0) {
01808 a_next=1;
01809 }
01810 if(a_next) {
01811 len = og.header_len + og.body_len;
01812 if(tf->apage_buffer_length < len) {
01813 tf->apage = (unsigned char *)realloc(tf->apage, len);
01814 tf->apage_buffer_length = len;
01815 }
01816 tf->apage_len = len;
01817 memcpy(tf->apage, og.header, og.header_len);
01818 memcpy(tf->apage+og.header_len , og.body, og.body_len);
01819
01820 tf->apage_valid = 1;
01821 tf->audiotime= vorbis_granule_time (&tf->vd,
01822 ogg_page_granulepos(&og));
01823 }
01824 }
01825
01826 if(!asset->audio_data && tf->vpage_valid) {
01827 write_video_page();
01828 }
01829 else if(!asset->video_data && tf->apage_valid) {
01830 write_audio_page();
01831 }
01832
01833
01834
01835
01836 else if(tf->vpage_valid && tf->apage_valid) {
01837
01838 if(tf->videotime <= tf->audiotime)
01839 write_video_page();
01840 else
01841 write_audio_page();
01842 }
01843 else if(e_o_s && tf->vpage_valid) {
01844 write_video_page();
01845 }
01846 else if(e_o_s && tf->apage_valid) {
01847 write_audio_page();
01848 }
01849 else {
01850 break;
01851 }
01852 }
01853 flush_lock->unlock();
01854 }
01855
01856
01857 int FileOGG::write_samples_vorbis(double **buffer, int64_t len, int e_o_s)
01858 {
01859 int i,j, count = 0;
01860 float **vorbis_buffer;
01861 static int samples = 0;
01862 samples += len;
01863 if(e_o_s)
01864 {
01865 vorbis_analysis_wrote (&tf->vd, 0);
01866 } else
01867 {
01868 vorbis_buffer = vorbis_analysis_buffer (&tf->vd, len);
01869
01870 for(i = 0; i<asset->channels; i++)
01871 {
01872 for (j = 0; j < len; j++)
01873 {
01874 vorbis_buffer[i][j] = buffer[i][j];
01875 }
01876 }
01877 vorbis_analysis_wrote (&tf->vd, len);
01878 }
01879 while(vorbis_analysis_blockout (&tf->vd, &tf->vb) == 1)
01880 {
01881
01882 vorbis_analysis (&tf->vb, NULL);
01883 vorbis_bitrate_addblock (&tf->vb);
01884
01885
01886 while (vorbis_bitrate_flushpacket (&tf->vd, &tf->op))
01887 {
01888 flush_lock->lock();
01889 ogg_stream_packetin (&tf->vo, &tf->op);
01890 tf->a_pkg++;
01891 flush_lock->unlock();
01892 }
01893
01894 }
01895 flush_ogg(0);
01896 return 0;
01897
01898
01899 }
01900
01901 int FileOGG::write_samples(double **buffer, int64_t len)
01902 {
01903 if (len > 0)
01904 return write_samples_vorbis(buffer, len, 0);
01905 return 0;
01906 }
01907
01908 int FileOGG::write_frames_theora(VFrame ***frames, int len, int e_o_s)
01909 {
01910
01911
01912
01913 int i, j, result = 0;
01914
01915 if(!stream) return 0;
01916
01917
01918 for(j = 0; j < len && !result; j++)
01919 {
01920 if (temp_frame)
01921 {
01922 yuv_buffer yuv;
01923 yuv.y_width = tf->ti.width;
01924 yuv.y_height = tf->ti.height;
01925 yuv.y_stride = temp_frame->get_bytes_per_line();
01926
01927 yuv.uv_width = tf->ti.width / 2;
01928 yuv.uv_height = tf->ti.height / 2;
01929 yuv.uv_stride = temp_frame->get_bytes_per_line() /2;
01930
01931 yuv.y = temp_frame->get_y();
01932 yuv.u = temp_frame->get_u();
01933 yuv.v = temp_frame->get_v();
01934 int ret = theora_encode_YUVin (&tf->td, &yuv);
01935 if (ret)
01936 {
01937 eprintf("theora_encode_YUVin() failed with code %i\nyuv_buffer: y_width: %i, y_height: %i, y_stride: %i, uv_width: %i, uv_height: %i, uv_stride: %i\n",
01938 ret,
01939 yuv.y_width,
01940 yuv.y_height,
01941 yuv.y_stride,
01942 yuv.uv_width,
01943 yuv.uv_height,
01944 yuv.uv_stride);
01945 }
01946
01947 while(theora_encode_packetout (&tf->td, e_o_s, &tf->op)) {
01948 flush_lock->lock();
01949 ogg_stream_packetin (&tf->to, &tf->op);
01950 tf->v_pkg++;
01951 flush_lock->unlock();
01952 }
01953 flush_ogg(0);
01954 }
01955
01956 if (e_o_s)
01957 break;
01958
01959 if (!temp_frame)
01960 {
01961 temp_frame = new VFrame (0,
01962 tf->ti.width,
01963 tf->ti.height,
01964 BC_YUV420P);
01965 }
01966 VFrame *frame = frames[0][j];
01967 int in_color_model = frame->get_color_model();
01968 if (in_color_model == BC_YUV422P &&
01969 temp_frame->get_w() == frame->get_w() &&
01970 temp_frame->get_h() == frame->get_h() &&
01971 temp_frame->get_bytes_per_line() == frame->get_bytes_per_line())
01972 {
01973 temp_frame->copy_from(frame);
01974 } else
01975 {
01976
01977 cmodel_transfer(temp_frame->get_rows(),
01978 frame->get_rows(),
01979 temp_frame->get_y(),
01980 temp_frame->get_u(),
01981 temp_frame->get_v(),
01982 frame->get_y(),
01983 frame->get_u(),
01984 frame->get_v(),
01985 0,
01986 0,
01987 frame->get_w(),
01988 frame->get_h(),
01989 0,
01990 0,
01991 frame->get_w(),
01992 frame->get_h(),
01993 frame->get_color_model(),
01994 BC_YUV420P,
01995 0,
01996 frame->get_w(),
01997 temp_frame->get_w());
01998
01999 }
02000 }
02001
02002 return 0;
02003 }
02004
02005
02006 int FileOGG::write_frames(VFrame ***frames, int len)
02007 {
02008
02009 return write_frames_theora(frames, len, 0);
02010 }
02011
02012 OGGConfigAudio::OGGConfigAudio(BC_WindowBase *parent_window, Asset *asset)
02013 : BC_Window(PROGRAM_NAME ": Audio Compression",
02014 parent_window->get_abs_cursor_x(1),
02015 parent_window->get_abs_cursor_y(1),
02016 350,
02017 250)
02018 {
02019 this->parent_window = parent_window;
02020 this->asset = asset;
02021 }
02022
02023 OGGConfigAudio::~OGGConfigAudio()
02024 {
02025
02026 }
02027
02028 int OGGConfigAudio::create_objects()
02029 {
02030
02031
02032 int x = 10, y = 10;
02033 int x1 = 150;
02034 char string[BCTEXTLEN];
02035
02036 add_tool(fixed_bitrate = new OGGVorbisFixedBitrate(x, y, this));
02037 add_tool(variable_bitrate = new OGGVorbisVariableBitrate(x1, y, this));
02038
02039 y += 30;
02040 sprintf(string, "%d", asset->vorbis_min_bitrate);
02041 add_tool(new BC_Title(x, y, _("Min bitrate:")));
02042 add_tool(new OGGVorbisMinBitrate(x1, y, this, string));
02043
02044 y += 30;
02045 add_tool(new BC_Title(x, y, _("Avg bitrate:")));
02046 sprintf(string, "%d", asset->vorbis_bitrate);
02047 add_tool(new OGGVorbisAvgBitrate(x1, y, this, string));
02048
02049 y += 30;
02050 add_tool(new BC_Title(x, y, _("Max bitrate:")));
02051 sprintf(string, "%d", asset->vorbis_max_bitrate);
02052 add_tool(new OGGVorbisMaxBitrate(x1, y, this, string));
02053
02054
02055 add_subwindow(new BC_OKButton(this));
02056 show_window();
02057 flush();
02058 return 0;
02059
02060
02061
02062 }
02063
02064 int OGGConfigAudio::close_event()
02065 {
02066 set_done(0);
02067 return 1;
02068 }
02069
02070 OGGVorbisFixedBitrate::OGGVorbisFixedBitrate(int x, int y, OGGConfigAudio *gui)
02071 : BC_Radial(x, y, !gui->asset->vorbis_vbr, _("Average bitrate"))
02072 {
02073 this->gui = gui;
02074 }
02075 int OGGVorbisFixedBitrate::handle_event()
02076 {
02077 gui->asset->vorbis_vbr = 0;
02078 gui->variable_bitrate->update(0);
02079 return 1;
02080 }
02081
02082 OGGVorbisVariableBitrate::OGGVorbisVariableBitrate(int x, int y, OGGConfigAudio *gui)
02083 : BC_Radial(x, y, gui->asset->vorbis_vbr, _("Variable bitrate"))
02084 {
02085 this->gui = gui;
02086 }
02087 int OGGVorbisVariableBitrate::handle_event()
02088 {
02089 gui->asset->vorbis_vbr = 1;
02090 gui->fixed_bitrate->update(0);
02091 return 1;
02092 }
02093
02094
02095 OGGVorbisMinBitrate::OGGVorbisMinBitrate(int x,
02096 int y,
02097 OGGConfigAudio *gui,
02098 char *text)
02099 : BC_TextBox(x, y, 180, 1, text)
02100 {
02101 this->gui = gui;
02102 }
02103 int OGGVorbisMinBitrate::handle_event()
02104 {
02105 gui->asset->vorbis_min_bitrate = atol(get_text());
02106 return 1;
02107 }
02108
02109
02110
02111 OGGVorbisMaxBitrate::OGGVorbisMaxBitrate(int x,
02112 int y,
02113 OGGConfigAudio *gui,
02114 char *text)
02115 : BC_TextBox(x, y, 180, 1, text)
02116 {
02117 this->gui = gui;
02118 }
02119 int OGGVorbisMaxBitrate::handle_event()
02120 {
02121 gui->asset->vorbis_max_bitrate = atol(get_text());
02122 return 1;
02123 }
02124
02125
02126
02127 OGGVorbisAvgBitrate::OGGVorbisAvgBitrate(int x, int y, OGGConfigAudio *gui, char *text)
02128 : BC_TextBox(x, y, 180, 1, text)
02129 {
02130 this->gui = gui;
02131 }
02132 int OGGVorbisAvgBitrate::handle_event()
02133 {
02134 gui->asset->vorbis_bitrate = atol(get_text());
02135 return 1;
02136 }
02137
02138
02139
02140
02141
02142 OGGConfigVideo::OGGConfigVideo(BC_WindowBase *parent_window, Asset *asset)
02143 : BC_Window(PROGRAM_NAME ": Video Compression",
02144 parent_window->get_abs_cursor_x(1),
02145 parent_window->get_abs_cursor_y(1),
02146 450,
02147 220)
02148 {
02149 this->parent_window = parent_window;
02150 this->asset = asset;
02151 }
02152
02153 OGGConfigVideo::~OGGConfigVideo()
02154 {
02155
02156 }
02157
02158 int OGGConfigVideo::create_objects()
02159 {
02160
02161 int x = 10, y = 10;
02162 int x1 = x + 150;
02163 int x2 = x + 300;
02164
02165 add_subwindow(new BC_Title(x, y + 5, _("Bitrate:")));
02166 add_subwindow(new OGGTheoraBitrate(x1, y, this));
02167 add_subwindow(fixed_bitrate = new OGGTheoraFixedBitrate(x2, y, this));
02168 y += 30;
02169
02170 add_subwindow(new BC_Title(x, y, _("Quality:")));
02171 add_subwindow(new BC_ISlider(x + 80,
02172 y,
02173 0,
02174 200,
02175 200,
02176 0,
02177 63,
02178 asset->theora_quality,
02179 0,
02180 0,
02181 &asset->theora_quality));
02182
02183
02184 add_subwindow(fixed_quality = new OGGTheoraFixedQuality(x2, y, this));
02185 y += 30;
02186
02187 add_subwindow(new BC_Title(x, y, _("Keyframe frequency:")));
02188 OGGTheoraKeyframeFrequency *keyframe_frequency =
02189 new OGGTheoraKeyframeFrequency(x1 + 60, y, this);
02190 keyframe_frequency->create_objects();
02191 y += 30;
02192
02193 add_subwindow(new BC_Title(x, y, _("Keyframe force frequency:")));
02194 OGGTheoraKeyframeForceFrequency *keyframe_force_frequency =
02195 new OGGTheoraKeyframeForceFrequency(x1 + 60, y, this);
02196 keyframe_force_frequency->create_objects();
02197 y += 30;
02198
02199 add_subwindow(new BC_Title(x, y, _("Sharpness:")));
02200 OGGTheoraSharpness *sharpness =
02201 new OGGTheoraSharpness(x1 + 60, y, this);
02202 sharpness->create_objects();
02203 y += 30;
02204
02205
02206 add_subwindow(new BC_OKButton(this));
02207 return 0;
02208 }
02209
02210
02211
02212
02213 int OGGConfigVideo::close_event()
02214 {
02215 set_done(0);
02216 return 1;
02217 }
02218
02219 OGGTheoraBitrate::OGGTheoraBitrate(int x, int y, OGGConfigVideo *gui)
02220 : BC_TextBox(x, y, 100, 1, gui->asset->theora_bitrate)
02221 {
02222 this->gui = gui;
02223 }
02224
02225
02226 int OGGTheoraBitrate::handle_event()
02227 {
02228
02229 gui->asset->theora_bitrate = atol(get_text());
02230 return 1;
02231 };
02232
02233
02234
02235
02236 OGGTheoraFixedBitrate::OGGTheoraFixedBitrate(int x, int y, OGGConfigVideo *gui)
02237 : BC_Radial(x, y, gui->asset->theora_fix_bitrate, _("Fixed bitrate"))
02238 {
02239 this->gui = gui;
02240 }
02241
02242 int OGGTheoraFixedBitrate::handle_event()
02243 {
02244 update(1);
02245 gui->asset->theora_fix_bitrate = 1;
02246 gui->fixed_quality->update(0);
02247 return 1;
02248 };
02249
02250 OGGTheoraFixedQuality::OGGTheoraFixedQuality(int x, int y, OGGConfigVideo *gui)
02251 : BC_Radial(x, y, !gui->asset->theora_fix_bitrate, _("Fixed quality"))
02252 {
02253 this->gui = gui;
02254 }
02255
02256 int OGGTheoraFixedQuality::handle_event()
02257 {
02258 update(1);
02259 gui->asset->theora_fix_bitrate = 0;
02260 gui->fixed_bitrate->update(0);
02261 return 1;
02262 };
02263
02264 OGGTheoraKeyframeFrequency::OGGTheoraKeyframeFrequency(int x, int y, OGGConfigVideo *gui)
02265 : BC_TumbleTextBox(gui,
02266 (int64_t)gui->asset->theora_keyframe_frequency,
02267 (int64_t)1,
02268 (int64_t)500,
02269 x,
02270 y,
02271 40)
02272 {
02273 this->gui = gui;
02274 }
02275
02276 int OGGTheoraKeyframeFrequency::handle_event()
02277 {
02278 gui->asset->theora_keyframe_frequency = atol(get_text());
02279 return 1;
02280 }
02281
02282 OGGTheoraKeyframeForceFrequency::OGGTheoraKeyframeForceFrequency(int x, int y, OGGConfigVideo *gui)
02283 : BC_TumbleTextBox(gui,
02284 (int64_t)gui->asset->theora_keyframe_frequency,
02285 (int64_t)1,
02286 (int64_t)500,
02287 x,
02288 y,
02289 40)
02290 {
02291 this->gui = gui;
02292 }
02293
02294 int OGGTheoraKeyframeForceFrequency::handle_event()
02295 {
02296 gui->asset->theora_keyframe_frequency = atol(get_text());
02297 return 1;
02298 }
02299
02300
02301 OGGTheoraSharpness::OGGTheoraSharpness(int x, int y, OGGConfigVideo *gui)
02302 : BC_TumbleTextBox(gui,
02303 (int64_t)gui->asset->theora_sharpness,
02304 (int64_t)0,
02305 (int64_t)2,
02306 x,
02307 y,
02308 40)
02309 {
02310 this->gui = gui;
02311 }
02312
02313 int OGGTheoraSharpness::handle_event()
02314 {
02315 gui->asset->theora_sharpness = atol(get_text());
02316 return 1;
02317 }
02318
02319
02320 PackagingEngineOGG::PackagingEngineOGG()
02321 {
02322 packages = 0;
02323 default_asset = 0;
02324 }
02325
02326 PackagingEngineOGG::~PackagingEngineOGG()
02327 {
02328 if(packages)
02329 {
02330 for(int i = 0; i < total_packages; i++)
02331 delete packages[i];
02332 delete [] packages;
02333 }
02334 if (default_asset)
02335 delete default_asset;
02336 }
02337
02338
02339
02340 int PackagingEngineOGG::create_packages_single_farm(
02341 EDL *edl,
02342 Preferences *preferences,
02343 Asset *default_asset,
02344 double total_start,
02345 double total_end)
02346 {
02347 this->total_start = total_start;
02348 this->total_end = total_end;
02349 this->edl = edl;
02350
02351 this->preferences = preferences;
02352
02353
02354
02355 this->default_asset = new Asset(*default_asset);
02356
02357 audio_start = Units::to_int64(total_start * default_asset->sample_rate);
02358 video_start = Units::to_int64(total_start * default_asset->frame_rate);
02359 audio_position = audio_start;
02360 video_position = video_start;
02361 audio_end = Units::to_int64(total_end * default_asset->sample_rate);
02362 video_end = Units::to_int64(total_end * default_asset->frame_rate);
02363 current_package = 0;
02364
02365 double total_len = total_end - total_start;
02366
02367
02368 total_packages = 0;
02369 if (default_asset->audio_data)
02370 total_packages++;
02371 if (default_asset->video_data)
02372 total_packages += preferences->renderfarm_job_count;
02373
02374 packages = new RenderPackage*[total_packages];
02375
02376 int local_current_package = 0;
02377 if (default_asset->audio_data)
02378 {
02379 packages[local_current_package] = new RenderPackage;
02380 sprintf(packages[current_package]->path, "%s.audio", default_asset->path);
02381 local_current_package++;
02382 }
02383
02384 if (default_asset->video_data)
02385 {
02386 video_package_len = (total_len) / preferences->renderfarm_job_count;
02387 int current_number;
02388 int number_start;
02389 int total_digits;
02390
02391 Render::get_starting_number(default_asset->path,
02392 current_number,
02393 number_start,
02394 total_digits,
02395 3);
02396
02397 for(int i = 0; i < preferences->renderfarm_job_count; i++)
02398 {
02399 RenderPackage *package = packages[local_current_package] = new RenderPackage;
02400 Render::create_filename(package->path,
02401 default_asset->path,
02402 current_number,
02403 total_digits,
02404 number_start);
02405 current_number++;
02406 local_current_package++;
02407 }
02408 }
02409 }
02410
02411 RenderPackage* PackagingEngineOGG::get_package_single_farm(double frames_per_second,
02412 int client_number,
02413 int use_local_rate)
02414 {
02415
02416
02417 if (current_package == total_packages)
02418 return 0;
02419
02420 RenderPackage *result = 0;
02421 if (current_package == 0 && default_asset->audio_data)
02422 {
02423 result = packages[0];
02424 result->audio_start = audio_start;
02425 result->video_start = video_start;
02426 result->audio_end = audio_end;
02427 result->video_end = video_end;
02428 result->audio_do = 1;
02429 result->video_do = 0;
02430 } else if (default_asset->video_data)
02431 {
02432
02433 result = packages[current_package];
02434 result->audio_do = 0;
02435 result->video_do = 1;
02436
02437 result->audio_start = audio_position;
02438 result->video_start = video_position;
02439 result->audio_end = audio_position +
02440 Units::round(video_package_len * default_asset->sample_rate);
02441 result->video_end = video_position +
02442 Units::round(video_package_len * default_asset->frame_rate);
02443
02444
02445 if (current_package == total_packages -1 )
02446 {
02447 result->audio_end = audio_end;
02448 result->video_end = video_end;
02449 }
02450
02451 audio_position = result->audio_end;
02452 video_position = result->video_end;
02453
02454 }
02455
02456 current_package ++;
02457 return result;
02458
02459 }
02460
02461 void PackagingEngineOGG::get_package_paths(ArrayList<char*> *path_list)
02462 {
02463 for(int i = 0; i < total_packages; i++)
02464 {
02465 path_list->append(strdup(packages[i]->path));
02466 }
02467
02468 path_list->append(strdup(default_asset->path));
02469 path_list->set_free();
02470 }
02471
02472 int64_t PackagingEngineOGG::get_progress_max()
02473 {
02474 return Units::to_int64(default_asset->sample_rate *
02475 (total_end - total_start)) * 2+
02476 Units::to_int64(preferences->render_preroll *
02477 total_packages *
02478 default_asset->sample_rate);
02479 }
02480
02481 int PackagingEngineOGG::packages_are_done()
02482 {
02483
02484
02485
02486
02487
02488
02489
02490 Asset *video_asset, *audio_asset;
02491 File *audio_file_gen, *video_file_gen;
02492 FileOGG *video_file, *audio_file;
02493 ogg_stream_state audio_in_stream, video_in_stream;
02494
02495 int local_current_package = 0;
02496 if (default_asset->audio_data)
02497 {
02498 audio_asset = new Asset(packages[local_current_package]->path);
02499 local_current_package++;
02500
02501 audio_file_gen = new File();
02502 audio_file_gen->open_file(preferences,
02503 audio_asset,
02504 1,
02505 0,
02506 0,
02507 0);
02508 audio_file = (FileOGG*) audio_file_gen->file;
02509 ogg_stream_init(&audio_in_stream, audio_file->tf->vo.serialno);
02510 audio_file->ogg_seek_to_databegin(audio_file->tf->audiosync, audio_file->tf->vo.serialno);
02511 }
02512
02513 if (default_asset->video_data)
02514 {
02515 video_asset = new Asset(packages[local_current_package]->path);
02516 local_current_package++;
02517
02518 video_file_gen = new File();
02519 video_file_gen->open_file(preferences,
02520 video_asset,
02521 1,
02522 0,
02523 0,
02524 0);
02525 video_file = (FileOGG*) video_file_gen->file;
02526 ogg_stream_init(&video_in_stream, video_file->tf->to.serialno);
02527 video_file->ogg_seek_to_databegin(video_file->tf->videosync, video_file->tf->to.serialno);
02528 }
02529
02530
02531 File *output_file_gen = new File();
02532 output_file_gen->open_file(preferences,
02533 default_asset,
02534 0,
02535 1,
02536 default_asset->sample_rate,
02537 default_asset->frame_rate);
02538 FileOGG *output_file = (FileOGG*) output_file_gen->file;
02539
02540 ogg_page og;
02541 ogg_packet op;
02542
02543
02544 int audio_ready = default_asset->audio_data;
02545 int video_ready = default_asset->video_data;
02546 int64_t video_packetno = 1;
02547 int64_t audio_packetno = 1;
02548 int64_t frame_offset = 0;
02549 int64_t current_frame = 0;
02550 while ((default_asset->audio_data && audio_ready) || (default_asset->video_data && video_ready))
02551 {
02552 if (video_ready)
02553 {
02554 while (ogg_stream_packetpeek(&video_in_stream, NULL) != 1)
02555 {
02556 if (!video_file->ogg_get_next_page(video_file->tf->videosync, video_file->tf->to.serialno, &video_file->tf->videopage))
02557 {
02558
02559 if (local_current_package < total_packages)
02560 {
02561 frame_offset = current_frame +1;
02562 ogg_stream_clear(&video_in_stream);
02563 video_file_gen->close_file();
02564 delete video_file_gen;
02565 delete video_asset;
02566 video_asset = new Asset(packages[local_current_package]->path);
02567 local_current_package++;
02568
02569 video_file_gen = new File();
02570 video_file_gen->open_file(preferences,
02571 video_asset,
02572 1,
02573 0,
02574 0,
02575 0);
02576 video_file = (FileOGG*) video_file_gen->file;
02577 ogg_stream_init(&video_in_stream, video_file->tf->to.serialno);
02578 int64_t fp = 0;
02579 video_file->ogg_seek_to_databegin(video_file->tf->videosync, video_file->tf->to.serialno);
02580
02581 } else
02582 video_ready = 0;
02583 break;
02584 }
02585 ogg_stream_pagein(&video_in_stream, &video_file->tf->videopage);
02586 }
02587 while (ogg_stream_packetpeek(&video_in_stream, NULL) == 1)
02588 {
02589 ogg_stream_packetout(&video_in_stream, &op);
02590 if (local_current_package != total_packages)
02591 op.e_o_s = 0;
02592 if (video_packetno != 1)
02593 op.b_o_s = 0;
02594 else
02595 op.b_o_s = 1;
02596 op.packetno = video_packetno;
02597 video_packetno ++;
02598 int64_t granulepos = op.granulepos;
02599 if (granulepos != -1)
02600 {
02601
02602 int64_t rel_iframe = granulepos >> video_file->theora_keyframe_granule_shift;
02603 int64_t rel_pframe = granulepos - (rel_iframe << video_file->theora_keyframe_granule_shift);
02604 int64_t rel_current_frame = rel_iframe + rel_pframe;
02605 current_frame = frame_offset + rel_current_frame;
02606 int64_t abs_iframe = current_frame - rel_pframe;
02607
02608 op.granulepos = (abs_iframe << video_file->theora_keyframe_granule_shift) + rel_pframe;
02609
02610
02611
02612 }
02613 ogg_stream_packetin (&output_file->tf->to, &op);
02614 output_file->tf->v_pkg++;
02615 }
02616 }
02617 if (audio_ready)
02618 {
02619 while (ogg_stream_packetpeek(&audio_in_stream, NULL) != 1)
02620 {
02621 if (!audio_file->ogg_get_next_page(audio_file->tf->audiosync, audio_file->tf->vo.serialno, &audio_file->tf->audiopage))
02622 {
02623 audio_ready = 0;
02624 break;
02625 }
02626 ogg_stream_pagein(&audio_in_stream, &audio_file->tf->audiopage);
02627 }
02628 while (ogg_stream_packetpeek(&audio_in_stream, NULL) == 1)
02629 {
02630 ogg_stream_packetout(&audio_in_stream, &op);
02631 ogg_stream_packetin (&output_file->tf->vo, &op);
02632 audio_packetno++;
02633 output_file->tf->a_pkg++;
02634 }
02635 }
02636
02637 output_file->flush_ogg(0);
02638
02639
02640 }
02641
02642
02643
02644
02645
02646 output_file->final_write = 0;
02647
02648 if (default_asset->audio_data)
02649 {
02650 ogg_stream_clear(&audio_in_stream);
02651 audio_file_gen->close_file();
02652 delete audio_file_gen;
02653 delete audio_asset;
02654 }
02655 if (default_asset->video_data)
02656 {
02657 ogg_stream_clear(&video_in_stream);
02658 video_file_gen->close_file();
02659 delete video_file_gen;
02660 delete video_asset;
02661 }
02662
02663 output_file_gen->close_file();
02664 delete output_file_gen;
02665
02666
02667 for(int i = 0; i < total_packages; i++)
02668 unlink(packages[i]->path);
02669
02670 return 0;
02671 }
02672
02673
02674