1 /********************************************************************
3 * THIS FILE IS PART OF THE OggTheora 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. *
8 * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
9 * by the Xiph.Org Foundation http://www.xiph.org/ *
11 ********************************************************************
13 function: example encoder application; makes an Ogg Theora/Vorbis
14 file from YUV4MPEG2 and WAV input
17 ********************************************************************/
20 #define _LARGEFILE_SOURCE
21 #define _LARGEFILE64_SOURCE
22 #define _FILE_OFFSET_BITS 64
24 /* Define to give performance data win32 only*/
25 //#define THEORA_PERF_DATA
26 #ifdef THEORA_PERF_DATA
52 #include "theora/theora.h"
53 #include "vorbis/codec.h"
54 #include "vorbis/vorbisenc.h"
57 /* supply missing headers and functions to Win32 */
61 static double rint(double x
)
64 return (double)(int)(x
- 0.5);
66 return (double)(int)(x
+ 0.5);
70 const char *optstring
= "o:a:A:v:V:s:S:f:F:";
71 struct option options
[] = {
72 {"output",required_argument
,NULL
,'o'},
73 {"audio-rate-target",required_argument
,NULL
,'A'},
74 {"video-rate-target",required_argument
,NULL
,'V'},
75 {"audio-quality",required_argument
,NULL
,'a'},
76 {"video-quality",required_argument
,NULL
,'v'},
77 {"aspect-numerator",optional_argument
,NULL
,'s'},
78 {"aspect-denominator",optional_argument
,NULL
,'S'},
79 {"framerate-numerator",optional_argument
,NULL
,'f'},
80 {"framerate-denominator",optional_argument
,NULL
,'F'},
84 /* You'll go to Hell for using globals. */
100 int frame_y_offset
=0;
109 static void usage(void){
111 "Usage: encoder_example [options] [audio_file] video_file\n\n"
113 " -o --output <filename.ogg> file name for encoded output;\n"
114 " If this option is not given, the\n"
115 " compressed data is sent to stdout.\n\n"
116 " -A --audio-rate-target <n> bitrate target for Vorbis audio;\n"
117 " use -a and not -A if at all possible,\n"
118 " as -a gives higher quality for a given\n"
120 " -V --video-rate-target <n> bitrate target for Theora video\n\n"
121 " -a --audio-quality <n> Vorbis quality selector from -1 to 10\n"
122 " (-1 yields smallest files but lowest\n"
123 " fidelity; 10 yields highest fidelity\n"
124 " but large files. '2' is a reasonable\n"
126 " -v --video-quality <n> Theora quality selector fro 0 to 10\n"
127 " (0 yields smallest files but lowest\n"
128 " video quality. 10 yields highest\n"
129 " fidelity but large files).\n\n"
130 " -s --aspect-numerator <n> Aspect ratio numerator, default is 0\n"
131 " or extracted from YUV input file\n"
132 " -S --aspect-denominator <n> Aspect ratio denominator, default is 0\n"
133 " or extracted from YUV input file\n"
134 " -f --framerate-numerator <n> Frame rate numerator, can be extracted\n"
135 " from YUV input file. ex: 30000000\n"
136 " -F --framerate-denominator <n>Frame rate denominator, can be extracted\n"
137 " from YUV input file. ex: 1000000\n"
138 " The frame rate nominator divided by this\n"
139 " determinates the frame rate in units per tick\n"
140 "encoder_example accepts only uncompressed RIFF WAV format audio and\n"
141 "YUV4MPEG2 uncompressed video.\n\n");
145 static void id_file(char *f
){
147 unsigned char buffer
[80];
149 int tmp_video_hzn
= -1,
155 /* open it, look for magic */
163 fprintf(stderr
,"Unable to open file %s.\n",f
);
168 ret
=fread(buffer
,1,4,test
);
170 fprintf(stderr
,"EOF determining file type of file %s.\n",f
);
174 if(!memcmp(buffer
,"RIFF",4)){
175 /* possible WAV file */
178 /* umm, we already have one */
179 fprintf(stderr
,"Multiple RIFF WAVE files specified on command line.\n");
183 /* Parse the rest of the header */
185 ret
=fread(buffer
,1,4,test
);
186 ret
=fread(buffer
,1,4,test
);
187 if(ret
<4)goto riff_err
;
188 if(!memcmp(buffer
,"WAVE",4)){
191 ret
=fread(buffer
,1,4,test
);
192 if(ret
<4)goto riff_err
;
193 if(!memcmp("fmt",buffer
,3)){
195 /* OK, this is our audio specs chunk. Slurp it up. */
197 ret
=fread(buffer
,1,20,test
);
198 if(ret
<20)goto riff_err
;
200 extra_hdr_bytes
= (buffer
[0] + (buffer
[1] << 8) +
201 (buffer
[2] << 16) + (buffer
[3] << 24)) - 16;
203 if(memcmp(buffer
+4,"\001\000",2)){
204 fprintf(stderr
,"The WAV file %s is in a compressed format; "
205 "can't read it.\n",f
);
210 audio_ch
=buffer
[6]+(buffer
[7]<<8);
211 audio_hz
=buffer
[8]+(buffer
[9]<<8)+
212 (buffer
[10]<<16)+(buffer
[11]<<24);
214 if(buffer
[18]+(buffer
[19]<<8)!=16){
215 fprintf(stderr
,"Can only read 16 bit WAV files for now.\n");
219 /* read past extra header bytes */
220 while(extra_hdr_bytes
){
221 int read_size
= (extra_hdr_bytes
> sizeof(buffer
)) ?
222 sizeof(buffer
) : extra_hdr_bytes
;
223 ret
= fread(buffer
, 1, read_size
, test
);
228 extra_hdr_bytes
-= read_size
;
231 /* Now, align things to the beginning of the data */
232 /* Look for 'dataxxxx' */
234 ret
=fread(buffer
,1,4,test
);
235 if(ret
<4)goto riff_err
;
236 if(!memcmp("data",buffer
,4)){
237 /* We're there. Ignore the declared size for now. */
238 ret
=fread(buffer
,1,4,test
);
239 if(ret
<4)goto riff_err
;
241 fprintf(stderr
,"File %s is 16 bit %d channel %d Hz RIFF WAV audio.\n",
242 f
,audio_ch
,audio_hz
);
251 fprintf(stderr
,"Couldn't find WAVE data in RIFF file %s.\n",f
);
255 if(!memcmp(buffer
,"YUV4",4)){
256 /* possible YUV2MPEG2 format file */
257 /* read until newline, or 80 cols, whichever happens first */
258 /* NB the mjpegtools spec doesn't define a length limit */
261 ret
=fread(buffer
+i
,1,1,test
);
262 if(ret
<1)goto yuv_err
;
263 if(buffer
[i
]=='\n')break;
266 fprintf(stderr
,"Error parsing %s header; not a YUV2MPEG2 file?\n",f
);
270 if(!memcmp(buffer
,"MPEG",4)){
271 char interlace
= '?';
274 /* umm, we already have one */
275 fprintf(stderr
,"Multiple video files specified on command line.\n");
280 fprintf(stderr
,"Incorrect YUV input file version; YUV4MPEG2 required.\n");
283 /* parse the frame header */
286 if ((buffer
[j
] != ' ') && (buffer
[j
-1] == ' '))
288 case 'W': frame_x
= atoi((char*)&buffer
[j
+1]); break;
289 case 'H': frame_y
= atoi((char*)&buffer
[j
+1]); break;
290 case 'C': /* chroma subsampling */ break;
291 case 'I': interlace
= buffer
[j
+1]; break;
292 case 'F': /* frame rate ratio */
293 tmp_video_hzn
= atoi((char*)&buffer
[j
+1]);
294 while ((buffer
[j
] != ':') && (j
< i
)) j
++;
295 tmp_video_hzd
= atoi((char*)&buffer
[j
+1]);
297 case 'A': /* sample aspect ratio */
298 tmp_video_an
= atoi((char*)&buffer
[j
+1]);
299 while ((buffer
[j
] != ':') && (j
< i
)) j
++;
300 tmp_video_ad
= atoi((char*)&buffer
[j
+1]);
302 case 'X': /* metadata */ break;
304 fprintf(stderr
, "unrecognized stream header tag '%c'\n", buffer
[j
]);
309 /* verify data from the stream header */
311 fprintf(stderr
,"Error parsing YUV4MPEG2 header:"
312 " missing width tag in file %s.\n", f
);
316 fprintf(stderr
,"Error parsing YUV4MPEG2 header:"
317 " missing height tag in file %s.\n", f
);
320 if (tmp_video_hzn
< 0 || tmp_video_hzd
< 0) {
321 /* default to 30 fps */
322 tmp_video_hzn
= 30; tmp_video_hzd
= 1;
323 fprintf(stderr
,"Warning: no framerate defined in file %s.\n", f
);
325 if (tmp_video_an
< 0 || tmp_video_ad
< 0) {
326 /* default to unknown */
327 tmp_video_an
= 0; tmp_video_ad
= 0;
330 /* update fps and aspect ratio globals if not specified in the command line */
331 if (video_hzn
==-1) video_hzn
= tmp_video_hzn
;
332 if (video_hzd
==-1) video_hzd
= tmp_video_hzd
;
333 if (video_an
==-1) video_an
= tmp_video_an
;
334 if (video_ad
==-1) video_ad
= tmp_video_ad
;
337 fprintf(stderr
,"Warning: input video isn't marked for interlacing;"
338 " treating this\nas progressive scan video."
339 " Deinterlace first if you get poor results.\n");
340 }else if(interlace
!='p'){
341 fprintf(stderr
,"Input video is interlaced; Theora handles only progressive scan\n");
347 fprintf(stderr
,"File %s is %dx%d %.02f fps YUV12 video.\n",
348 f
,frame_x
,frame_y
,(double)video_hzn
/video_hzd
);
353 fprintf(stderr
,"Input file %s is neither a WAV nor YUV4MPEG2 file.\n",f
);
357 fprintf(stderr
,"EOF parsing RIFF file %s.\n",f
);
360 fprintf(stderr
,"EOF parsing YUV4MPEG2 file %s.\n",f
);
366 char *spinascii
="|/-\\";
369 if(spinner
==4)spinner
=0;
370 fprintf(stderr
,"\r%c",spinascii
[spinner
]);
373 int fetch_and_process_audio(FILE *audio
,ogg_page
*audiopage
,
374 ogg_stream_state
*vo
,
375 vorbis_dsp_state
*vd
,
381 while(audio
&& !audioflag
){
382 /* process any audio already buffered */
384 if(ogg_stream_pageout(vo
,audiopage
)>0) return 1;
385 if(ogg_stream_eos(vo
))return 0;
388 /* read and process more audio */
389 signed char readbuffer
[4096];
390 int toread
=4096/2/audio_ch
;
391 int bytesread
=fread(readbuffer
,1,toread
*2*audio_ch
,audio
);
392 int sampread
=bytesread
/2/audio_ch
;
393 float **vorbis_buffer
;
397 /* end of file. this can be done implicitly, but it's
398 easier to see here in non-clever fashion. Tell the
399 library we're at end of stream so that it can handle the
400 last frame and mark end of stream in the output properly */
401 vorbis_analysis_wrote(vd
,0);
403 vorbis_buffer
=vorbis_analysis_buffer(vd
,sampread
);
404 /* uninterleave samples */
405 for(i
=0;i
<sampread
;i
++){
406 for(j
=0;j
<audio_ch
;j
++){
407 vorbis_buffer
[j
][i
]=((readbuffer
[count
+1]<<8)|
408 (0x00ff&(int)readbuffer
[count
]))/32768.f
;
413 vorbis_analysis_wrote(vd
,sampread
);
417 while(vorbis_analysis_blockout(vd
,vb
)==1){
419 /* analysis, assume we want to use bitrate management */
420 vorbis_analysis(vb
,NULL
);
421 vorbis_bitrate_addblock(vb
);
423 /* weld packets into the bitstream */
424 while(vorbis_bitrate_flushpacket(vd
,&op
))
425 ogg_stream_packetin(vo
,&op
);
434 int fetch_and_process_video(FILE *video
,ogg_page
*videopage
,
435 ogg_stream_state
*to
,
438 /* You'll go to Hell for using static variables */
440 static unsigned char *yuvframe
[2];
447 /* initialize the double frame buffer */
448 yuvframe
[0]=malloc(video_x
*video_y
*3/2);
449 yuvframe
[1]=malloc(video_x
*video_y
*3/2);
451 /* clear initial frame as it may be larger than actual video data */
452 /* fill Y plane with 0x10 and UV planes with 0X80, for black data */
453 memset(yuvframe
[0],0x10,video_x
*video_y
);
454 memset(yuvframe
[0]+video_x
*video_y
,0x80,video_x
*video_y
/2);
455 memset(yuvframe
[1],0x10,video_x
*video_y
);
456 memset(yuvframe
[1]+video_x
*video_y
,0x80,video_x
*video_y
/2);
461 /* is there a video page flushed? If not, work until there is. */
465 if(ogg_stream_pageout(to
,videopage
)>0) return 1;
466 if(ogg_stream_eos(to
)) return 0;
469 /* read and process more video */
470 /* video strategy reads one frame ahead so we know when we're
471 at end of stream and can mark last video frame as such
472 (vorbis audio has to flush one frame past last video frame
473 due to overlap and thus doesn't need this extra work */
475 /* have two frame buffers full (if possible) before
476 proceeding. after first pass and until eos, one will
477 always be full when we get here */
479 for(i
=state
;i
<2;i
++){
481 int ret
=fread(frame
,1,6,video
);
483 /* match and skip the frame header */
485 if(memcmp(frame
,"FRAME",5)){
486 fprintf(stderr
,"Loss of framing in YUV input data\n");
492 if(fread(&c
,1,1,video
)&&c
=='\n')break;
494 fprintf(stderr
,"Error parsing YUV frame header\n");
499 /* read the Y plane into our frame buffer with centering */
500 line
=yuvframe
[i
]+video_x
*frame_y_offset
+frame_x_offset
;
501 for(e
=0;e
<frame_y
;e
++){
502 ret
=fread(line
,1,frame_x
,video
);
503 if(ret
!=frame_x
) break;
507 line
=yuvframe
[i
]+(video_x
*video_y
)
508 +(video_x
/2)*(frame_y_offset
/2)+frame_x_offset
/2;
509 for(e
=0;e
<frame_y
/2;e
++){
510 ret
=fread(line
,1,frame_x
/2,video
);
511 if(ret
!=frame_x
/2) break;
515 line
=yuvframe
[i
]+(video_x
*video_y
*5/4)
516 +(video_x
/2)*(frame_y_offset
/2)+frame_x_offset
/2;
517 for(e
=0;e
<frame_y
/2;e
++){
518 ret
=fread(line
,1,frame_x
/2,video
);
519 if(ret
!=frame_x
/2) break;
526 /* can't get here unless YUV4MPEG stream has no video */
527 fprintf(stderr
,"Video input contains no frames.\n");
531 /* Theora is a one-frame-in,one-frame-out system; submit a frame
532 for compression and pull out the packet */
536 yuv
.y_height
=video_y
;
537 yuv
.y_stride
=video_x
;
539 yuv
.uv_width
=video_x
/2;
540 yuv
.uv_height
=video_y
/2;
541 yuv
.uv_stride
=video_x
/2;
544 yuv
.u
= yuvframe
[0]+ video_x
*video_y
;
545 yuv
.v
= yuvframe
[0]+ video_x
*video_y
*5/4 ;
548 theora_encode_YUVin(td
,&yuv
);
550 /* if there's only one frame, it's the last in the stream */
552 theora_encode_packetout(td
,1,&op
);
554 theora_encode_packetout(td
,0,&op
);
556 ogg_stream_packetin(to
,&op
);
559 unsigned char *temp
=yuvframe
[0];
560 yuvframe
[0]=yuvframe
[1];
570 int main(int argc
,char *argv
[]){
571 int c
,long_option_index
,ret
;
573 ogg_stream_state to
; /* take physical pages, weld into a logical
575 ogg_stream_state vo
; /* take physical pages, weld into a logical
577 ogg_page og
; /* one Ogg bitstream page. Vorbis packets are inside */
578 ogg_packet op
; /* one raw packet of data for decode */
584 vorbis_info vi
; /* struct that stores all the static vorbis bitstream
586 vorbis_comment vc
; /* struct that stores all the user comments */
588 vorbis_dsp_state vd
; /* central working state for the packet->PCM decoder */
589 vorbis_block vb
; /* local working space for packet->PCM decode */
596 ogg_int64_t audio_bytesout
=0;
597 ogg_int64_t video_bytesout
=0;
601 FILE* outfile
= stdout
;
604 # ifdef THEORA_PERF_DATA
605 LARGE_INTEGER start_time
;
606 LARGE_INTEGER final_time
;
608 LONGLONG elapsed_ticks
;
609 LARGE_INTEGER ticks_per_second
;
611 LONGLONG elapsed_secs
;
612 LONGLONG elapsed_sec_mod
;
613 double elapsed_secs_dbl
;
615 /* We need to set stdin/stdout to binary mode. Damn windows. */
616 /* if we were reading/writing a file, it would also need to in
617 binary mode, eg, fopen("file.wav","wb"); */
618 /* Beware the evil ifdef. We avoid these where we can, but this one we
619 cannot. Don't add any more, you'll probably go to hell if you do. */
620 _setmode( _fileno( stdin
), _O_BINARY
);
621 _setmode( _fileno( stdout
), _O_BINARY
);
626 while((c
=getopt_long(argc
,argv
,optstring
,options
,&long_option_index
))!=EOF
){
629 outfile
=fopen(optarg
,"wb");
631 fprintf(stderr
,"Unable to open output file '%s'\n", optarg
);
637 audio_q
=atof(optarg
)*.099;
638 if(audio_q
<-.1 || audio_q
>1){
639 fprintf(stderr
,"Illegal audio quality (choose -1 through 10)\n");
646 video_q
=rint(atof(optarg
)*6.3);
647 if(video_q
<0 || video_q
>63){
648 fprintf(stderr
,"Illegal video quality (choose 0 through 10)\n");
655 audio_r
=atof(optarg
)*1000;
657 fprintf(stderr
,"Illegal audio quality (choose > 0 please)\n");
664 video_r
=rint(atof(optarg
)*1000);
665 if(video_r
<45000 || video_r
>2000000){
666 fprintf(stderr
,"Illegal video bitrate (choose 45kbps through 2000kbps)\n");
673 video_an
=rint(atof(optarg
));
677 video_ad
=rint(atof(optarg
));
681 video_hzn
=rint(atof(optarg
));
685 video_hzd
=rint(atof(optarg
));
694 /* assume that anything following the options must be a filename */
695 id_file(argv
[optind
]);
701 #ifdef THEORA_PERF_DATA
703 QueryPerformanceCounter(&start_time
);
708 /* yayness. Set up Ogg output stream */
711 /* need two inequal serial numbers */
712 int serial1
, serial2
;
715 if (serial1
== serial2
) serial2
++;
716 ogg_stream_init(&to
,serial1
);
717 ogg_stream_init(&vo
,serial2
);
720 /* Set up Theora encoder */
722 fprintf(stderr
,"No video files submitted for compression?\n");
725 /* Theora has a divisible-by-sixteen restriction for the encoded video size */
726 /* scale the frame size up to the nearest /16 and calculate offsets */
727 video_x
=((frame_x
+ 15) >>4)<<4;
728 video_y
=((frame_y
+ 15) >>4)<<4;
729 /* We force the offset to be even.
730 This ensures that the chroma samples align properly with the luma
732 frame_x_offset
=((video_x
-frame_x
)/2)&~1;
733 frame_y_offset
=((video_y
-frame_y
)/2)&~1;
735 theora_info_init(&ti
);
738 ti
.frame_width
=frame_x
;
739 ti
.frame_height
=frame_y
;
740 ti
.offset_x
=frame_x_offset
;
741 ti
.offset_y
=frame_y_offset
;
742 ti
.fps_numerator
=video_hzn
;
743 ti
.fps_denominator
=video_hzd
;
744 ti
.aspect_numerator
=video_an
;
745 ti
.aspect_denominator
=video_ad
;
746 ti
.colorspace
=OC_CS_UNSPECIFIED
;
747 ti
.pixelformat
=OC_PF_420
;
748 ti
.target_bitrate
=video_r
;
753 ti
.keyframe_auto_p
=1;
754 ti
.keyframe_frequency
=64;
755 ti
.keyframe_frequency_force
=64;
756 ti
.keyframe_data_target_bitrate
=video_r
*1.5;
757 ti
.keyframe_auto_threshold
=80;
758 ti
.keyframe_mindistance
=8;
759 ti
.noise_sensitivity
=1;
761 theora_encode_init(&td
,&ti
);
762 theora_info_clear(&ti
);
764 /* initialize Vorbis too, assuming we have audio to compress. */
766 vorbis_info_init(&vi
);
768 ret
= vorbis_encode_init_vbr(&vi
,audio_ch
,audio_hz
,audio_q
);
770 ret
= vorbis_encode_init(&vi
,audio_ch
,audio_hz
,-1,audio_r
,-1);
772 fprintf(stderr
,"The Vorbis encoder could not set up a mode according to\n"
773 "the requested quality or bitrate.\n\n");
777 vorbis_comment_init(&vc
);
778 vorbis_analysis_init(&vd
,&vi
);
779 vorbis_block_init(&vd
,&vb
);
782 /* write the bitstream header packets with proper page interleave */
784 /* first packet will get its own page automatically */
785 theora_encode_header(&td
,&op
);
786 ogg_stream_packetin(&to
,&op
);
787 if(ogg_stream_pageout(&to
,&og
)!=1){
788 fprintf(stderr
,"Internal Ogg library error.\n");
791 fwrite(og
.header
,1,og
.header_len
,outfile
);
792 fwrite(og
.body
,1,og
.body_len
,outfile
);
794 /* create the remaining theora headers */
795 theora_comment_init(&tc
);
796 theora_encode_comment(&tc
,&op
);
797 ogg_stream_packetin(&to
,&op
);
798 /*theora_encode_comment() doesn't take a theora_state parameter, so it has to
799 allocate its own buffer to pass back the packet data.
800 If we don't free it here, we'll leak.
801 libogg2 makes this much cleaner: the stream owns the buffer after you call
802 packetin in libogg2, but this is not true in libogg1.*/
804 theora_encode_tables(&td
,&op
);
805 ogg_stream_packetin(&to
,&op
);
809 ogg_packet header_comm
;
810 ogg_packet header_code
;
812 vorbis_analysis_headerout(&vd
,&vc
,&header
,&header_comm
,&header_code
);
813 ogg_stream_packetin(&vo
,&header
); /* automatically placed in its own
815 if(ogg_stream_pageout(&vo
,&og
)!=1){
816 fprintf(stderr
,"Internal Ogg library error.\n");
819 fwrite(og
.header
,1,og
.header_len
,outfile
);
820 fwrite(og
.body
,1,og
.body_len
,outfile
);
822 /* remaining vorbis header packets */
823 ogg_stream_packetin(&vo
,&header_comm
);
824 ogg_stream_packetin(&vo
,&header_code
);
827 /* Flush the rest of our headers. This ensures
828 the actual data in each stream will start
829 on a new page, as per spec. */
831 int result
= ogg_stream_flush(&to
,&og
);
834 fprintf(stderr
,"Internal Ogg library error.\n");
838 fwrite(og
.header
,1,og
.header_len
,outfile
);
839 fwrite(og
.body
,1,og
.body_len
,outfile
);
843 int result
=ogg_stream_flush(&vo
,&og
);
846 fprintf(stderr
,"Internal Ogg library error.\n");
850 fwrite(og
.header
,1,og
.header_len
,outfile
);
851 fwrite(og
.body
,1,og
.body_len
,outfile
);
855 /* setup complete. Raw processing loop */
856 fprintf(stderr
,"Compressing....\n");
861 /* is there an audio page flushed? If not, fetch one if possible */
862 audioflag
=fetch_and_process_audio(audio
,&audiopage
,&vo
,&vd
,&vb
,audioflag
);
864 /* is there a video page flushed? If not, fetch one if possible */
865 videoflag
=fetch_and_process_video(video
,&videopage
,&to
,&td
,videoflag
);
867 /* no pages of either? Must be end of stream. */
868 if(!audioflag
&& !videoflag
)break;
870 /* which is earlier; the end of the audio page or the end of the
871 video page? Flush the earlier to stream */
873 int audio_or_video
=-1;
875 audioflag
?vorbis_granule_time(&vd
,ogg_page_granulepos(&audiopage
)):-1;
877 videoflag
?theora_granule_time(&td
,ogg_page_granulepos(&videopage
)):-1;
881 } else if(!videoflag
) {
884 if(audiotime
<videotime
)
890 if(audio_or_video
==1){
891 /* flush a video page */
892 video_bytesout
+=fwrite(videopage
.header
,1,videopage
.header_len
,outfile
);
893 video_bytesout
+=fwrite(videopage
.body
,1,videopage
.body_len
,outfile
);
898 /* flush an audio page */
899 audio_bytesout
+=fwrite(audiopage
.header
,1,audiopage
.header_len
,outfile
);
900 audio_bytesout
+=fwrite(audiopage
.body
,1,audiopage
.body_len
,outfile
);
905 int hundredths
=timebase
*100-(long)timebase
*100;
906 int seconds
=(long)timebase
%60;
907 int minutes
=((long)timebase
/60)%60;
908 int hours
=(long)timebase
/3600;
911 vkbps
=rint(video_bytesout
*8./timebase
*.001);
913 akbps
=rint(audio_bytesout
*8./timebase
*.001);
916 "\r %d:%02d:%02d.%02d audio: %dkbps video: %dkbps ",
917 hours
,minutes
,seconds
,hundredths
,akbps
,vkbps
);
923 /* clear out state */
926 ogg_stream_clear(&vo
);
927 vorbis_block_clear(&vb
);
928 vorbis_dsp_clear(&vd
);
929 vorbis_comment_clear(&vc
);
930 vorbis_info_clear(&vi
);
933 ogg_stream_clear(&to
);
937 if(outfile
&& outfile
!=stdout
)fclose(outfile
);
939 fprintf(stderr
,"\r \ndone.\n\n");
941 #ifdef THEORA_PERF_DATA
943 QueryPerformanceCounter(&final_time
);
944 elapsed_ticks
= final_time
.QuadPart
- start_time
.QuadPart
;
946 QueryPerformanceFrequency(&ticks_per_second
);
947 elapsed_secs
= elapsed_ticks
/ ticks_per_second
.QuadPart
;
948 elapsed_sec_mod
= elapsed_ticks
% ticks_per_second
.QuadPart
;
949 elapsed_secs_dbl
= elapsed_secs
;
950 elapsed_secs_dbl
+= ((double)elapsed_sec_mod
/ (double)ticks_per_second
.QuadPart
);
951 printf("Encode time = %lld ticks\n", elapsed_ticks
);
952 printf("~%lld and %lld / %lld seconds\n", elapsed_secs
, elapsed_sec_mod
, ticks_per_second
.QuadPart
);
953 printf("~%Lf seconds\n", elapsed_secs_dbl
);