ref: 4ba367d435c859051d4ef2224b3f0e93cf1d1802
parent: 2e6f158f4dc9ebc6eb826041254221cba57c4019
author: Sigrid <[email protected]>
date: Tue Aug 11 13:26:33 EDT 2020
audio/oggdec: add -s SECONDS option to seek before decoding
--- a/sys/src/cmd/audio/oggdec/oggdec.c
+++ b/sys/src/cmd/audio/oggdec/oggdec.c
@@ -27,6 +27,9 @@
#include <math.h>
#include <vorbis/codec.h>
#include <sys/wait.h>
+#define _PLAN9_SOURCE
+#include <utf.h>
+#include <lib9.h>
static int ifd = -1;
@@ -95,7 +98,14 @@
write(ifd, buf, n);
}
-int main(){
+void
+usage(void)
+{
+ fprintf(stderr, "usage: %s [-s SECONDS]\n", argv0);
+ exit(1);
+}
+
+int main(int argc, char **argv){
ogg_sync_state oy; /* sync and verify incoming physical bitstream */
ogg_stream_state os; /* take physical pages, weld into a logical
stream of packets */
@@ -110,8 +120,25 @@
char *buffer;
int bytes;
- int status;
+ int status, n;
+ long seeking, seekoff = 4096;
+ double seek, left, right, time, lasttime;
+
+ seek = 0.0;
+ ARGBEGIN{
+ case 's':
+ seek = atof(EARGF(usage()));
+ seeking = 1;
+ if(seek > 0.0)
+ break;
+ default:
+ usage();
+ }ARGEND;
+
+ lasttime = left = 0.0;
+ right = seek;
+
/********** Decode setup ************/
ogg_sync_init(&oy); /* Now we can read pages */
@@ -134,7 +161,6 @@
if(ogg_sync_pageout(&oy,&og)!=1){
/* have we simply run out of data? If so, we're done. */
if(bytes<4096)break;
-
/* error case. Must not be Vorbis data */
fprintf(stderr,"Input does not appear to be an Ogg bitstream.\n");
exit(1);
@@ -241,7 +267,7 @@
proceed in parallel. We could init
multiple vorbis_block structures
for vd here */
-
+
/* The rest is just a straight decode loop until end of stream */
while(!eos){
while(!eos){
@@ -248,7 +274,8 @@
int result=ogg_sync_pageout(&oy,&og);
if(result==0)break; /* need more data */
if(result<0){ /* missing or corrupt data at this page position */
- fprintf(stderr,"Corrupt or missing data in bitstream; "
+ if(!seeking)
+ fprintf(stderr,"Corrupt or missing data in bitstream; "
"continuing...\n");
}else{
if(ogg_page_bos(&og)){ /* got new start of stream */
@@ -261,6 +288,7 @@
}
ogg_stream_pagein(&os,&og); /* can safely ignore errors at
this point */
+
while(1){
result=ogg_stream_packetout(&os,&op);
@@ -268,6 +296,28 @@
if(result<0){ /* missing or corrupt data at this page position */
/* no reason to complain; already complained above */
}else{
+ if(seeking){
+ time = vorbis_granule_time(&vd, ogg_page_granulepos(&og));
+ if(time > left && time < right && time - lasttime > 0.1){
+ if(time > seek)
+ right = time;
+ else
+ left = time;
+ seekoff *= (seek - time)/(time - lasttime);
+ if(fabs(right - left) > 1.0 && seekoff >= 4096){
+ lasttime = time;
+ if((n = fseek(stdin, seekoff, SEEK_CUR)) < 0 && feof(stdin))
+ n = fseek(stdin, -seekoff/2, SEEK_END);
+ if(n >= 0){
+ ogg_sync_reset(&oy);
+ ogg_stream_reset(&os);
+ goto again;
+ }
+ }
+ }
+ seeking = 0;
+ fprintf(stderr, "time: %g\n", time);
+ }
float **pcm;
int samples;
if(vorbis_synthesis(&vb,&op)==0) /* test for success! */
@@ -277,7 +327,7 @@
vorbis_synthesis_read(&vd,samples); /* tell libvorbis how
many samples we
actually consumed */
- }
+ }
}
}
if(ogg_page_eos(&og))eos=1;
@@ -284,6 +334,7 @@
}
}
if(!eos){
+again:
buffer=ogg_sync_buffer(&oy,4096);
bytes=fread(buffer,1,4096,stdin);
ogg_sync_wrote(&oy,bytes);