From d95d39e77128f33a9e0684b3d64185e3b48f4a92 Mon Sep 17 00:00:00 2001 From: tterribe Date: Fri, 4 Jan 2008 20:21:30 +0000 Subject: [PATCH] Remove the old encoder_example to make way for one using the new theora-exp API. git-svn-id: http://svn.xiph.org/trunk@14363 0101bb08-14d6-0310-b084-bc0e0c8e3800 --- theora/examples/encoder_example.c | 1094 ------------------------------------- 1 file changed, 1094 deletions(-) delete mode 100644 theora/examples/encoder_example.c diff --git a/theora/examples/encoder_example.c b/theora/examples/encoder_example.c deleted file mode 100644 index 0bfc2f6aa..000000000 --- a/theora/examples/encoder_example.c +++ /dev/null @@ -1,1094 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: example encoder application; makes an Ogg Theora/Vorbis - file from YUV4MPEG2 and WAV input - last mod: $Id$ - - ********************************************************************/ - -#if !defined(_GNU_SOURCE) -#define _GNU_SOURCE -#endif -#if !defined(_LARGEFILE_SOURCE) -#define _LARGEFILE_SOURCE -#endif -#if !defined(_LARGEFILE64_SOURCE) -#define _LARGEFILE64_SOURCE -#endif -#if !defined(_FILE_OFFSET_BITS) -#define _FILE_OFFSET_BITS 64 -#endif - -/* Define to give performance data win32 only*/ -//#define THEORA_PERF_DATA -#ifdef THEORA_PERF_DATA -#include -#endif - -#ifdef HAVE_CONFIG_H -# include - -#endif - -#ifndef _REENTRANT -# define _REENTRANT -#endif - -#include -#ifndef _WIN32 -#include -#include -#else -#include "getopt.h" -#endif -#ifndef _WIN32 -#endif -#include -#include -#include -#include -#include "theora/theora.h" -#include "vorbis/codec.h" -#include "vorbis/vorbisenc.h" - -#ifdef _WIN32 -/* supply missing headers and functions to Win32 */ - -#include - -static double rint(double x) -{ - if (x < 0.0) - return (double)(int)(x - 0.5); - else - return (double)(int)(x + 0.5); -} -#endif - -const char *optstring = "b:e:o:a:A:v:V:s:S:f:F:n:m:k:"; -struct option options [] = { - {"begin-time",required_argument,NULL,'b'}, - {"end-time",required_argument,NULL,'e'}, - {"output",required_argument,NULL,'o'}, - {"audio-rate-target",required_argument,NULL,'A'}, - {"video-rate-target",required_argument,NULL,'V'}, - {"audio-quality",required_argument,NULL,'a'}, - {"video-quality",required_argument,NULL,'v'}, - {"aspect-numerator",optional_argument,NULL,'s'}, - {"aspect-denominator",optional_argument,NULL,'S'}, - {"framerate-numerator",optional_argument,NULL,'f'}, - {"framerate-denominator",optional_argument,NULL,'F'}, - {"noise-sensitivity",required_argument,NULL,'n'}, - {"sharpness",required_argument,NULL,'m'}, - {"keyframe-freq",required_argument,NULL,'k'}, - {NULL,0,NULL,0} -}; - -/* You'll go to Hell for using globals. */ - -FILE *audio=NULL; -FILE *video=NULL; - -int audio_ch=0; -int audio_hz=0; - -float audio_q=.1; -int audio_r=-1; - -int video_x=0; -int video_y=0; -int frame_x=0; -int frame_y=0; -int frame_x_offset=0; -int frame_y_offset=0; -int video_hzn=-1; -int video_hzd=-1; -int video_an=-1; -int video_ad=-1; - -int video_r=-1; -int video_q=16; -int noise_sensitivity=1; -int sharpness=0; -int keyframe_frequency=64; - -long begin_sec=-1; -long begin_usec=0; -long end_sec=-1; -long end_usec=0; - -static void usage(void){ - fprintf(stderr, - "Usage: encoder_example [options] [audio_file] video_file\n\n" - "Options: \n\n" - " -o --output file name for encoded output;\n" - " If this option is not given, the\n" - " compressed data is sent to stdout.\n\n" - " -A --audio-rate-target bitrate target for Vorbis audio;\n" - " use -a and not -A if at all possible,\n" - " as -a gives higher quality for a given\n" - " bitrate.\n\n" - " -V --video-rate-target bitrate target for Theora video\n\n" - " -a --audio-quality Vorbis quality selector from -1 to 10\n" - " (-1 yields smallest files but lowest\n" - " fidelity; 10 yields highest fidelity\n" - " but large files. '2' is a reasonable\n" - " default).\n\n" - " -v --video-quality Theora quality selector fro 0 to 10\n" - " (0 yields smallest files but lowest\n" - " video quality. 10 yields highest\n" - " fidelity but large files).\n\n" - " -s --aspect-numerator Aspect ratio numerator, default is 0\n" - " or extracted from YUV input file\n" - " -S --aspect-denominator Aspect ratio denominator, default is 0\n" - " or extracted from YUV input file\n" - " -f --framerate-numerator Frame rate numerator, can be extracted\n" - " from YUV input file. ex: 30000000\n" - " -F --framerate-denominator Frame rate denominator, can be extracted\n" - " from YUV input file. ex: 1000000\n" - " The frame rate nominator divided by this\n" - " determinates the frame rate in units per tick\n" - " -n --noise-sensitivity Theora noise sensitivity selector from 0\n" - " to 6 (0 yields best quality but larger\n" - " files, defaults to 1)\n" - " -m --sharpness Theora sharpness selector from 0 to 2\n" - " (0 yields crispest video at the cost of\n" - " larger files, selecting 2 can greatly\n" - " reduce file size but resulting video\n" - " is blurrier, defaults to 0)\n" - " -k --keyframe-freq Keyframe frequency from 8 to 1000\n" - " -b --begin-time Begin encoding at offset into input\n" - " -e --end-time End encoding at offset into input\n" - "encoder_example accepts only uncompressed RIFF WAV format audio and\n" - "YUV4MPEG2 uncompressed video.\n\n"); - exit(1); -} - -static void id_file(char *f){ - FILE *test; - unsigned char buffer[80]; - int ret; - int tmp_video_hzn = -1, - tmp_video_hzd = -1, - tmp_video_an = -1, - tmp_video_ad = -1; - int extra_hdr_bytes; - - /* open it, look for magic */ - - if(!strcmp(f,"-")){ - /* stdin */ - test=stdin; - }else{ - test=fopen(f,"rb"); - if(!test){ - fprintf(stderr,"Unable to open file %s.\n",f); - exit(1); - } - } - - ret=fread(buffer,1,4,test); - if(ret<4){ - fprintf(stderr,"EOF determining file type of file %s.\n",f); - exit(1); - } - - if(!memcmp(buffer,"RIFF",4)){ - /* possible WAV file */ - - if(audio){ - /* umm, we already have one */ - fprintf(stderr,"Multiple RIFF WAVE files specified on command line.\n"); - exit(1); - } - - /* Parse the rest of the header */ - - ret=fread(buffer,1,4,test); - ret=fread(buffer,1,4,test); - if(ret<4)goto riff_err; - if(!memcmp(buffer,"WAVE",4)){ - - while(!feof(test)){ - ret=fread(buffer,1,4,test); - if(ret<4)goto riff_err; - if(!memcmp("fmt",buffer,3)){ - - /* OK, this is our audio specs chunk. Slurp it up. */ - - ret=fread(buffer,1,20,test); - if(ret<20)goto riff_err; - - extra_hdr_bytes = (buffer[0] + (buffer[1] << 8) + - (buffer[2] << 16) + (buffer[3] << 24)) - 16; - - if(memcmp(buffer+4,"\001\000",2)){ - fprintf(stderr,"The WAV file %s is in a compressed format; " - "can't read it.\n",f); - exit(1); - } - - audio=test; - audio_ch=buffer[6]+(buffer[7]<<8); - audio_hz=buffer[8]+(buffer[9]<<8)+ - (buffer[10]<<16)+(buffer[11]<<24); - - if(buffer[18]+(buffer[19]<<8)!=16){ - fprintf(stderr,"Can only read 16 bit WAV files for now.\n"); - exit(1); - } - - /* read past extra header bytes */ - while(extra_hdr_bytes){ - int read_size = (extra_hdr_bytes > sizeof(buffer)) ? - sizeof(buffer) : extra_hdr_bytes; - ret = fread(buffer, 1, read_size, test); - - if (ret < read_size) - goto riff_err; - else - extra_hdr_bytes -= read_size; - } - - /* Now, align things to the beginning of the data */ - /* Look for 'dataxxxx' */ - while(!feof(test)){ - ret=fread(buffer,1,4,test); - if(ret<4)goto riff_err; - if(!memcmp("data",buffer,4)){ - /* We're there. Ignore the declared size for now. */ - ret=fread(buffer,1,4,test); - if(ret<4)goto riff_err; - - fprintf(stderr,"File %s is 16 bit %d channel %d Hz RIFF WAV audio.\n", - f,audio_ch,audio_hz); - - return; - } - } - } - } - } - - fprintf(stderr,"Couldn't find WAVE data in RIFF file %s.\n",f); - exit(1); - - } - if(!memcmp(buffer,"YUV4",4)){ - /* possible YUV2MPEG2 format file */ - /* read until newline, or 80 cols, whichever happens first */ - /* NB the mjpegtools spec doesn't define a length limit */ - int i,j; - for(i=0;i<79;i++){ - ret=fread(buffer+i,1,1,test); - if(ret<1)goto yuv_err; - if(buffer[i]=='\n')break; - } - if(i==79){ - fprintf(stderr,"Error parsing %s header; not a YUV2MPEG2 file?\n",f); - } - buffer[i]='\0'; - - if(!memcmp(buffer,"MPEG",4)){ - char interlace = '?'; - - if(video){ - /* umm, we already have one */ - fprintf(stderr,"Multiple video files specified on command line.\n"); - exit(1); - } - - if(buffer[4]!='2'){ - fprintf(stderr,"Incorrect YUV input file version; YUV4MPEG2 required.\n"); - } - - /* parse the frame header */ - j = 5; - while (j < i) { - if ((buffer[j] != ' ') && (buffer[j-1] == ' ')) - switch (buffer[j]) { - case 'W': frame_x = atoi((char*)&buffer[j+1]); break; - case 'H': frame_y = atoi((char*)&buffer[j+1]); break; - case 'C': /* chroma subsampling */ break; - case 'I': interlace = buffer[j+1]; break; - case 'F': /* frame rate ratio */ - tmp_video_hzn = atoi((char*)&buffer[j+1]); - while ((buffer[j] != ':') && (j < i)) j++; - tmp_video_hzd = atoi((char*)&buffer[j+1]); - break; - case 'A': /* sample aspect ratio */ - tmp_video_an = atoi((char*)&buffer[j+1]); - while ((buffer[j] != ':') && (j < i)) j++; - tmp_video_ad = atoi((char*)&buffer[j+1]); - break; - case 'X': /* metadata */ break; - default: - fprintf(stderr, "unrecognized stream header tag '%c'\n", buffer[j]); - break; - } - j++; - } - /* verify data from the stream header */ - if (frame_x <= 0) { - fprintf(stderr,"Error parsing YUV4MPEG2 header:" - " missing width tag in file %s.\n", f); - exit(1); - } - if (frame_y <= 0) { - fprintf(stderr,"Error parsing YUV4MPEG2 header:" - " missing height tag in file %s.\n", f); - exit(1); - } - if (tmp_video_hzn < 0 || tmp_video_hzd < 0) { - /* default to 30 fps */ - tmp_video_hzn = 30; tmp_video_hzd = 1; - fprintf(stderr,"Warning: no framerate defined in file %s.\n", f); - } - if (tmp_video_an < 0 || tmp_video_ad < 0) { - /* default to unknown */ - tmp_video_an = 0; tmp_video_ad = 0; - } - - /* update fps and aspect ratio globals if not specified in the command line */ - if (video_hzn==-1) video_hzn = tmp_video_hzn; - if (video_hzd==-1) video_hzd = tmp_video_hzd; - if (video_an==-1) video_an = tmp_video_an; - if (video_ad==-1) video_ad = tmp_video_ad; - - if(interlace=='?'){ - fprintf(stderr,"Warning: input video isn't marked for interlacing;" - " treating this\nas progressive scan video." - " Deinterlace first if you get poor results.\n"); - }else if(interlace!='p'){ - fprintf(stderr,"Input video is interlaced; Theora handles only progressive scan\n"); - exit(1); - } - - video=test; - - fprintf(stderr,"File %s is %dx%d %.02f fps YUV12 video.\n", - f,frame_x,frame_y,(double)video_hzn/video_hzd); - - return; - } - } - fprintf(stderr,"Input file %s is neither a WAV nor YUV4MPEG2 file.\n",f); - exit(1); - - riff_err: - fprintf(stderr,"EOF parsing RIFF file %s.\n",f); - exit(1); - yuv_err: - fprintf(stderr,"EOF parsing YUV4MPEG2 file %s.\n",f); - exit(1); - -} - -int spinner=0; -char *spinascii="|/-\\"; -void spinnit(void){ - spinner++; - if(spinner==4)spinner=0; - fprintf(stderr,"\r%c",spinascii[spinner]); -} - -int fetch_and_process_audio(FILE *audio,ogg_page *audiopage, - ogg_stream_state *vo, - vorbis_dsp_state *vd, - vorbis_block *vb, - int audioflag){ - static ogg_int64_t samples_sofar=0; - ogg_packet op; - int i,j; - ogg_int64_t beginsample = audio_hz*begin_sec + audio_hz*begin_usec/1000000; - ogg_int64_t endsample = audio_hz*end_sec + audio_hz*end_usec/1000000; - - while(audio && !audioflag){ - /* process any audio already buffered */ - spinnit(); - if(ogg_stream_pageout(vo,audiopage)>0) return 1; - if(ogg_stream_eos(vo))return 0; - - { - /* read and process more audio */ - signed char readbuffer[4096]; - signed char *readptr=readbuffer; - int toread=4096/2/audio_ch; - int bytesread=fread(readbuffer,1,toread*2*audio_ch,audio); - int sampread=bytesread/2/audio_ch; - float **vorbis_buffer; - int count=0; - - if(bytesread<=0 || - (samples_sofar>=endsample && endsample>0)){ - /* end of file. this can be done implicitly, but it's - easier to see here in non-clever fashion. Tell the - library we're at end of stream so that it can handle the - last frame and mark end of stream in the output properly */ - vorbis_analysis_wrote(vd,0); - }else{ - if(samples_sofar < beginsample){ - if(samples_sofar+sampread > beginsample){ - readptr += (beginsample-samples_sofar)*2*audio_ch; - sampread += samples_sofar-beginsample; - samples_sofar = sampread+beginsample; - }else{ - samples_sofar += sampread; - sampread = 0; - } - }else{ - samples_sofar += sampread; - } - - if(samples_sofar > endsample && endsample > 0) - sampread-= (samples_sofar - endsample); - - if(sampread>0){ - - vorbis_buffer=vorbis_analysis_buffer(vd,sampread); - /* uninterleave samples */ - for(i=0;i0) return 1; - if(ogg_stream_eos(to)) return 0; - - { - /* read and process more video */ - /* video strategy reads one frame ahead so we know when we're - at end of stream and can mark last video frame as such - (vorbis audio has to flush one frame past last video frame - due to overlap and thus doesn't need this extra work */ - - /* have two frame buffers full (if possible) before - proceeding. after first pass and until eos, one will - always be full when we get here */ - - for(;state<2 && (frames=beginframe) - state++; - - } - - if(state<1){ - /* can't get here unless YUV4MPEG stream has no video */ - fprintf(stderr,"Video input contains no frames.\n"); - exit(1); - } - - /* Theora is a one-frame-in,one-frame-out system; submit a frame - for compression and pull out the packet */ - - { - yuv.y_width=video_x; - yuv.y_height=video_y; - yuv.y_stride=video_x; - - yuv.uv_width=video_x/2; - yuv.uv_height=video_y/2; - yuv.uv_stride=video_x/2; - - yuv.y= yuvframe[0]; - yuv.u= yuvframe[0]+ video_x*video_y; - yuv.v= yuvframe[0]+ video_x*video_y*5/4 ; - } - - theora_encode_YUVin(td,&yuv); - - /* if there's only one frame, it's the last in the stream */ - if(state<2) - theora_encode_packetout(td,1,&op); - else - theora_encode_packetout(td,0,&op); - - ogg_stream_packetin(to,&op); - - { - unsigned char *temp=yuvframe[0]; - yuvframe[0]=yuvframe[1]; - yuvframe[1]=temp; - state--; - } - - } - } - return videoflag; -} - -int main(int argc,char *const *argv){ - int c,long_option_index,ret; - - ogg_stream_state to; /* take physical pages, weld into a logical - stream of packets */ - ogg_stream_state vo; /* take physical pages, weld into a logical - stream of packets */ - ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */ - ogg_packet op; /* one raw packet of data for decode */ - - theora_state td; - theora_info ti; - theora_comment tc; - - vorbis_info vi; /* struct that stores all the static vorbis bitstream - settings */ - vorbis_comment vc; /* struct that stores all the user comments */ - - vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ - vorbis_block vb; /* local working space for packet->PCM decode */ - - int audioflag=0; - int videoflag=0; - int akbps=0; - int vkbps=0; - - ogg_int64_t audio_bytesout=0; - ogg_int64_t video_bytesout=0; - double timebase; - - - FILE* outfile = stdout; - -#ifdef _WIN32 -# ifdef THEORA_PERF_DATA - LARGE_INTEGER start_time; - LARGE_INTEGER final_time; - - LONGLONG elapsed_ticks; - LARGE_INTEGER ticks_per_second; - - LONGLONG elapsed_secs; - LONGLONG elapsed_sec_mod; - double elapsed_secs_dbl ; -# endif - /* We need to set stdin/stdout to binary mode. Damn windows. */ - /* if we were reading/writing a file, it would also need to in - binary mode, eg, fopen("file.wav","wb"); */ - /* Beware the evil ifdef. We avoid these where we can, but this one we - cannot. Don't add any more, you'll probably go to hell if you do. */ - _setmode( _fileno( stdin ), _O_BINARY ); - _setmode( _fileno( stdout ), _O_BINARY ); - - -#endif - - while((c=getopt_long(argc,argv,optstring,options,&long_option_index))!=EOF){ - switch(c){ - case 'o': - outfile=fopen(optarg,"wb"); - if(outfile==NULL){ - fprintf(stderr,"Unable to open output file '%s'\n", optarg); - exit(1); - } - break;; - - case 'a': - audio_q=atof(optarg)*.099; - if(audio_q<-.1 || audio_q>1){ - fprintf(stderr,"Illegal audio quality (choose -1 through 10)\n"); - exit(1); - } - audio_r=-1; - break; - - case 'v': - video_q=rint(atof(optarg)*6.3); - if(video_q<0 || video_q>63){ - fprintf(stderr,"Illegal video quality (choose 0 through 10)\n"); - exit(1); - } - video_r=0; - break; - - case 'A': - audio_r=atof(optarg)*1000; - if(audio_q<0){ - fprintf(stderr,"Illegal audio quality (choose > 0 please)\n"); - exit(1); - } - audio_q=-99; - break; - - case 'V': - video_r=rint(atof(optarg)*1000); - if(video_r<45000 || video_r>2000000){ - fprintf(stderr,"Illegal video bitrate (choose 45kbps through 2000kbps)\n"); - exit(1); - } - video_q=0; - break; - - case 's': - video_an=rint(atof(optarg)); - break; - - case 'S': - video_ad=rint(atof(optarg)); - break; - - case 'f': - video_hzn=rint(atof(optarg)); - break; - - case 'F': - video_hzd=rint(atof(optarg)); - break; - - case 'n': - noise_sensitivity=rint(atof(optarg)); - if(noise_sensitivity<0 || noise_sensitivity>6){ - fprintf(stderr,"Illegal noise sensitivity (choose 0 through 6)\n"); - exit(1); - } - break; - - case 'm': - sharpness=rint(atof(optarg)); - if(sharpness<0 || sharpness>2){ - fprintf(stderr,"Illegal sharpness (choose 0 through 2)\n"); - exit(1); - } - break; - - case 'k': - keyframe_frequency=rint(atof(optarg)); - if(keyframe_frequency<8 || keyframe_frequency>1000){ - fprintf(stderr,"Illegal keyframe frequency (choose 8 through 1000)\n"); - exit(1); - } - break; - - case 'b': - { - char *pos=strchr(optarg,':'); - begin_sec=atol(optarg); - if(pos){ - char *pos2=strchr(++pos,':'); - begin_sec*=60; - begin_sec+=atol(pos); - if(pos2){ - pos2++; - begin_sec*=60; - begin_sec+=atol(pos2); - }else{ - pos2=pos; - } - pos2=strchr(pos2,'.'); - if(pos2){ - pos2++; - begin_usec=atol(pos2); - } - } - } - break; - case 'e': - { - char *pos=strchr(optarg,':'); - end_sec=atol(optarg); - if(pos){ - char *pos2=strchr(++pos,':'); - end_sec*=60; - end_sec+=atol(pos); - if(pos2){ - pos2++; - end_sec*=60; - end_sec+=atol(pos2); - }else{ - pos2=pos; - } - pos2=strchr(pos2,'.'); - if(pos2){ - pos2++; - end_usec=atol(pos2); - } - } - } - break; - default: - usage(); - } - } - - while(optind>4)<<4; - video_y=((frame_y + 15) >>4)<<4; - /* We force the offset to be even. - This ensures that the chroma samples align properly with the luma - samples. */ - frame_x_offset=((video_x-frame_x)/2)&~1; - frame_y_offset=((video_y-frame_y)/2)&~1; - - theora_info_init(&ti); - ti.width=video_x; - ti.height=video_y; - ti.frame_width=frame_x; - ti.frame_height=frame_y; - ti.offset_x=frame_x_offset; - ti.offset_y=frame_y_offset; - ti.fps_numerator=video_hzn; - ti.fps_denominator=video_hzd; - ti.aspect_numerator=video_an; - ti.aspect_denominator=video_ad; - ti.colorspace=OC_CS_UNSPECIFIED; - ti.pixelformat=OC_PF_420; - ti.target_bitrate=video_r; - ti.quality=video_q; - - ti.dropframes_p=0; - ti.quick_p=1; - ti.keyframe_auto_p=1; - ti.keyframe_frequency=keyframe_frequency; - ti.keyframe_frequency_force=keyframe_frequency; - ti.keyframe_data_target_bitrate=video_r*1.5; - ti.keyframe_auto_threshold=80; - ti.keyframe_mindistance=8; - ti.noise_sensitivity=noise_sensitivity; - ti.sharpness=sharpness; - - theora_encode_init(&td,&ti); - theora_info_clear(&ti); - - /* initialize Vorbis too, assuming we have audio to compress. */ - if(audio){ - vorbis_info_init(&vi); - if(audio_q>-99) - ret = vorbis_encode_init_vbr(&vi,audio_ch,audio_hz,audio_q); - else - ret = vorbis_encode_init(&vi,audio_ch,audio_hz,-1,audio_r,-1); - if(ret){ - fprintf(stderr,"The Vorbis encoder could not set up a mode according to\n" - "the requested quality or bitrate.\n\n"); - exit(1); - } - - vorbis_comment_init(&vc); - vorbis_analysis_init(&vd,&vi); - vorbis_block_init(&vd,&vb); - } - - /* write the bitstream header packets with proper page interleave */ - - /* first packet will get its own page automatically */ - theora_encode_header(&td,&op); - ogg_stream_packetin(&to,&op); - if(ogg_stream_pageout(&to,&og)!=1){ - fprintf(stderr,"Internal Ogg library error.\n"); - exit(1); - } - fwrite(og.header,1,og.header_len,outfile); - fwrite(og.body,1,og.body_len,outfile); - - /* create the remaining theora headers */ - theora_comment_init(&tc); - theora_encode_comment(&tc,&op); - ogg_stream_packetin(&to,&op); - /*theora_encode_comment() doesn't take a theora_state parameter, so it has to - allocate its own buffer to pass back the packet data. - If we don't free it here, we'll leak. - libogg2 makes this much cleaner: the stream owns the buffer after you call - packetin in libogg2, but this is not true in libogg1.*/ - free(op.packet); - theora_encode_tables(&td,&op); - ogg_stream_packetin(&to,&op); - - if(audio){ - ogg_packet header; - ogg_packet header_comm; - ogg_packet header_code; - - vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code); - ogg_stream_packetin(&vo,&header); /* automatically placed in its own - page */ - if(ogg_stream_pageout(&vo,&og)!=1){ - fprintf(stderr,"Internal Ogg library error.\n"); - exit(1); - } - fwrite(og.header,1,og.header_len,outfile); - fwrite(og.body,1,og.body_len,outfile); - - /* remaining vorbis header packets */ - ogg_stream_packetin(&vo,&header_comm); - ogg_stream_packetin(&vo,&header_code); - } - - /* Flush the rest of our headers. This ensures - the actual data in each stream will start - on a new page, as per spec. */ - while(1){ - int result = ogg_stream_flush(&to,&og); - if(result<0){ - /* can't get here */ - fprintf(stderr,"Internal Ogg library error.\n"); - exit(1); - } - if(result==0)break; - fwrite(og.header,1,og.header_len,outfile); - fwrite(og.body,1,og.body_len,outfile); - } - if(audio){ - while(1){ - int result=ogg_stream_flush(&vo,&og); - if(result<0){ - /* can't get here */ - fprintf(stderr,"Internal Ogg library error.\n"); - exit(1); - } - if(result==0)break; - fwrite(og.header,1,og.header_len,outfile); - fwrite(og.body,1,og.body_len,outfile); - } - } - - /* setup complete. Raw processing loop */ - fprintf(stderr,"Compressing....\n"); - while(1){ - ogg_page audiopage; - ogg_page videopage; - - /* is there an audio page flushed? If not, fetch one if possible */ - audioflag=fetch_and_process_audio(audio,&audiopage,&vo,&vd,&vb,audioflag); - - /* is there a video page flushed? If not, fetch one if possible */ - videoflag=fetch_and_process_video(video,&videopage,&to,&td,videoflag); - - /* no pages of either? Must be end of stream. */ - if(!audioflag && !videoflag)break; - - /* which is earlier; the end of the audio page or the end of the - video page? Flush the earlier to stream */ - { - int audio_or_video=-1; - double audiotime= - audioflag?vorbis_granule_time(&vd,ogg_page_granulepos(&audiopage)):-1; - double videotime= - videoflag?theora_granule_time(&td,ogg_page_granulepos(&videopage)):-1; - - if(!audioflag){ - audio_or_video=1; - } else if(!videoflag) { - audio_or_video=0; - } else { - if(audiotime