00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00045 #include <time.h>
00046 #include <string.h>
00047 #include <locale.h>
00048
00049 #ifdef __WIN32__
00050 #include <io.h>
00051 #include <fcntl.h>
00052 #endif
00053
00054 #include "splt.h"
00055 #include "ogg.h"
00056 #include "ogg_utils.h"
00057 #include "ogg_silence.h"
00058 #include "ogg_new_stream_handler.h"
00059
00060 #define FIRST_GRANPOS 1
00061
00071
00072
00073
00074 splt_ogg_state *splt_ogg_info(FILE *in, splt_state *state, int *error);
00075 static void splt_ogg_clear_sync_in(splt_ogg_state *oggstate);
00076 static void splt_ogg_clear_sync_in_and_free(splt_ogg_state *oggstate);
00077
00078
00079
00080
00081 FILE *splt_ogg_open_file_read(splt_state *state, const char *filename, int *error)
00082 {
00083 FILE *file_input = NULL;
00084
00085 if (strcmp(filename,"o-") == 0)
00086 {
00087 file_input = stdin;
00088 #ifdef __WIN32__
00089 _setmode(fileno(file_input), _O_BINARY);
00090 #endif
00091 }
00092 else
00093 {
00094
00095 file_input = splt_io_fopen(filename, "rb");
00096 if (file_input == NULL)
00097 {
00098 splt_e_set_strerror_msg_with_data(state, filename);
00099 *error = SPLT_ERROR_CANNOT_OPEN_FILE;
00100 }
00101 }
00102
00103 return file_input;
00104 }
00105
00106
00107 void splt_ogg_get_info(splt_state *state, FILE *file_input, int *error)
00108 {
00109
00110 state->codec = splt_ogg_info(file_input, state, error);
00111
00112
00113 if ((*error < 0) || (state->codec == NULL))
00114 {
00115 return;
00116 }
00117 else
00118 {
00119
00120 if (! splt_o_messages_locked(state))
00121 {
00122 splt_ogg_state *oggstate = state->codec;
00123
00124 char ogg_infos[1024] = { '\0' };
00125 snprintf(ogg_infos, 1023,
00126 _(" info: Ogg Vorbis Stream - %ld - %ld Kb/s - %d channels"),
00127 oggstate->vd->vi->rate, oggstate->vd->vi->bitrate_nominal/1024,
00128 oggstate->vd->vi->channels);
00129
00130 char total_time[256] = { '\0' };
00131 int total_seconds = (int) splt_t_get_total_time(state) / 100;
00132 int minutes = total_seconds / 60;
00133 int seconds = total_seconds % 60;
00134 snprintf(total_time, 255, _(" - Total time: %dm.%02ds"), minutes, seconds%60);
00135
00136 splt_c_put_info_message_to_client(state, "%s%s\n", ogg_infos, total_time);
00137 }
00138 }
00139 }
00140
00141
00142 static void splt_ogg_v_free(splt_ogg_state *oggstate)
00143 {
00144 if (!oggstate)
00145 {
00146 return;
00147 }
00148
00149 if(oggstate->packets)
00150 {
00151 splt_ogg_free_packet(&oggstate->packets[0]);
00152 splt_ogg_free_packet(&oggstate->packets[1]);
00153 free(oggstate->packets);
00154 oggstate->packets = NULL;
00155 }
00156
00157 splt_ogg_free_oggstate_headers(oggstate);
00158
00159 splt_ogg_free_vorbis_comment(&oggstate->vc, oggstate->cloned_vorbis_comment);
00160 oggstate->cloned_vorbis_comment = 2;
00161
00162 if(oggstate->vb)
00163 {
00164 vorbis_block_clear(oggstate->vb);
00165 free(oggstate->vb);
00166 oggstate->vb = NULL;
00167 }
00168
00169 if(oggstate->vd)
00170 {
00171 vorbis_dsp_clear(oggstate->vd);
00172 free(oggstate->vd);
00173 oggstate->vd = NULL;
00174 }
00175
00176
00177 if(oggstate->stream_in && oggstate->in != stdin)
00178 {
00179 ogg_stream_clear(oggstate->stream_in);
00180 free(oggstate->stream_in);
00181 oggstate->stream_in = NULL;
00182 }
00183
00184 splt_ogg_clear_sync_in_and_free(oggstate);
00185
00186 if (oggstate->vi)
00187 {
00188 vorbis_info_clear(oggstate->vi);
00189 free(oggstate->vi);
00190 oggstate->vi = NULL;
00191 }
00192
00193 free(oggstate);
00194 oggstate = NULL;
00195 }
00196
00197 static void splt_ogg_clear_sync_in_and_free(splt_ogg_state *oggstate)
00198 {
00199 if (oggstate->sync_in)
00200 {
00201 ogg_sync_clear(oggstate->sync_in);
00202
00203 free(oggstate->sync_in);
00204 oggstate->sync_in = NULL;
00205 }
00206 }
00207
00208 static splt_ogg_state *splt_ogg_v_new(int *error)
00209 {
00210 splt_ogg_state *oggstate = NULL;
00211
00212 if ((oggstate = malloc(sizeof(splt_ogg_state)))==NULL)
00213 {
00214 goto error;
00215 }
00216 memset(oggstate, 0, sizeof(splt_ogg_state));
00217 if ((oggstate->sync_in = malloc(sizeof(ogg_sync_state)))==NULL)
00218 {
00219 goto error;
00220 }
00221 if ((oggstate->stream_in = malloc(sizeof(ogg_stream_state)))==NULL)
00222 {
00223 goto error;
00224 }
00225 if ((oggstate->vd = malloc(sizeof(vorbis_dsp_state)))==NULL)
00226 {
00227 goto error;
00228 }
00229 if ((oggstate->vi = malloc(sizeof(vorbis_info)))==NULL)
00230 {
00231 goto error;
00232 }
00233 if ((oggstate->vb = malloc(sizeof(vorbis_block)))==NULL)
00234 {
00235 goto error;
00236 }
00237
00238 if ((oggstate->headers = malloc(sizeof(splt_v_packet) * TOTAL_HEADER_PACKETS))==NULL)
00239 {
00240 goto error;
00241 }
00242 memset(oggstate->headers, 0, sizeof(splt_v_packet) * TOTAL_HEADER_PACKETS);
00243
00244 if ((oggstate->packets = malloc(sizeof(splt_v_packet) * 2))==NULL)
00245 {
00246 goto error;
00247 }
00248 memset(oggstate->packets, 0, sizeof(splt_v_packet) * 2);
00249
00250 oggstate->cloned_vorbis_comment = 2;
00251
00252 return oggstate;
00253
00254 error:
00255 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00256 splt_ogg_v_free(oggstate);
00257 return NULL;
00258 }
00259
00260
00261
00262 void splt_ogg_state_free(splt_state *state)
00263 {
00264 splt_ogg_state *oggstate = state->codec;
00265 if (oggstate)
00266 {
00267 ov_clear(&oggstate->vf);
00268 splt_ogg_v_free(oggstate);
00269 state->codec = NULL;
00270 }
00271 }
00272
00273
00274
00275
00276
00277 #define OGG_VERIFY_ERROR() \
00278 if (err != SPLT_OK) \
00279 { \
00280 *tag_error = err; \
00281 return; \
00282 };
00283
00284 void splt_ogg_get_original_tags(const char *filename,
00285 splt_state *state, int *tag_error)
00286 {
00287 splt_ogg_state *oggstate = state->codec;
00288
00289 vorbis_comment *vc_local = NULL;
00290 vc_local = ov_comment(&oggstate->vf,-1);
00291 int err = SPLT_OK;
00292
00293 char *a = NULL,*t = NULL,*al = NULL,*da = NULL, *g = NULL,*tr = NULL,
00294 *com = NULL;
00295
00296 int has_tags = SPLT_FALSE;
00297
00298 a = vorbis_comment_query(vc_local, SPLT_OGG_ARTIST, 0);
00299 if (a != NULL)
00300 {
00301 err = splt_tu_set_original_tags_field(state, SPLT_TAGS_ARTIST, a);
00302 has_tags = SPLT_TRUE;
00303 OGG_VERIFY_ERROR();
00304 }
00305
00306 t = vorbis_comment_query(vc_local, SPLT_OGG_TITLE, 0);
00307 if (t != NULL)
00308 {
00309 err = splt_tu_set_original_tags_field(state, SPLT_TAGS_TITLE, t);
00310 has_tags = SPLT_TRUE;
00311 OGG_VERIFY_ERROR();
00312 }
00313
00314 al = vorbis_comment_query(vc_local, SPLT_OGG_ALBUM, 0);
00315 if (al != NULL)
00316 {
00317 err = splt_tu_set_original_tags_field(state, SPLT_TAGS_ALBUM, al);
00318 has_tags = SPLT_TRUE;
00319 OGG_VERIFY_ERROR();
00320 }
00321
00322 da = vorbis_comment_query(vc_local, SPLT_OGG_DATE, 0);
00323 if (da != NULL)
00324 {
00325 err = splt_tu_set_original_tags_field(state, SPLT_TAGS_YEAR, da);
00326 has_tags = SPLT_TRUE;
00327 OGG_VERIFY_ERROR();
00328 }
00329
00330 g = vorbis_comment_query(vc_local, SPLT_OGG_GENRE, 0);
00331 if (g != NULL)
00332 {
00333 err = splt_tu_set_original_tags_field(state, SPLT_TAGS_GENRE, g);
00334 has_tags = SPLT_TRUE;
00335 OGG_VERIFY_ERROR();
00336 }
00337
00338 tr = vorbis_comment_query(vc_local, SPLT_OGG_TRACKNUMBER, 0);
00339 if (tr != NULL)
00340 {
00341 int track = atoi(tr);
00342 err = splt_tu_set_original_tags_field(state, SPLT_TAGS_TRACK, &track);
00343 has_tags = SPLT_TRUE;
00344 OGG_VERIFY_ERROR();
00345 }
00346
00347 com = vorbis_comment_query(vc_local, SPLT_OGG_COMMENT, 0);
00348 if (com != NULL)
00349 {
00350 err = splt_tu_set_original_tags_field(state, SPLT_TAGS_COMMENT, com);
00351 has_tags = SPLT_TRUE;
00352 OGG_VERIFY_ERROR();
00353 }
00354
00355 splt_tu_set_original_tags_field(state, SPLT_TAGS_VERSION, &has_tags);
00356
00357 vorbis_comment *cloned_comment = splt_ogg_clone_vorbis_comment(vc_local);
00358 if (cloned_comment == NULL)
00359 {
00360 err = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00361 OGG_VERIFY_ERROR();
00362 }
00363
00364 splt_tu_set_original_tags_data(state, cloned_comment);
00365 }
00366
00367
00368
00369
00370
00371
00372 static int splt_ogg_read_headers_and_save_them(splt_state *state, splt_ogg_state *oggstate, int *error)
00373 {
00374 ogg_page page;
00375 ogg_packet packet;
00376 int bytes = 0;
00377 int i = 0;
00378 char *buffer = NULL;
00379
00380 ogg_sync_init(oggstate->sync_in);
00381 vorbis_info_init(oggstate->vi);
00382
00383 int result = 0;
00384 while ((result = ogg_sync_pageout(oggstate->sync_in, &page))!=1)
00385 {
00386 buffer = ogg_sync_buffer(oggstate->sync_in, SPLT_OGG_BUFSIZE);
00387 if (buffer == NULL)
00388 {
00389 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00390 return -1;
00391 }
00392 bytes = fread(buffer, 1, SPLT_OGG_BUFSIZE, oggstate->in);
00393 if (bytes <= 0)
00394 {
00395 goto error_invalid_file;
00396 }
00397 if (ogg_sync_wrote(oggstate->sync_in, bytes) != 0)
00398 {
00399 goto error_invalid_file;
00400 }
00401 }
00402
00403 oggstate->serial = ogg_page_serialno(&page);
00404
00405 ogg_stream_init(oggstate->stream_in, oggstate->serial);
00406 if(ogg_stream_pagein(oggstate->stream_in, &page) < 0)
00407 {
00408 goto error_invalid_file;
00409 }
00410
00411 if(ogg_stream_packetout(oggstate->stream_in, &packet)!=1)
00412 {
00413 goto error_invalid_file;
00414 }
00415
00416 if(vorbis_synthesis_headerin(oggstate->vi, &oggstate->vc, &packet) < 0)
00417 {
00418 goto error_invalid_file;
00419 }
00420 oggstate->cloned_vorbis_comment = SPLT_FALSE;
00421
00422 int packet_err = SPLT_OK;
00423 oggstate->headers[0] = splt_ogg_clone_packet(&packet, &packet_err);
00424 if (packet_err < 0)
00425 {
00426 goto error;
00427 }
00428
00429 i=0;
00430 while(i<2)
00431 {
00432 while(i<2)
00433 {
00434 int res = ogg_sync_pageout(oggstate->sync_in, &page);
00435
00436 if(res == 0)
00437 {
00438 break;
00439 }
00440
00441 if(res == 1)
00442 {
00443 if (ogg_stream_pagein(oggstate->stream_in, &page) < 0)
00444 {
00445 goto error_invalid_file;
00446 }
00447 while(i<2)
00448 {
00449 res = ogg_stream_packetout(oggstate->stream_in, &packet);
00450 if(res==0)
00451 {
00452 break;
00453 }
00454
00455 if(res<0)
00456 {
00457 goto error_invalid_file;
00458 }
00459
00460 oggstate->headers[i+1] = splt_ogg_clone_packet(&packet, &packet_err);
00461 if (packet_err < 0)
00462 {
00463 goto error;
00464 }
00465
00466 if (vorbis_synthesis_headerin(oggstate->vi,&oggstate->vc,&packet) < 0)
00467 {
00468 goto error_invalid_file;
00469 }
00470 oggstate->cloned_vorbis_comment = SPLT_FALSE;
00471 i++;
00472 }
00473 }
00474 }
00475
00476 buffer=ogg_sync_buffer(oggstate->sync_in, SPLT_OGG_BUFSIZE);
00477 if (buffer == NULL)
00478 {
00479 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00480 goto error;
00481 }
00482 bytes=fread(buffer,1,SPLT_OGG_BUFSIZE,oggstate->in);
00483
00484 if(bytes == 0 && i < 2)
00485 {
00486 goto error_invalid_file;
00487 }
00488 if (ogg_sync_wrote(oggstate->sync_in, bytes) != 0)
00489 {
00490 *error = SPLT_ERROR_INVALID;
00491 goto error;
00492 }
00493 }
00494
00495 return 0;
00496
00497 error_invalid_file:
00498 *error = SPLT_ERROR_INVALID;
00499 splt_e_set_error_data(state, splt_t_get_filename_to_split(state));
00500 error:
00501 return -1;
00502 }
00503
00504
00505 splt_ogg_state *splt_ogg_info(FILE *in, splt_state *state, int *error)
00506 {
00507 splt_ogg_state *oggstate = state->codec;
00508
00509 oggstate = splt_ogg_v_new(error);
00510 if (oggstate == NULL) { return NULL; }
00511
00512 char *filename = splt_t_get_filename_to_split(state);
00513
00514 oggstate->in = in;
00515 oggstate->end = 0;
00516
00517 oggstate->total_blocksize = -1;
00518 oggstate->first_granpos = 0;
00519
00520
00521 if (oggstate->in != stdin)
00522 {
00523 int ret = ov_open(oggstate->in, &oggstate->vf, NULL, 0);
00524 if(ret < 0)
00525 {
00526 splt_e_set_error_data(state,filename);
00527 switch (ret)
00528 {
00529 case OV_EREAD:
00530 *error = SPLT_ERROR_WHILE_READING_FILE;
00531 break;
00532 default:
00533 splt_e_set_error_data(state, splt_t_get_filename_to_split(state));
00534 *error = SPLT_ERROR_INVALID;
00535 break;
00536 }
00537 splt_ogg_v_free(oggstate);
00538 return NULL;
00539 }
00540
00541 rewind(oggstate->in);
00542 }
00543
00544
00545 if (splt_ogg_read_headers_and_save_them(state, oggstate, error) == -1)
00546 {
00547 splt_ogg_v_free(oggstate);
00548 return NULL;
00549 }
00550
00551 if (oggstate->in != stdin)
00552 {
00553
00554 double total_time = ov_time_total(&oggstate->vf, -1) * 100;
00555 splt_t_set_total_time(state, total_time);
00556 oggstate->len = (ogg_int64_t) (oggstate->vi->rate * total_time);
00557 }
00558
00559 oggstate->cutpoint_begin = 0;
00560
00561
00562 vorbis_synthesis_init(oggstate->vd, oggstate->vi);
00563 vorbis_block_init(oggstate->vd, oggstate->vb);
00564
00565 srand(time(NULL));
00566
00567 return oggstate;
00568 }
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584 static int splt_ogg_find_begin_cutpoint(splt_state *state, splt_ogg_state *oggstate,
00585 FILE *in, ogg_int64_t cutpoint, int *error, const char *filename,
00586 int save_end_point)
00587 {
00588 splt_ogg_new_stream_handler *ogg_new_stream_handler =
00589 splt_ogg_nsh_new(state, oggstate, NULL, NULL, SPLT_FALSE, NULL);
00590 if (ogg_new_stream_handler == NULL)
00591 {
00592 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00593 return -1;
00594 }
00595
00596 int eos=0;
00597 ogg_page page;
00598 ogg_packet packet;
00599 ogg_int64_t granpos, prevgranpos;
00600
00601 granpos = prevgranpos = 0;
00602
00603 int packet_err = SPLT_OK;
00604
00605 cutpoint += oggstate->first_granpos;
00606
00607 while (!eos)
00608 {
00609 while (!eos)
00610 {
00611 int result = ogg_sync_pageout(oggstate->sync_in, &page);
00612
00613
00614 if (result==0)
00615 {
00616 break;
00617 }
00618 else
00619 {
00620
00621 if (result > 0)
00622 {
00623 if (ogg_page_bos(&page))
00624 {
00625 splt_ogg_initialise_for_new_stream(ogg_new_stream_handler,
00626 &page, &cutpoint, prevgranpos);
00627 }
00628
00629 granpos = ogg_page_granulepos(&page);
00630
00631
00632
00633
00634
00635
00636 if (ogg_stream_pagein(oggstate->stream_in, &page) == -1)
00637 {
00638 splt_e_set_error_data(state, splt_t_get_filename_to_split(state));
00639 *error = SPLT_ERROR_INVALID;
00640 goto error;
00641 }
00642
00643
00644
00645 if (granpos < cutpoint)
00646 {
00647 while (1)
00648 {
00649 result = ogg_stream_packetout(oggstate->stream_in, &packet);
00650
00651 if (result == 0)
00652 {
00653 break;
00654 }
00655
00656
00657 if (granpos == 0)
00658 {
00659 continue;
00660 }
00661
00662 if (result != -1)
00663 {
00664
00665
00666
00667
00668 if (splt_ogg_new_stream_needs_header_packet(ogg_new_stream_handler))
00669 {
00670 splt_ogg_new_stream_handle_header_packet(ogg_new_stream_handler, &packet, error);
00671 if (*error < 0) { goto error; }
00672 continue;
00673 }
00674
00675 int bs = splt_ogg_get_blocksize(oggstate, oggstate->vi, &packet);
00676
00677 cutpoint += splt_ogg_compute_first_granulepos(state, oggstate, &packet, bs);
00678
00679
00680
00681
00682
00683
00684 splt_ogg_free_packet(&oggstate->packets[0]);
00685 oggstate->packets[0] = splt_ogg_clone_packet(&packet, &packet_err);
00686 if (packet_err < 0) { goto error; }
00687 }
00688 }
00689
00690 prevgranpos = granpos;
00691 }
00692 else
00693 {
00694 eos = 1;
00695
00696 while ((result = ogg_stream_packetout(oggstate->stream_in, &packet)) != 0)
00697 {
00698
00699 if (granpos == 0)
00700 {
00701 continue;
00702 }
00703
00704
00705 if (result != -1)
00706 {
00707
00708
00709
00710
00711 int bs = splt_ogg_get_blocksize(oggstate, oggstate->vi, &packet);
00712 prevgranpos += bs;
00713
00714 ogg_int64_t old_first_granpos = oggstate->first_granpos;
00715 ogg_int64_t first_granpos = splt_ogg_compute_first_granulepos(state, oggstate, &packet, bs);
00716 cutpoint += first_granpos;
00717 if (first_granpos != 0)
00718 {
00719 eos = 0;
00720 }
00721 if (old_first_granpos == 0)
00722 {
00723 prevgranpos += first_granpos;
00724 }
00725
00726 if (prevgranpos > cutpoint)
00727 {
00728 splt_ogg_free_packet(&oggstate->packets[1]);
00729 oggstate->packets[1] = splt_ogg_clone_packet(&packet, &packet_err);
00730 if (packet_err < 0) { goto error; }
00731 eos = 1;
00732 break;
00733 }
00734
00735 splt_ogg_free_packet(&oggstate->packets[0]);
00736 oggstate->packets[0] = splt_ogg_clone_packet(&packet, &packet_err);
00737 if (packet_err < 0) { goto error; }
00738 }
00739 }
00740 }
00741
00742 if (ogg_page_eos(&page))
00743 {
00744 break;
00745 }
00746 }
00747 }
00748 }
00749
00750 if (!eos)
00751 {
00752 int sync_bytes = splt_ogg_update_sync(state, oggstate->sync_in, in, error);
00753 if (sync_bytes == 0)
00754 {
00755 eos = 1;
00756 }
00757 else if (sync_bytes == -1)
00758 {
00759 goto error;
00760 }
00761 }
00762 }
00763
00764 if (granpos < cutpoint)
00765 {
00766 *error = SPLT_ERROR_BEGIN_OUT_OF_FILE;
00767 goto error;
00768 }
00769
00770
00771 oggstate->initialgranpos = prevgranpos - cutpoint;
00772 oggstate->cutpoint_begin = cutpoint;
00773
00774 splt_ogg_nsh_free(&ogg_new_stream_handler);
00775
00776 return 0;
00777
00778 error:
00779 splt_ogg_nsh_free(&ogg_new_stream_handler);
00780
00781 return -1;
00782 }
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794 static int splt_ogg_find_end_cutpoint(splt_state *state, ogg_stream_state *stream,
00795 FILE *in, FILE *f, ogg_int64_t cutpoint, int adjust, float threshold, int shots,
00796 int *error, const char *output_fname, int save_end_point,
00797 double *sec_split_time_length)
00798 {
00799 splt_c_put_progress_text(state, SPLT_PROGRESS_CREATE);
00800
00801
00802
00803 splt_ogg_state *oggstate = state->codec;
00804
00805 splt_ogg_new_stream_handler *ogg_new_stream_handler =
00806 splt_ogg_nsh_new(state, oggstate, stream, output_fname, SPLT_TRUE, NULL);
00807 if (ogg_new_stream_handler == NULL)
00808 {
00809 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00810 return -1;
00811 }
00812
00813 ogg_packet packet;
00814 ogg_page page;
00815 int eos=0;
00816 int result = 0;
00817 ogg_int64_t page_granpos = 0, current_granpos = 0, prev_granpos = 0;
00818 ogg_int64_t packetnum = 0;
00819
00820 ogg_int64_t first_cut_granpos = 0;
00821
00822 if (oggstate->packets[0] && oggstate->packets[1])
00823 {
00824
00825 packet.bytes = oggstate->packets[0]->length;
00826 packet.packet = oggstate->packets[0]->packet;
00827 packet.b_o_s = 0;
00828 packet.e_o_s = 0;
00829 packet.granulepos = FIRST_GRANPOS;
00830 packet.packetno = packetnum++;
00831 ogg_stream_packetin(stream,&packet);
00832
00833 packet.bytes = oggstate->packets[1]->length;
00834 packet.packet = oggstate->packets[1]->packet;
00835 packet.b_o_s = 0;
00836 packet.e_o_s = 0;
00837 packet.granulepos = oggstate->initialgranpos;
00838 packet.packetno = packetnum++;
00839 ogg_stream_packetin(stream,&packet);
00840
00841 if (ogg_stream_flush(stream, &page)!=0)
00842 {
00843 if (splt_io_fwrite(state, page.header,1,page.header_len,f) < page.header_len)
00844 {
00845 goto write_error;
00846 }
00847 if (splt_io_fwrite(state, page.body,1,page.body_len,f) < page.body_len)
00848 {
00849 goto write_error;
00850 }
00851 }
00852
00853 while (ogg_stream_flush(stream, &page) != 0)
00854 {
00855
00856
00857
00858
00859
00860 if (splt_io_fwrite(state, page.header,1,page.header_len,f) < page.header_len)
00861 {
00862 goto write_error;
00863 }
00864 if (splt_io_fwrite(state, page.body,1,page.body_len,f) < page.body_len)
00865 {
00866 goto write_error;
00867 }
00868 }
00869 }
00870
00871 else
00872 {
00873 if (oggstate->packets[1])
00874 {
00875 packet.bytes = oggstate->packets[1]->length;
00876 packet.packet = oggstate->packets[1]->packet;
00877 packet.b_o_s = 0;
00878 packet.e_o_s = 0;
00879 packet.granulepos = FIRST_GRANPOS;
00880 packet.packetno = packetnum++;
00881 ogg_stream_packetin(stream, &packet);
00882
00883 if (ogg_stream_flush(stream, &page)!=0)
00884 {
00885 if (splt_io_fwrite(state, page.header,1,page.header_len,f) < page.header_len)
00886 {
00887 goto write_error;
00888 }
00889 if (splt_io_fwrite(state, page.body,1,page.body_len,f) < page.body_len)
00890 {
00891 goto write_error;
00892 }
00893 }
00894 }
00895
00896 oggstate->initialgranpos = FIRST_GRANPOS;
00897 }
00898
00899 current_granpos = oggstate->initialgranpos;
00900
00901 int packet_err = SPLT_OK;
00902
00903 while (!eos)
00904 {
00905 while (!eos)
00906 {
00907 result = ogg_sync_pageout(oggstate->sync_in, &page);
00908
00909
00910 if (result==0)
00911 {
00912 break;
00913 }
00914 else
00915 {
00916 if (result != -1)
00917 {
00918 if (ogg_page_bos(&page))
00919 {
00920 splt_ogg_initialise_for_new_stream(ogg_new_stream_handler, &page, &cutpoint, prev_granpos);
00921 oggstate->cutpoint_begin = 0;
00922 }
00923
00924 page_granpos = ogg_page_granulepos(&page) - oggstate->cutpoint_begin;
00925
00926
00927
00928
00929
00930
00931 if (ogg_stream_pagein(oggstate->stream_in, &page) == -1)
00932 {
00933 splt_e_set_error_data(state, splt_t_get_filename_to_split(state));
00934 *error = SPLT_ERROR_INVALID;
00935 goto error;
00936 }
00937
00938 if ((cutpoint == 0) || (page_granpos < cutpoint))
00939 {
00940 while(1)
00941 {
00942 result = ogg_stream_packetout(oggstate->stream_in, &packet);
00943
00944
00945 if (result==0)
00946 {
00947 break;
00948 }
00949 else
00950 {
00951 if (result != -1)
00952 {
00953
00954
00955
00956
00957 if (splt_ogg_new_stream_needs_header_packet(ogg_new_stream_handler))
00958 {
00959 splt_ogg_new_stream_handle_header_packet(ogg_new_stream_handler, &packet, error);
00960 if (*error < 0) { goto error; }
00961 continue;
00962 }
00963
00964 int bs = splt_ogg_get_blocksize(oggstate, oggstate->vi, &packet);
00965 ogg_int64_t first_granpos = splt_ogg_compute_first_granulepos(state, oggstate, &packet, bs);
00966 if (first_cut_granpos == 0)
00967 {
00968 first_cut_granpos = first_granpos;
00969 if (cutpoint != 0)
00970 {
00971 cutpoint += first_granpos;
00972 }
00973 }
00974 current_granpos += bs;
00975
00976
00977 splt_ogg_free_packet(&oggstate->packets[0]);
00978 oggstate->packets[0] = splt_ogg_clone_packet(&packet, &packet_err);
00979
00980 if (packet_err < 0) { goto error; }
00981 if (current_granpos > page_granpos)
00982 {
00983 current_granpos = page_granpos;
00984 }
00985 packet.granulepos = current_granpos;
00986 packet.packetno = packetnum++;
00987
00988
00989 if ((splt_o_get_int_option(state,SPLT_OPT_SPLIT_MODE) == SPLT_OPTION_SILENCE_MODE) ||
00990 (splt_o_get_int_option(state,SPLT_OPT_SPLIT_MODE) == SPLT_OPTION_TRIM_SILENCE_MODE) ||
00991 (!splt_o_get_int_option(state,SPLT_OPT_AUTO_ADJUST)))
00992 {
00993 splt_c_update_progress(state, (double)page_granpos,
00994 (double)cutpoint,
00995 1,0,SPLT_DEFAULT_PROGRESS_RATE);
00996 }
00997 else
00998 {
00999 splt_c_update_progress(state, (double)page_granpos,
01000 (double)cutpoint,
01001 2,0,SPLT_DEFAULT_PROGRESS_RATE);
01002 }
01003
01004 ogg_stream_packetin(stream, &packet);
01005
01006 if (packet.packetno == 4 && packet.granulepos != -1)
01007 {
01008 if (splt_ogg_write_pages_to_file(state, stream,f, 1,
01009 error, output_fname)) { goto error; }
01010 }
01011 else
01012 {
01013 if (splt_ogg_write_pages_to_file(state, stream,f, 0,
01014 error, output_fname)) { goto error; }
01015 }
01016 }
01017 }
01018 }
01019
01020 prev_granpos = page_granpos;
01021 }
01022 else
01023 {
01024 if (adjust)
01025 {
01026 if (splt_ogg_scan_silence(state,
01027 (2 * adjust), threshold, 0.f, shots, 0, &page, current_granpos, error, first_cut_granpos,
01028 splt_scan_silence_processor) > 0)
01029 {
01030 cutpoint = (splt_siu_silence_position(state->silence_list,
01031 oggstate->off) * oggstate->vi->rate);
01032 }
01033 else
01034 {
01035 cutpoint = (cutpoint + (adjust * oggstate->vi->rate));
01036 }
01037
01038 if (first_cut_granpos == 0 && oggstate->first_granpos != 0)
01039 {
01040 first_cut_granpos = oggstate->first_granpos;
01041 cutpoint += first_cut_granpos;
01042 prev_granpos += first_cut_granpos;
01043 }
01044
01045 *sec_split_time_length = cutpoint / oggstate->vi->rate;
01046
01047 splt_siu_ssplit_free(&state->silence_list);
01048 adjust = 0;
01049 splt_c_put_progress_text(state, SPLT_PROGRESS_CREATE);
01050
01051 if (*error < 0) { goto error; }
01052 }
01053 else
01054 {
01055 eos = 1;
01056 }
01057
01058 while ((result = ogg_stream_packetout(oggstate->stream_in, &packet)) != 0)
01059 {
01060
01061 if (result != -1)
01062 {
01063
01064
01065
01066
01067 if (splt_ogg_new_stream_needs_header_packet(ogg_new_stream_handler))
01068 {
01069 splt_ogg_new_stream_handle_header_packet(ogg_new_stream_handler, &packet, error);
01070 if (*error < 0) { goto error; }
01071 continue;
01072 }
01073
01074 int bs;
01075 bs = splt_ogg_get_blocksize(oggstate, oggstate->vi, &packet);
01076
01077 ogg_int64_t first_granpos = splt_ogg_compute_first_granulepos(state, oggstate, &packet, bs);
01078 if (first_cut_granpos == 0 && first_granpos != 0)
01079 {
01080 first_cut_granpos = first_granpos;
01081 cutpoint += first_granpos;
01082 prev_granpos += first_granpos;
01083 eos = 0;
01084 }
01085
01086 if (prev_granpos == -1)
01087 {
01088 prev_granpos = 0;
01089 }
01090 else if (prev_granpos == 0 && !packet.e_o_s)
01091 {
01092 prev_granpos = bs + first_cut_granpos;
01093 if (prev_granpos > current_granpos + first_cut_granpos)
01094 {
01095 prev_granpos = current_granpos + first_cut_granpos;
01096 }
01097 }
01098 else
01099 {
01100 prev_granpos += bs;
01101 }
01102
01103 current_granpos += bs;
01104
01105 if (prev_granpos >= cutpoint)
01106 {
01107 splt_ogg_free_packet(&oggstate->packets[1]);
01108
01109 if (prev_granpos != cutpoint)
01110 {
01111 oggstate->packets[1] = splt_ogg_clone_packet(&packet, &packet_err);
01112 }
01113 if (packet_err < 0) { goto error; }
01114 if (first_cut_granpos != 0)
01115 {
01116 packet.granulepos = current_granpos;
01117 }
01118 else
01119 {
01120 packet.granulepos = cutpoint;
01121 }
01122
01123
01124 packet.e_o_s = 1;
01125 ogg_stream_packetin(stream, &packet);
01126 break;
01127 }
01128 else
01129 {
01130 if (first_cut_granpos != 0)
01131 {
01132 packet.granulepos = current_granpos;
01133 }
01134 else
01135 {
01136 packet.granulepos = prev_granpos - first_cut_granpos;
01137 }
01138
01139
01140 packet.packetno = packetnum++;
01141 }
01142
01143 splt_ogg_free_packet(&oggstate->packets[0]);
01144 oggstate->packets[0] = splt_ogg_clone_packet(&packet, &packet_err);
01145 if (packet_err < 0) { goto error; }
01146
01147 ogg_stream_packetin(stream, &packet);
01148 if (splt_ogg_write_pages_to_file(state, stream, f, 0, error, output_fname))
01149 {
01150 goto error;
01151 }
01152 }
01153 }
01154 }
01155
01156 if (ogg_page_eos(&page))
01157 {
01158 break;
01159 }
01160 }
01161 }
01162 }
01163
01164 if (!eos)
01165 {
01166 int sync_bytes = splt_ogg_update_sync(state, oggstate->sync_in, in, error);
01167 if (sync_bytes == 0)
01168 {
01169 eos = 1;
01170 }
01171 else if (sync_bytes == -1)
01172 {
01173 goto error;
01174 }
01175 }
01176 }
01177
01178 if ((cutpoint == 0) || (page_granpos < cutpoint))
01179 {
01180 if (splt_ogg_write_pages_to_file(state, stream, f, 1, error, output_fname))
01181 {
01182 goto error;
01183 }
01184
01185 oggstate->end = -1;
01186
01187 splt_ogg_nsh_free(&ogg_new_stream_handler);
01188
01189 return 0;
01190 }
01191
01192 if (splt_ogg_write_pages_to_file(state, stream, f, 0, error, output_fname))
01193 {
01194 goto error;
01195 }
01196
01197 oggstate->initialgranpos = prev_granpos - cutpoint;
01198 oggstate->cutpoint_begin += cutpoint;
01199
01200
01201
01202
01203
01204
01205 if (save_end_point)
01206 {
01207 oggstate->end = 1;
01208 }
01209 else
01210 {
01211 oggstate->end = 0;
01212
01213 rewind(oggstate->in);
01214 }
01215
01216 splt_ogg_nsh_free(&ogg_new_stream_handler);
01217
01218 return 0;
01219
01220 write_error:
01221 splt_e_set_error_data(state, output_fname);
01222 *error = SPLT_ERROR_CANT_WRITE_TO_OUTPUT_FILE;
01223
01224 error:
01225 splt_ogg_nsh_free(&ogg_new_stream_handler);
01226
01227 return -1;
01228 }
01229
01230 double splt_ogg_split(const char *output_fname, splt_state *state,
01231 double sec_begin, double sec_end, short seekable,
01232 int adjust, float threshold, int shots, int *error, int save_end_point)
01233 {
01234 splt_ogg_state *oggstate = state->codec;
01235
01236 ogg_stream_state stream_out;
01237 ogg_int64_t begin, end = 0, cutpoint = 0;
01238
01239 begin = (ogg_int64_t) (sec_begin * oggstate->vi->rate);
01240
01241 double sec_end_time = sec_end;
01242
01243 char *filename = splt_t_get_filename_to_split(state);
01244
01245 short sec_end_is_not_eof =
01246 !splt_u_fend_sec_is_bigger_than_total_time(state, sec_end);
01247
01248 if (sec_end_is_not_eof)
01249 {
01250 if (adjust)
01251 {
01252 if (sec_end_is_not_eof)
01253 {
01254 float gap = (float) adjust;
01255 if (sec_end > gap)
01256 {
01257 sec_end -= gap;
01258 }
01259 if (sec_end < sec_begin)
01260 {
01261 sec_end = sec_begin;
01262 }
01263 }
01264 else
01265 {
01266 adjust = 0;
01267 }
01268 }
01269 end = (ogg_int64_t) (sec_end * oggstate->vi->rate);
01270 cutpoint = end - begin;
01271 }
01272
01273
01274 if (oggstate->end == 0)
01275 {
01276
01277
01278 if (splt_ogg_find_begin_cutpoint(state,
01279 oggstate, oggstate->in, begin, error, filename, save_end_point) < 0)
01280 {
01281 return sec_end_time;
01282 }
01283 }
01284
01285 if (! splt_o_get_int_option(state, SPLT_OPT_PRETEND_TO_SPLIT))
01286 {
01287
01288 if (strcmp(output_fname, "-")==0)
01289 {
01290 oggstate->out = stdout;
01291 #ifdef __WIN32__
01292 _setmode(fileno(oggstate->out), _O_BINARY);
01293 #endif
01294 }
01295 else
01296 {
01297 if (!(oggstate->out = splt_io_fopen(output_fname, "wb")))
01298 {
01299 splt_e_set_strerror_msg_with_data(state, output_fname);
01300 *error = SPLT_ERROR_CANNOT_OPEN_DEST_FILE;
01301 return sec_end_time;
01302 }
01303 }
01304 }
01305
01306 ogg_stream_init(&stream_out, rand());
01307
01308 splt_ogg_set_tags_in_headers(oggstate, error);
01309 if (*error < 0)
01310 {
01311 ogg_stream_clear(&stream_out);
01312 return sec_end_time;
01313 }
01314
01315 if (splt_ogg_write_header_packets(state, oggstate, &stream_out, output_fname, error) == -1)
01316 {
01317 goto end;
01318 }
01319
01320 double sec_split_time_length = sec_end - sec_begin;
01321 splt_ogg_find_end_cutpoint(state, &stream_out, oggstate->in,
01322 oggstate->out, cutpoint, adjust, threshold, shots, error, output_fname,
01323 save_end_point, &sec_split_time_length);
01324 sec_end_time = sec_begin + sec_split_time_length;
01325
01326 end:
01327 ogg_stream_clear(&stream_out);
01328 if (oggstate->out)
01329 {
01330 if (oggstate->out != stdout)
01331 {
01332 if (fclose(oggstate->out) != 0)
01333 {
01334 splt_e_set_strerror_msg_with_data(state, output_fname);
01335 *error = SPLT_ERROR_CANNOT_CLOSE_FILE;
01336 }
01337 }
01338 oggstate->out = NULL;
01339 }
01340
01341 if (*error >= 0)
01342 {
01343 if (oggstate->end == -1)
01344 {
01345 *error = SPLT_OK_SPLIT_EOF;
01346 return sec_end_time;
01347 }
01348
01349 *error = SPLT_OK_SPLIT;
01350 }
01351
01352 return sec_end_time;
01353 }
01354
01366 void splt_pl_set_plugin_info(splt_plugin_info *info, int *error)
01367 {
01368 float plugin_version = 1.0;
01369
01370
01371 info->version = plugin_version;
01372
01373
01374 info->name = malloc(sizeof(char) * 40);
01375 if (info->name != NULL)
01376 {
01377 snprintf(info->name, 39, "ogg vorbis (libvorbis)");
01378 }
01379 else
01380 {
01381 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
01382 return;
01383 }
01384
01385
01386 info->extension = malloc(sizeof(char) * (strlen(SPLT_OGGEXT)+2));
01387 if (info->extension != NULL)
01388 {
01389 snprintf(info->extension, strlen(SPLT_OGGEXT)+1, SPLT_OGGEXT);
01390 }
01391 else
01392 {
01393 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
01394 return;
01395 }
01396
01397 info->upper_extension = splt_su_convert(info->extension, SPLT_TO_UPPERCASE, error);
01398 }
01399
01401 int splt_pl_check_plugin_is_for_file(splt_state *state, int *error)
01402 {
01403 char *filename = splt_t_get_filename_to_split(state);
01404
01405
01406 if ((filename != NULL) && (strcmp(filename,"o-")) == 0)
01407 {
01408 return SPLT_TRUE;
01409 }
01410
01411 int is_ogg = SPLT_FALSE;
01412 OggVorbis_File ogg_file;
01413
01414 FILE *file_input = NULL;
01415
01416 if ((file_input = splt_io_fopen(filename, "rb")) == NULL)
01417 {
01418 splt_e_set_strerror_msg_with_data(state, filename);
01419 *error = SPLT_ERROR_CANNOT_OPEN_FILE;
01420 }
01421 else
01422 {
01423
01424 if ((ov_test(file_input, &ogg_file, NULL, 0) + 1) == 1)
01425 {
01426 is_ogg = SPLT_TRUE;
01427 ov_clear(&ogg_file);
01428 }
01429 else
01430 {
01431 if (file_input != stdin)
01432 {
01433 if (fclose(file_input) != 0)
01434 {
01435 splt_e_set_strerror_msg_with_data(state, filename);
01436 *error = SPLT_ERROR_CANNOT_CLOSE_FILE;
01437 }
01438 }
01439 file_input = NULL;
01440 }
01441 }
01442
01443 return is_ogg;
01444 }
01445
01447 void splt_pl_init(splt_state *state, int *error)
01448 {
01449 FILE *file_input = NULL;
01450 char *filename = splt_t_get_filename_to_split(state);
01451
01452 if (splt_io_input_is_stdin(state))
01453 {
01454 if (filename[1] == '\0')
01455 {
01456 splt_c_put_info_message_to_client(state,
01457 _(" warning: stdin 'o-' is supposed to be ogg stream.\n"));
01458 }
01459 }
01460
01461
01462 if ((file_input = splt_ogg_open_file_read(state, filename, error)) != NULL)
01463 {
01464 splt_ogg_get_info(state, file_input, error);
01465 if (*error >= 0)
01466 {
01467 splt_ogg_state *oggstate = state->codec;
01468 oggstate->off = splt_o_get_float_option(state,SPLT_OPT_PARAM_OFFSET);
01469 }
01470 }
01471 }
01472
01474 void splt_pl_end(splt_state *state, int *error)
01475 {
01476 splt_ogg_state_free(state);
01477 }
01478
01480 double splt_pl_split(splt_state *state, const char *final_fname,
01481 double begin_point, double end_point, int *error, int save_end_point)
01482 {
01483 splt_ogg_put_tags(state, error);
01484
01485 if (*error >= 0)
01486 {
01487 int gap = splt_o_get_int_option(state, SPLT_OPT_PARAM_GAP);
01488 float threshold = splt_o_get_int_option(state, SPLT_OPT_PARAM_THRESHOLD);
01489 int shots = splt_o_get_int_option(state, SPLT_OPT_PARAM_SHOTS);
01490
01491 int input_not_seekable = splt_o_get_int_option(state, SPLT_OPT_INPUT_NOT_SEEKABLE);
01492
01493 return splt_ogg_split(final_fname, state, begin_point, end_point,
01494 input_not_seekable, gap, threshold, shots, error, save_end_point);
01495 }
01496
01497 return end_point;
01498 }
01499
01501 int splt_pl_scan_silence(splt_state *state, int *error)
01502 {
01503 float offset = splt_o_get_float_option(state,SPLT_OPT_PARAM_OFFSET);
01504 float threshold = splt_o_get_float_option(state, SPLT_OPT_PARAM_THRESHOLD);
01505 float min_length = splt_o_get_float_option(state, SPLT_OPT_PARAM_MIN_LENGTH);
01506 int shots = splt_o_get_int_option(state, SPLT_OPT_PARAM_SHOTS);
01507
01508 splt_ogg_state *oggstate = state->codec;
01509 oggstate->off = offset;
01510
01511 int found = splt_ogg_scan_silence(state, 0, threshold, min_length, shots, 1, NULL, 0,
01512 error, 0, splt_scan_silence_processor);
01513 if (*error < 0) { return -1; }
01514
01515 return found;
01516 }
01517
01519 int splt_pl_scan_trim_silence(splt_state *state, int *error)
01520 {
01521 float threshold = splt_o_get_float_option(state, SPLT_OPT_PARAM_THRESHOLD);
01522 int shots = splt_o_get_int_option(state, SPLT_OPT_PARAM_SHOTS);
01523
01524 int found = splt_ogg_scan_silence(state, 0, threshold, 0, shots, 1, NULL, 0, error, 0,
01525 splt_trim_silence_processor);
01526 if (*error < 0) { return -1; }
01527
01528 return found;
01529 }
01530
01532 void splt_pl_set_original_tags(splt_state *state, int *error)
01533 {
01534 splt_d_print_debug(state,"Taking ogg original tags... \n");
01535 char *filename = splt_t_get_filename_to_split(state);
01536 splt_ogg_get_original_tags(filename, state, error);
01537 }
01538
01539 void splt_pl_clear_original_tags(splt_original_tags *original_tags)
01540 {
01541 vorbis_comment *comment = (vorbis_comment *)original_tags->all_original_tags;
01542 if (!comment)
01543 {
01544 return;
01545 }
01546
01547 splt_ogg_free_vorbis_comment(comment, SPLT_TRUE);
01548
01549 free(original_tags->all_original_tags);
01550 original_tags->all_original_tags = NULL;
01551 }
01552