Remove OP_SSL_SKIP_CERTIFICATE_CHECK from opusfile_example.
[opusfile.git] / examples / opusfile_example.c
1 /********************************************************************
2  *                                                                  *
3  * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. *
4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
5  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
7  *                                                                  *
8  * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 1994-2012           *
9  * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
10  *                                                                  *
11  ********************************************************************/
12 /*For fileno()*/
13 #if !defined(_POSIX_SOURCE)
14 # define _POSIX_SOURCE 1
15 #endif
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <errno.h>
19 #include <string.h>
20 #if defined(_WIN32)
21 /*We need the following two to set stdin/stdout to binary.*/
22 # include <io.h>
23 # include <fcntl.h>
24 #endif
25 #include <opusfile.h>
26
27 #if defined(OP_FIXED_POINT)
28 typedef opus_int16 op_sample;
29 # define op_read_native_stereo op_read_stereo
30 #else
31 typedef float op_sample;
32 # define op_read_native_stereo op_read_float_stereo
33 #endif
34
35 static void print_duration(FILE *_fp,ogg_int64_t _nsamples,int _frac){
36   ogg_int64_t seconds;
37   ogg_int64_t minutes;
38   ogg_int64_t hours;
39   ogg_int64_t days;
40   ogg_int64_t weeks;
41   _nsamples+=_frac?24:24000;
42   seconds=_nsamples/48000;
43   _nsamples-=seconds*48000;
44   minutes=seconds/60;
45   seconds-=minutes*60;
46   hours=minutes/60;
47   minutes-=hours*60;
48   days=hours/24;
49   hours-=days*24;
50   weeks=days/7;
51   days-=weeks*7;
52   if(weeks)fprintf(_fp,"%liw",(long)weeks);
53   if(weeks||days)fprintf(_fp,"%id",(int)days);
54   if(weeks||days||hours){
55     if(weeks||days)fprintf(_fp,"%02ih",(int)hours);
56     else fprintf(_fp,"%ih",(int)hours);
57   }
58   if(weeks||days||hours||minutes){
59     if(weeks||days||hours)fprintf(_fp,"%02im",(int)minutes);
60     else fprintf(_fp,"%im",(int)minutes);
61     fprintf(_fp,"%02i",(int)seconds);
62   }
63   else fprintf(_fp,"%i",(int)seconds);
64   if(_frac)fprintf(_fp,".%03i",(int)(_nsamples/48));
65   fprintf(_fp,"s");
66 }
67
68 static void print_size(FILE *_fp,opus_int64 _nbytes,int _metric,
69  const char *_spacer){
70   static const char SUFFIXES[7]={' ','k','M','G','T','P','E'};
71   opus_int64 val;
72   opus_int64 den;
73   opus_int64 round;
74   int        base;
75   int        shift;
76   base=_metric?1000:1024;
77   round=0;
78   den=1;
79   for(shift=0;shift<6;shift++){
80     if(_nbytes<den*base-round)break;
81     den*=base;
82     round=den>>1;
83   }
84   val=(_nbytes+round)/den;
85   if(den>1&&val<10){
86     if(den>=1000000000)val=(_nbytes+(round/100))/(den/100);
87     else val=(_nbytes*100+round)/den;
88     fprintf(_fp,"%li.%02i%s%c",(long)(val/100),(int)(val%100),
89      _spacer,SUFFIXES[shift]);
90   }
91   else if(den>1&&val<100){
92     if(den>=1000000000)val=(_nbytes+(round/10))/(den/10);
93     else val=(_nbytes*10+round)/den;
94     fprintf(_fp,"%li.%i%s%c",(long)(val/10),(int)(val%10),
95      _spacer,SUFFIXES[shift]);
96   }
97   else fprintf(_fp,"%li%s%c",(long)val,_spacer,SUFFIXES[shift]);
98 }
99
100 int main(int _argc,const char **_argv){
101   OggOpusFile *of;
102   ogg_int64_t  pcm_offset;
103   ogg_int64_t  pcm_print_offset;
104   ogg_int64_t  nsamples;
105   opus_int32   bitrate;
106   int          ret;
107   int          prev_li;
108   int          is_ssl;
109 #if defined(_WIN32)
110 # undef fileno
111 # define fileno _fileno
112   /*We need to set stdin/stdout to binary mode. Damn windows.*/
113   /*Beware the evil ifdef. We avoid these where we can, but this one we
114      cannot.
115     Don't add any more.
116     You'll probably go to hell if you do.*/
117   _setmode(fileno(stdin),_O_BINARY);
118   _setmode(fileno(stdout),_O_BINARY);
119 #endif
120   if(_argc!=2){
121     fprintf(stderr,"Usage: %s <file.opus>\n",_argv[0]);
122     return EXIT_FAILURE;
123   }
124   is_ssl=0;
125   if(strcmp(_argv[1],"-")==0){
126     OpusFileCallbacks cb={NULL,NULL,NULL,NULL};
127     of=op_open_callbacks(op_fdopen(&cb,fileno(stdin),"rb"),&cb,NULL,0,&ret);
128   }
129   else{
130     /*Try to treat the argument as a URL.*/
131     of=op_open_url(_argv[1],&ret,NULL);
132 #if 0
133     if(of==NULL){
134       OpusFileCallbacks  cb={NULL,NULL,NULL,NULL};
135       void              *fp;
136       /*For debugging: force a file to not be seekable.*/
137       fp=op_fopen(&cb,_argv[1],"rb");
138       cb.seek=NULL;
139       cb.tell=NULL;
140       of=op_open_callbacks(fp,&cb,NULL,0,NULL);
141     }
142 #else
143     if(of==NULL)of=op_open_file(_argv[1],&ret);
144     /*This is not a very good check, but at least it won't give false
145        positives.*/
146     else is_ssl=strncmp(_argv[1],"https:",6)==0;
147 #endif
148   }
149   if(of==NULL){
150     fprintf(stderr,"Failed to open file '%s': %i\n",_argv[1],ret);
151     return EXIT_FAILURE;
152   }
153   if(op_seekable(of)){
154     ogg_int64_t duration;
155     opus_int64  size;
156     fprintf(stderr,"Total number of links: %i\n",op_link_count(of));
157     duration=op_pcm_total(of,-1);
158     fprintf(stderr,"Total duration: ");
159     print_duration(stderr,duration,3);
160     fprintf(stderr," (%li samples @ 48 kHz)\n",(long)duration);
161     size=op_raw_total(of,-1);
162     fprintf(stderr,"Total size: ");
163     print_size(stderr,size,0,"");
164     fprintf(stderr,"\n");
165   }
166   prev_li=-1;
167   nsamples=0;
168   pcm_offset=op_pcm_tell(of);
169   if(pcm_offset!=0){
170     fprintf(stderr,"Non-zero starting PCM offset: %li\n",(long)pcm_offset);
171   }
172   pcm_print_offset=pcm_offset-48000;
173   bitrate=0;
174   for(;;){
175     ogg_int64_t next_pcm_offset;
176     op_sample   pcm[120*48*2];
177     int         li;
178     ret=op_read_native_stereo(of,pcm,sizeof(pcm)/sizeof(*pcm));
179     if(ret<0){
180       fprintf(stderr,"\nError decoding '%s': %i\n",_argv[1],ret);
181       if(is_ssl)fprintf(stderr,"Possible truncation attack?\n");
182       ret=EXIT_FAILURE;
183       break;
184     }
185     li=op_current_link(of);
186     if(li!=prev_li){
187       const OpusHead *head;
188       const OpusTags *tags;
189       int             ci;
190       /*We found a new link.
191         Print out some information.*/
192       fprintf(stderr,"Decoding link %i:                          \n",li);
193       head=op_head(of,li);
194       fprintf(stderr,"  Channels: %i\n",head->channel_count);
195       if(op_seekable(of)){
196         ogg_int64_t duration;
197         opus_int64  size;
198         duration=op_pcm_total(of,li);
199         fprintf(stderr,"  Duration: ");
200         print_duration(stderr,duration,3);
201         fprintf(stderr," (%li samples @ 48 kHz)\n",(long)duration);
202         size=op_raw_total(of,li);
203         fprintf(stderr,"  Size: ");
204         print_size(stderr,size,0,"");
205         fprintf(stderr,"\n");
206       }
207       if(head->input_sample_rate){
208         fprintf(stderr,"  Original sampling rate: %lu Hz\n",
209          (unsigned long)head->input_sample_rate);
210       }
211       tags=op_tags(of,li);
212       fprintf(stderr,"  Encoded by: %s\n",tags->vendor);
213       for(ci=0;ci<tags->comments;ci++){
214         fprintf(stderr,"  %s\n",tags->user_comments[ci]);
215       }
216       fprintf(stderr,"\n");
217       if(!op_seekable(of)){
218         pcm_offset=op_pcm_tell(of)-ret;
219         if(pcm_offset!=0){
220           fprintf(stderr,"Non-zero starting PCM offset in link %i: %li\n",
221            li,(long)pcm_offset);
222         }
223       }
224     }
225     if(li!=prev_li||pcm_offset>=pcm_print_offset+48000){
226       opus_int32 next_bitrate;
227       opus_int64 raw_offset;
228       next_bitrate=op_bitrate_instant(of);
229       if(next_bitrate>=0)bitrate=next_bitrate;
230       raw_offset=op_raw_tell(of);
231       fprintf(stderr,"\r ");
232       print_size(stderr,raw_offset,0,"");
233       fprintf(stderr,"  ");
234       print_duration(stderr,pcm_offset,0);
235       fprintf(stderr,"  (");
236       print_size(stderr,bitrate,1," ");
237       fprintf(stderr,"bps)                    \r");
238       pcm_print_offset=pcm_offset;
239     }
240     next_pcm_offset=op_pcm_tell(of);
241     if(pcm_offset+ret!=next_pcm_offset){
242       fprintf(stderr,"\nPCM offset gap! %li+%i!=%li\n",
243        (long)pcm_offset,ret,(long)next_pcm_offset);
244     }
245     pcm_offset=next_pcm_offset;
246     if(ret<=0){
247       ret=EXIT_SUCCESS;
248       break;
249     }
250     if(!fwrite(pcm,sizeof(*pcm)*2,ret,stdout)){
251       fprintf(stderr,"\nError writing decoded audio data: %s\n",
252        strerror(errno));
253       ret=EXIT_FAILURE;
254       break;
255     }
256     nsamples+=ret;
257     prev_li=li;
258   }
259   op_free(of);
260   if(ret==EXIT_SUCCESS){
261     fprintf(stderr,"\nDone: played ");
262     print_duration(stderr,nsamples,3);
263     fprintf(stderr," (%li samples @ 48 kHz).\n",(long)nsamples);
264   }
265   return ret;
266 }