404
482
remaining -= bytes;
407
cb_ret = oggz_read_sync (oggz);
410
if (cb_ret == -1) oggz_purge (oggz);
485
cb_ret = oggz_read_sync (oggz);
488
if (cb_ret == OGGZ_STOP_ERR) oggz_purge (oggz);
490
/* Don't return 0 unless it's actually an EOF condition */
493
case OGGZ_CONTINUE: return 0; break;
494
case OGGZ_READ_EMPTY:
496
printf ("oggz_read_input: OUT EMPTY\n");
498
return OGGZ_ERR_READ_STOP_OK;
500
case OGGZ_STOP_ERR: return OGGZ_ERR_READ_STOP_ERR; break;
501
case OGGZ_STOP_OK: default: return OGGZ_ERR_READ_STOP_OK; break;
415
/* oggz_seek() (and oggz_purge()) related functions from here down */
418
* The typical usage is:
420
* oggz_set_data_start (oggz, oggz_tell (oggz));
423
oggz_set_data_start (OGGZ * oggz, oggz_off_t offset)
425
if (oggz == NULL) return -1;
427
if (offset < 0) return -1;
429
oggz->offset_data_begin = offset;
435
oggz_tell_raw (OGGZ * oggz)
437
oggz_off_t offset_at;
439
offset_at = oggz_io_tell (oggz);
448
oggz_seek_raw (OGGZ * oggz, oggz_off_t offset, int whence)
450
OggzReader * reader = &oggz->x.reader;
451
oggz_off_t offset_at;
453
if (oggz_io_seek (oggz, offset, whence) == -1) {
457
offset_at = oggz_io_tell (oggz);
459
oggz->offset = offset_at;
461
ogg_sync_reset (&reader->ogg_sync);
467
oggz_stream_reset (void * data)
469
oggz_stream_t * stream = (oggz_stream_t *) data;
471
if (stream->ogg_stream.serialno != -1) {
472
ogg_stream_reset (&stream->ogg_stream);
479
oggz_reset_streams (OGGZ * oggz)
481
oggz_vector_foreach (oggz->streams, oggz_stream_reset);
485
oggz_reset_seek (OGGZ * oggz, oggz_off_t offset, ogg_int64_t unit, int whence)
487
OggzReader * reader = &oggz->x.reader;
489
oggz_off_t offset_at;
491
offset_at = oggz_seek_raw (oggz, offset, whence);
492
if (offset_at == -1) return -1;
494
oggz->offset = offset_at;
497
printf ("reset to %ld\n", offset_at);
500
if (unit != -1) reader->current_unit = unit;
506
oggz_reset (OGGZ * oggz, oggz_off_t offset, ogg_int64_t unit, int whence)
508
oggz_reset_streams (oggz);
509
return oggz_reset_seek (oggz, offset, unit, whence);
513
oggz_purge (OGGZ * oggz)
515
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
517
if (oggz->flags & OGGZ_WRITE) {
518
return OGGZ_ERR_INVALID;
521
oggz_reset_streams (oggz);
523
if (oggz->file && oggz_reset (oggz, oggz->offset, -1, SEEK_SET) < 0) {
524
return OGGZ_ERR_SYSTEM;
531
* oggz_get_next_page (oggz, og, do_read)
533
* retrieves the next page.
534
* returns >= 0 if found; return value is offset of page start
535
* returns -1 on error
536
* returns -2 if EOF was encountered
539
oggz_get_next_page (OGGZ * oggz, ogg_page * og)
541
OggzReader * reader = &oggz->x.reader;
543
long bytes = 0, more;
544
oggz_off_t page_offset = 0, ret;
548
more = ogg_sync_pageseek (&reader->ogg_sync, og);
553
buffer = ogg_sync_buffer (&reader->ogg_sync, CHUNKSIZE);
554
if ((bytes = (long) oggz_io_read (oggz, buffer, CHUNKSIZE)) == 0) {
557
if (bytes == OGGZ_ERR_SYSTEM) {
558
/*oggz_set_error (oggz, OGGZ_ERR_SYSTEM);*/
564
} else if (oggz->file && feof (oggz->file)) {
565
clearerr (oggz->file);
569
ogg_sync_wrote(&reader->ogg_sync, bytes);
571
} else if (more < 0) {
573
printf ("get_next_page: skipped %ld bytes\n", -more);
578
printf ("get_next_page: page has %ld bytes\n", more);
585
/* Calculate the byte offset of the page which was found */
587
oggz->offset = oggz_tell_raw (oggz) - bytes + page_offset;
590
/* didn't need to do any reading -- accumulate the page_offset */
591
ret = oggz->offset + page_offset;
592
oggz->offset += page_offset + more;
599
oggz_get_next_start_page (OGGZ * oggz, ogg_page * og)
601
oggz_off_t page_offset;
605
page_offset = oggz_get_next_page (oggz, og);
607
/* Return this value if one of the following conditions is met:
609
* page_offset < 0 : error or EOF
610
* page_offset == 0 : start of stream
611
* !ogg_page_continued : start of page
613
if (page_offset <= 0 || !ogg_page_continued (og))
621
oggz_get_prev_start_page (OGGZ * oggz, ogg_page * og,
622
ogg_int64_t * granule, long * serialno)
624
oggz_off_t offset_at, offset_start;
625
oggz_off_t page_offset, prev_offset = 0;
626
long granule_at = -1;
629
offset_at = oggz_tell_raw (oggz);
630
if (offset_at == -1) return -1;
632
offset_at = oggz->offset;
635
offset_start = offset_at;
639
offset_start = offset_at - CHUNKSIZE;
640
if (offset_start < 0) offset_start = 0;
642
offset_start = oggz_seek_raw (oggz, offset_start, SEEK_SET);
643
if (offset_start == -1) return -1;
647
printf ("[A] offset_at: @%ld\toffset_start: @%ld\n",
648
offset_at, offset_start);
650
printf ("*** get_prev_start_page: seeked to %ld\n", offset_start);
656
prev_offset = page_offset;
658
page_offset = oggz_get_next_start_page (oggz, og);
659
if (page_offset == -1) return -1;
660
if (page_offset == -2) break;
662
granule_at = (long)ogg_page_granulepos (og);
665
printf ("\tGOT page (%ld) @%ld\tat @%ld\n", granule_at,
666
page_offset, offset_at);
669
/* Need to stash the granule and serialno of this page because og
670
* will be overwritten by the time we realise this was the desired
672
if (page_offset >= 0 && page_offset < offset_at) {
673
*granule = granule_at;
674
*serialno = ogg_page_serialno (og);
677
} while (page_offset >= 0 && page_offset < offset_at);
680
printf ("[B] offset_at: @%ld\toffset_start: @%ld\n"
681
"prev_offset: @%ld\tpage_offset: @%ld\n",
682
offset_at, offset_start, prev_offset, page_offset);
684
/* reset the file offset */
685
offset_at = offset_start;
687
} while (offset_at > 0 && prev_offset == 0);
696
oggz_scan_for_page (OGGZ * oggz, ogg_page * og, ogg_int64_t unit_target,
697
oggz_off_t offset_begin, oggz_off_t offset_end)
699
oggz_off_t offset_at, offset_next;
700
oggz_off_t offset_prev = -1;
701
ogg_int64_t granule_at;
706
printf (" SCANNING from %ld...", offset_begin);
710
offset_at = oggz_seek_raw (oggz, offset_begin, SEEK_SET);
711
if (offset_at == -1) return -1;
714
printf (" scan @%ld\n", offset_at);
717
offset_next = oggz_get_next_start_page (oggz, og);
719
if (offset_next < 0) {
723
if (offset_next == 0 && offset_begin != 0) {
725
printf (" ... scanned past EOF\n");
729
if (offset_next > offset_end) {
731
printf (" ... scanned to page %ld\n", (long)ogg_page_granulepos (og));
733
if (offset_prev != -1) {
734
offset_at = oggz_seek_raw (oggz, offset_prev, SEEK_SET);
735
if (offset_at == -1) return -1;
737
offset_next = oggz_get_next_start_page (oggz, og);
738
if (offset_next < 0) return offset_next;
740
serialno = ogg_page_serialno (og);
741
granule_at = ogg_page_granulepos (og);
742
unit_at = oggz_get_unit (oggz, serialno, granule_at);
750
offset_at = offset_next;
752
serialno = ogg_page_serialno (og);
753
granule_at = ogg_page_granulepos (og);
754
unit_at = oggz_get_unit (oggz, serialno, granule_at);
756
if (unit_at < unit_target) {
758
printf (" scan: (%ld) < (%ld)\n", unit_at, unit_target);
760
offset_prev = offset_next;
761
offset_begin = offset_next+1;
762
} else if (unit_at > unit_target) {
764
printf (" scan: (%ld) > (%ld)\n", unit_at, unit_target);
768
offset_at = oggz_seek_raw (oggz, offset_begin, SEEK_SET);
769
if (offset_at == -1) return -1;
771
offset_next = oggz_get_next_start_page (oggz, og);
772
if (offset_next < 0) return offset_next;
774
serialno = ogg_page_serialno (og);
775
granule_at = ogg_page_granulepos (og);
776
unit_at = oggz_get_unit (oggz, serialno, granule_at);
782
} else if (unit_at == unit_target) {
784
printf (" scan: (%ld) == (%ld)\n", unit_at, unit_target);
794
oggz_seek_set (OGGZ * oggz, ogg_int64_t unit_target)
796
OggzReader * reader = &oggz->x.reader;
799
oggz_off_t offset_orig, offset_at, offset_guess;
800
oggz_off_t offset_begin, offset_end = -1, offset_next;
801
ogg_int64_t granule_at;
802
ogg_int64_t unit_at, unit_begin = 0, unit_end = -1;
811
if (unit_target > 0 && !oggz_has_metrics (oggz)) {
812
/* No metric defined */
816
if (oggz->file != NULL) {
817
if ((fd = fileno (oggz->file)) == -1) {
818
/*oggz_set_error (oggz, OGGZ_ERR_SYSTEM);*/
822
if (fstat (fd, &statbuf) == -1) {
823
/*oggz_set_error (oggz, OGGZ_ERR_SYSTEM);*/
827
if (oggz_stat_regular (statbuf.st_mode)) {
828
offset_end = statbuf.st_size;
830
/*oggz_set_error (oggz, OGGZ_ERR_NOSEEK);*/
832
/* XXX: should be able to just carry on and guess, as per io */
836
oggz_off_t offset_save;
838
if (oggz->io == NULL || oggz->io->seek == NULL) {
839
/* No file, and no io seek method */
843
/* Get the offset of the end by querying the io seek method */
844
offset_save = oggz_io_tell (oggz);
845
if (oggz_io_seek (oggz, 0, SEEK_END) == -1) {
848
offset_end = oggz_io_tell (oggz);
849
if (oggz_io_seek (oggz, offset_save, SEEK_SET) == -1) {
850
return -1; /* fubar */
854
if (unit_target == reader->current_unit) {
855
return (long)reader->current_unit;
858
if (unit_target == 0) {
859
offset_at = oggz_reset (oggz, oggz->offset_data_begin, 0, SEEK_SET);
860
if (offset_at == -1) return -1;
864
offset_at = oggz_tell_raw (oggz);
865
if (offset_at == -1) return -1;
868
offset_orig = offset_at;
870
offset_orig = oggz->offset;
875
unit_at = reader->current_unit;
879
og = &oggz->current_page;
884
printf ("oggz_read_seek (%ld): (%ld - %ld) [%ld - %ld]\t",
885
unit_target, unit_begin, unit_end, offset_begin, offset_end);
888
if (unit_end == -1) {
889
if (unit_at == unit_begin) {
893
offset_guess = offset_begin + (offset_end - offset_begin)/2;
899
(double)(unit_target - unit_begin) /
900
(double)(unit_at - unit_begin);
903
printf ("\nguess_ration %f = (%ld - %ld) / (%ld - %ld)\n",
904
guess_ratio, unit_target, unit_begin, unit_at, unit_begin);
907
offset_guess = offset_begin +
908
(oggz_off_t)((offset_at - offset_begin) * guess_ratio);
910
} else if (unit_end <= unit_begin) {
912
printf ("unit_end <= unit_begin\n");
918
(double)(unit_target - unit_begin) /
919
(double)(unit_end - unit_begin);
921
offset_guess = offset_begin +
922
(oggz_off_t)((offset_end - offset_begin) * guess_ratio);
925
if (offset_guess <= offset_begin) {
926
offset_guess = offset_begin + 1;
930
offset_guess = offset_begin + (offset_end - offset_begin)/2;
935
printf ("%ld ->", offset_guess);
938
offset_at = oggz_seek_raw (oggz, offset_guess, SEEK_SET);
939
if (offset_at == -1) {
943
offset_next = oggz_get_next_start_page (oggz, og);
949
if (offset_next < 0) {
953
if (offset_next > offset_end) {
954
offset_next = oggz_scan_for_page (oggz, og, unit_target,
955
offset_begin, offset_end);
957
if (offset_next < 0) {
961
offset_at = offset_next;
962
serialno = ogg_page_serialno (og);
963
granule_at = ogg_page_granulepos (og);
965
unit_at = oggz_get_unit (oggz, serialno, granule_at);
970
offset_at = offset_next;
971
serialno = ogg_page_serialno (og);
972
granule_at = ogg_page_granulepos (og);
974
unit_at = oggz_get_unit (oggz, serialno, granule_at);
977
printf ("oggz_read_seek (%ld): got page (%ld) @%ld\n", unit_target,
981
if (unit_at < unit_target) {
982
offset_begin = offset_at;
983
unit_begin = unit_at;
984
} else if (unit_at > unit_target) {
985
offset_end = offset_at-1;
994
printf ("FOUND (%ld)\n", unit_at);
997
offset_at = oggz_reset (oggz, offset_at, unit_at, SEEK_SET);
998
if (offset_at == -1) return -1;
1000
return (long)reader->current_unit;
1004
printf ("NOT FOUND\n");
1007
oggz_reset (oggz, offset_orig, -1, SEEK_SET);
1013
oggz_seek_end (OGGZ * oggz, ogg_int64_t unit_offset)
1015
oggz_off_t offset_orig, offset_at, offset_end;
1016
ogg_int64_t granulepos;
1017
ogg_int64_t unit_end;
1021
og = &oggz->current_page;
1023
offset_orig = oggz->offset;
1025
offset_at = oggz_seek_raw (oggz, 0, SEEK_END);
1026
if (offset_at == -1) return -1;
1028
offset_end = oggz_get_prev_start_page (oggz, og, &granulepos, &serialno);
1030
unit_end = oggz_get_unit (oggz, serialno, granulepos);
1032
if (offset_end < 0) {
1033
oggz_reset (oggz, offset_orig, -1, SEEK_SET);
1038
printf ("*** oggz_seek_end: found packet (%ld) at @%ld\n",
1039
unit_end, offset_end);
1042
return oggz_seek_set (oggz, unit_end + unit_offset);
1046
oggz_seek (OGGZ * oggz, oggz_off_t offset, int whence)
1048
ogg_int64_t units = -1;
1050
if (oggz == NULL) return -1;
1052
if (oggz->flags & OGGZ_WRITE) {
1056
if (offset == 0) units = 0;
1058
return (off_t)oggz_reset (oggz, offset, units, whence);
1062
oggz_seek_units (OGGZ * oggz, ogg_int64_t units, int whence)
1064
OggzReader * reader = &oggz->x.reader;
1066
if (oggz == NULL) return -1;
1068
if (oggz->flags & OGGZ_WRITE) {
1072
if (!oggz_has_metrics (oggz)) {
1078
return oggz_seek_set (oggz, units);
1081
units += reader->current_unit;
1082
return oggz_seek_set (oggz, units);
1085
return oggz_seek_end (oggz, units);
1088
/*oggz_set_error (oggz, OGGZ_EINVALID);*/
1095
oggz_seek_byorder (OGGZ * oggz, void * target)
1101
oggz_seek_packets (OGGZ * oggz, long serialno, long packets, int whence)
1106
509
#else /* OGGZ_CONFIG_READ */
1108
511
#include <ogg/ogg.h>
1109
512
#include "oggz_private.h"
515
oggz_read_init (OGGZ * oggz)
521
oggz_read_close (OGGZ * oggz)
1112
527
oggz_set_read_callback (OGGZ * oggz, long serialno,
1113
528
OggzReadPacket read_packet, void * user_data)