[xiph-commits] r8216 - trunk/ffmpeg2theora
j at motherfish-iii.xiph.org
j at motherfish-iii.xiph.org
Thu Nov 18 03:41:30 PST 2004
Author: j
Date: 2004-11-18 03:41:29 -0800 (Thu, 18 Nov 2004)
New Revision: 8216
Modified:
trunk/ffmpeg2theora/ffmpeg2theora.c
trunk/ffmpeg2theora/theorautils.c
trunk/ffmpeg2theora/theorautils.h
Log:
patch by ralph
- add metadata(artist,title,date etc) commandline options
- get rig on global theoraframes_info in theorautils.c
Modified: trunk/ffmpeg2theora/ffmpeg2theora.c
===================================================================
--- trunk/ffmpeg2theora/ffmpeg2theora.c 2004-11-17 22:31:42 UTC (rev 8215)
+++ trunk/ffmpeg2theora/ffmpeg2theora.c 2004-11-18 11:41:29 UTC (rev 8216)
@@ -425,7 +425,7 @@
info.sample_rate = this->sample_rate;
info.vorbis_quality = this->audio_quality;
info.vorbis_bitrate = this->audio_bitrate;
- theoraframes_init ();
+ theoraframes_init (&info);
/* main decoding loop */
do{
@@ -491,7 +491,7 @@
}
first=0;
//now output_resized
- if(theoraframes_add_video(output_resized->data[0],
+ if(theoraframes_add_video(&info, output_resized->data[0],
this->video_x,this->video_y,output_resized->linesize[0],e_o_s)){
//this->output_width,this->output_height,output_resized->linesize[0],e_o_s)){
ret = -1;
@@ -529,7 +529,7 @@
resampled=audio_buf;
}
}
- if (theoraframes_add_audio(resampled,
+ if (theoraframes_add_audio(&info, resampled,
samples_out *(this->channels),samples_out,e_o_s)){
ret = -1;
fprintf (stderr,"No audio frames available\n");
@@ -541,7 +541,7 @@
}
/* flush out the file */
- theoraframes_flush (e_o_s);
+ theoraframes_flush (&info, e_o_s);
av_free_packet (&pkt);
}
while (ret >= 0);
@@ -557,7 +557,7 @@
if (this->audio_resample_ctx)
audio_resample_close(this->audio_resample_ctx);
- theoraframes_close ();
+ theoraframes_close (&info);
}
else{
fprintf (stderr, "No video or audio stream found\n");
@@ -631,31 +631,45 @@
fprintf (stderr,
PACKAGE " " PACKAGE_VERSION "\n\n"
" usage: " PACKAGE " [options] input\n\n"
- " Options:\n"
+
+ "Output options:\n"
"\t --output,-o\t\talternative output\n"
- "\t --format,-f\t\tspecify input format\n"
"\t --width, -x\t\tscale to given size\n"
"\t --height,-y\t\tscale to given size\n"
"\t --aspect\t\tdefine frame aspect ratio: i.e. 4:3 or 16:9\n"
- "\t --crop[top|bottom|left|right]\tcrop input before resizing\n"
- "\t --deinterlace,-d \t\t[off|on] disable deinterlace, \n"
- "\t\t\t\t\tenabled by default right now\n"
- "\t --videoquality,-v\t[0 to 10] encoding quality for video\n"
- "\t --videobitrate,-V\t[45 to 2000] encoding bitrate for video [recommended for streaming]\n"
- "\t --audioquality,-a\t[-1 to 10] encoding quality for audio\n"
- "\t --audiobitrate,-A\t[45 to 2000] encoding bitrate for audio [recommended for streaming]\n"
- "\t --samplerate,-H\t\tset output samplerate in Hz\n"
+ "\t --crop[top|bottom|left|right]\tcrop input before resizing\n"
+ "\t --videoquality,-v\t[0 to 10] encoding quality for video\n"
+ "\t --videobitrate,-V\t[45 to 2000] encoding bitrate for video\n"
+ "\t --audioquality,-a\t[-1 to 10] encoding quality for audio\n"
+ "\t --audiobitrate,-A\t[45 to 2000] encoding bitrate for audio\n"
+ "\t --samplerate,-H\tset output samplerate in Hz\n"
"\t --nosound\t\tdisable the sound from input\n"
- "\t --inputfps [fps]\t\toverride input fps\n"
- "\n"
"\t --v2v-preset,-p\tencode file with v2v preset, \n"
"\t\t\t\t right now there is preview and pro,\n"
"\t\t\t\t '"PACKAGE" -p info' for more informations\n"
+
+ "\nInput options:\n"
+ "\t --deinterlace,-d \t[off|on] disable deinterlace, \n"
+ "\t\t\t\t\t enabled by default right now\n"
+ "\t --format,-f\t\tspecify input format\n"
+ "\t --inputfps [fps]\toverride input fps\n"
+
+ "\nMetadata options:\n"
+ "\t --artist\tName of artist\n"
+ "\t --title\tTitle\n"
+ "\t --date\t\tDate\n"
+ "\t --location\tLocation\n"
+ "\t --organizaion\tName of organization\n"
+ "\t --copyright\tCopyright\n"
+ "\t --license\tLicence\n"
+ "\nOther options:\n"
#ifndef _WIN32
"\t --nice\t\t\tset niceness to n\n"
#endif
"\t --debug\t\toutput some more information during encoding\n"
"\t --help,-h\t\tthis message\n"
+
+
"\n Examples:\n"
"\tffmpeg2theora videoclip.avi (will write output to videoclip.avi.ogg)\n\n"
@@ -683,6 +697,7 @@
static int nosound_flag=0;
static int aspect_flag=0;
static int inputfps_flag=0;
+ static int metadata_flag=0;
AVInputFormat *input_fmt=NULL;
ff2theora convert = ff2theora_init ();
@@ -711,7 +726,15 @@
{"cropright",required_argument,&cropright_flag,1},
{"cropleft",required_argument,&cropleft_flag,1},
{"inputfps",required_argument,&inputfps_flag,1},
-
+
+ {"artist",required_argument,&metadata_flag,10},
+ {"title",required_argument,&metadata_flag,11},
+ {"date",required_argument,&metadata_flag,12},
+ {"location",required_argument,&metadata_flag,13},
+ {"organization",required_argument,&metadata_flag,14},
+ {"copyright",required_argument,&metadata_flag,15},
+ {"license",required_argument,&metadata_flag,16},
+
{"debug",0,NULL,'D'},
{"help",0,NULL,'h'},
{NULL,0,NULL,0}
@@ -721,6 +744,7 @@
}
// set some variables;
info.debug=0;
+ theora_comment_init (&info.tc);
while((c=getopt_long(argc,argv,optstring,options,&long_option_index))!=EOF){
switch(c)
@@ -755,6 +779,33 @@
convert->force_input_fps=atof(optarg);
aspect_flag=0;
}
+ /* metadata */
+ if (metadata_flag){
+ switch(metadata_flag) {
+ case 10:
+ theora_comment_add_tag(&info.tc, "ARTIST", optarg);
+ break;
+ case 11:
+ theora_comment_add_tag(&info.tc, "TITLE", optarg);
+ break;
+ case 12:
+ theora_comment_add_tag(&info.tc, "DATE", optarg);
+ break;
+ case 13:
+ theora_comment_add_tag(&info.tc, "LOCATION", optarg);
+ break;
+ case 14:
+ theora_comment_add_tag(&info.tc, "ORGANIZATION", optarg);
+ break;
+ case 15:
+ theora_comment_add_tag(&info.tc, "COPYRIGHT", optarg);
+ break;
+ case 16:
+ theora_comment_add_tag(&info.tc, "LICENSE", optarg);
+ break;
+ }
+ metadata_flag=0;
+ }
break;
case 'o':
sprintf(outputfile_name,optarg);
Modified: trunk/ffmpeg2theora/theorautils.c
===================================================================
--- trunk/ffmpeg2theora/theorautils.c 2004-11-17 22:31:42 UTC (rev 8215)
+++ trunk/ffmpeg2theora/theorautils.c 2004-11-18 11:41:29 UTC (rev 8216)
@@ -32,8 +32,6 @@
#include "theorautils.h"
-theoraframes_info info;
-
static double rint(double x)
{
if (x < 0.0)
@@ -42,30 +40,30 @@
return (double)(int)(x + 0.5);
}
-void theoraframes_init (){
- info.audio_bytesout = 0;
- info.video_bytesout = 0;
+void theoraframes_init (theoraframes_info *info){
+ info->audio_bytesout = 0;
+ info->video_bytesout = 0;
/* yayness. Set up Ogg output stream */
srand (time (NULL));
- ogg_stream_init (&info.vo, rand ());
+ ogg_stream_init (&info->vo, rand ());
- if(!info.audio_only){
- ogg_stream_init (&info.to, rand ()); /* oops, add one ot the above */
- theora_encode_init (&info.td, &info.ti);
- theora_info_clear (&info.ti);
+ if(!info->audio_only){
+ ogg_stream_init (&info->to, rand ()); /* oops, add one ot the above */
+ theora_encode_init (&info->td, &info->ti);
+ theora_info_clear (&info->ti);
}
/* init theora done */
/* initialize Vorbis too, if we have audio. */
- if(!info.video_only){
- vorbis_info_init (&info.vi);
+ if(!info->video_only){
+ vorbis_info_init (&info->vi);
/* Encoding using a VBR quality mode. */
int ret;
- if(info.vorbis_quality>-99)
- ret =vorbis_encode_init_vbr (&info.vi, info.channels,info.sample_rate,info.vorbis_quality);
+ if(info->vorbis_quality>-99)
+ ret =vorbis_encode_init_vbr (&info->vi, info->channels,info->sample_rate,info->vorbis_quality);
else
- ret=vorbis_encode_init(&info.vi,info.channels,info.sample_rate,-1,info.vorbis_bitrate,-1);
+ ret=vorbis_encode_init(&info->vi,info->channels,info->sample_rate,-1,info->vorbis_bitrate,-1);
if (ret){
fprintf (stderr,
@@ -74,11 +72,11 @@
exit (1);
}
- vorbis_comment_init (&info.vc);
- vorbis_comment_add_tag (&info.vc, "ENCODER",PACKAGE_STRING);
+ vorbis_comment_init (&info->vc);
+ vorbis_comment_add_tag (&info->vc, "ENCODER",PACKAGE_STRING);
/* set up the analysis state and auxiliary encoding storage */
- vorbis_analysis_init (&info.vd, &info.vi);
- vorbis_block_init (&info.vd, &info.vb);
+ vorbis_analysis_init (&info->vd, &info->vi);
+ vorbis_block_init (&info->vd, &info->vb);
}
/* audio init done */
@@ -86,50 +84,50 @@
/* write the bitstream header packets with proper page interleave */
/* first packet will get its own page automatically */
- if(!info.audio_only){
- theora_encode_header (&info.td, &info.op);
- ogg_stream_packetin (&info.to, &info.op);
- if (ogg_stream_pageout (&info.to, &info.og) != 1){
+ if(!info->audio_only){
+ theora_encode_header (&info->td, &info->op);
+ ogg_stream_packetin (&info->to, &info->op);
+ if (ogg_stream_pageout (&info->to, &info->og) != 1){
fprintf (stderr, "Internal Ogg library error.\n");
exit (1);
}
- fwrite (info.og.header, 1, info.og.header_len, info.outfile);
- fwrite (info.og.body, 1, info.og.body_len, info.outfile);
+ fwrite (info->og.header, 1, info->og.header_len, info->outfile);
+ fwrite (info->og.body, 1, info->og.body_len, info->outfile);
/* create the remaining theora headers */
- theora_comment_init (&info.tc);
- theora_comment_add_tag (&info.tc, "ENCODER",PACKAGE_STRING);
- theora_encode_comment (&info.tc, &info.op);
- ogg_stream_packetin (&info.to, &info.op);
- theora_encode_tables (&info.td, &info.op);
- ogg_stream_packetin (&info.to, &info.op);
+ /* theora_comment_init (&info->tc); is called in main() prior to parsing options */
+ theora_comment_add_tag (&info->tc, "ENCODER",PACKAGE_STRING);
+ theora_encode_comment (&info->tc, &info->op);
+ ogg_stream_packetin (&info->to, &info->op);
+ theora_encode_tables (&info->td, &info->op);
+ ogg_stream_packetin (&info->to, &info->op);
}
- if(!info.video_only){
+ if(!info->video_only){
ogg_packet header;
ogg_packet header_comm;
ogg_packet header_code;
- vorbis_analysis_headerout (&info.vd, &info.vc, &header,
+ vorbis_analysis_headerout (&info->vd, &info->vc, &header,
&header_comm, &header_code);
- ogg_stream_packetin (&info.vo, &header); /* automatically placed in its own
+ ogg_stream_packetin (&info->vo, &header); /* automatically placed in its own
* page */
- if (ogg_stream_pageout (&info.vo, &info.og) != 1){
+ if (ogg_stream_pageout (&info->vo, &info->og) != 1){
fprintf (stderr, "Internal Ogg library error.\n");
exit (1);
}
- fwrite (info.og.header, 1, info.og.header_len, info.outfile);
- fwrite (info.og.body, 1, info.og.body_len, info.outfile);
+ fwrite (info->og.header, 1, info->og.header_len, info->outfile);
+ fwrite (info->og.body, 1, info->og.body_len, info->outfile);
/* remaining vorbis header packets */
- ogg_stream_packetin (&info.vo, &header_comm);
- ogg_stream_packetin (&info.vo, &header_code);
+ ogg_stream_packetin (&info->vo, &header_comm);
+ ogg_stream_packetin (&info->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 && !info.audio_only){
- int result = ogg_stream_flush (&info.to, &info.og);
+ while (1 && !info->audio_only){
+ int result = ogg_stream_flush (&info->to, &info->og);
if (result < 0){
/* can't get here */
fprintf (stderr, "Internal Ogg library error.\n");
@@ -137,11 +135,11 @@
}
if (result == 0)
break;
- fwrite (info.og.header, 1, info.og.header_len, info.outfile);
- fwrite (info.og.body, 1, info.og.body_len, info.outfile);
+ fwrite (info->og.header, 1, info->og.header_len, info->outfile);
+ fwrite (info->og.body, 1, info->og.body_len, info->outfile);
}
- while (1 && !info.video_only){
- int result = ogg_stream_flush (&info.vo, &info.og);
+ while (1 && !info->video_only){
+ int result = ogg_stream_flush (&info->vo, &info->og);
if (result < 0){
/* can't get here */
fprintf (stderr,
@@ -150,8 +148,8 @@
}
if (result == 0)
break;
- fwrite (info.og.header, 1, info.og.header_len,info.outfile);
- fwrite (info.og.body, 1, info.og.body_len, info.outfile);
+ fwrite (info->og.header, 1, info->og.header_len,info->outfile);
+ fwrite (info->og.body, 1, info->og.body_len, info->outfile);
}
}
@@ -166,7 +164,7 @@
* @param linesize of data
* @param e_o_s 1 indicates ond of stream
*/
-int theoraframes_add_video (uint8_t * data, int width, int height, int linesize,int e_o_s){
+int theoraframes_add_video (theoraframes_info *info, uint8_t * data, int width, int height, int linesize,int e_o_s){
/* map some things from info struk to local variables,
* just to understand the code better */
/* pysical pages */
@@ -186,10 +184,10 @@
yuv.u = data + width * height;
yuv.v = data + width * height * 5 / 4;
}
- theora_encode_YUVin (&info.td, &yuv);
- theora_encode_packetout (&info.td, e_o_s, &info.op);
- ogg_stream_packetin (&info.to, &info.op);
- info.videoflag=1;
+ theora_encode_YUVin (&info->td, &yuv);
+ theora_encode_packetout (&info->td, e_o_s, &info->op);
+ ogg_stream_packetin (&info->to, &info->op);
+ info->videoflag=1;
return 0;
}
@@ -200,71 +198,71 @@
* @param samples samples in buffer
* @param e_o_s 1 indicates end of stream.
*/
-int theoraframes_add_audio (int16_t * buffer, int bytes, int samples, int e_o_s){
+int theoraframes_add_audio (theoraframes_info *info, int16_t * buffer, int bytes, int samples, int e_o_s){
int i,j, count = 0;
float **vorbis_buffer;
if (bytes <= 0 && samples <= 0){
/* end of audio stream */
if(e_o_s)
- vorbis_analysis_wrote (&info.vd, 0);
+ vorbis_analysis_wrote (&info->vd, 0);
}
else{
- vorbis_buffer = vorbis_analysis_buffer (&info.vd, samples);
+ vorbis_buffer = vorbis_analysis_buffer (&info->vd, samples);
/* uninterleave samples */
for (i = 0; i < samples; i++){
- for(j=0;j<info.channels;j++){
+ for(j=0;j<info->channels;j++){
vorbis_buffer[j][i] = buffer[count++] / 32768.f;
}
}
- vorbis_analysis_wrote (&info.vd, samples);
+ vorbis_analysis_wrote (&info->vd, samples);
}
- while(vorbis_analysis_blockout (&info.vd, &info.vb) == 1){
+ while(vorbis_analysis_blockout (&info->vd, &info->vb) == 1){
/* analysis, assume we want to use bitrate management */
- vorbis_analysis (&info.vb, NULL);
- vorbis_bitrate_addblock (&info.vb);
+ vorbis_analysis (&info->vb, NULL);
+ vorbis_bitrate_addblock (&info->vb);
/* weld packets into the bitstream */
- while (vorbis_bitrate_flushpacket (&info.vd, &info.op)){
- ogg_stream_packetin (&info.vo, &info.op);
+ while (vorbis_bitrate_flushpacket (&info->vd, &info->op)){
+ ogg_stream_packetin (&info->vo, &info->op);
}
}
- info.audioflag=1;
+ info->audioflag=1;
/*
- if (ogg_stream_eos (&info.vo)){
- info.audioflag = 0;
+ if (ogg_stream_eos (&info->vo)){
+ info->audioflag = 0;
return 0;
}
*/
return 0;
}
-void print_stats(double timebase){
+static void print_stats(theoraframes_info *info, double timebase){
int hundredths = timebase * 100 - (long) timebase * 100;
int seconds = (long) timebase % 60;
int minutes = ((long) timebase / 60) % 60;
int hours = (long) timebase / 3600;
- if(info.vkbps<0)
- info.vkbps=0;
- if(info.akbps<0)
- info.akbps=0;
+ if(info->vkbps<0)
+ info->vkbps=0;
+ if(info->akbps<0)
+ info->akbps=0;
- if(info.debug==1 && !info.video_only && !info.audio_only){
+ if(info->debug==1 && !info->video_only && !info->audio_only){
fprintf (stderr,"\r %d:%02d:%02d.%02d audio: %dkbps video: %dkbps diff: %.4f ",
- hours, minutes, seconds, hundredths,info.akbps, info.vkbps,info.audiotime-info.videotime);
+ hours, minutes, seconds, hundredths,info->akbps, info->vkbps,info->audiotime-info->videotime);
}
else{
fprintf (stderr,"\r %d:%02d:%02d.%02d audio: %dkbps video: %dkbps ",
- hours, minutes, seconds, hundredths,info.akbps, info.vkbps);
+ hours, minutes, seconds, hundredths,info->akbps, info->vkbps);
}
}
-void theoraframes_flush (int e_o_s){
- /* flush out the ogg pages to info.outfile */
+void theoraframes_flush (theoraframes_info *info, int e_o_s){
+ /* flush out the ogg pages to info->outfile */
int flushloop=1;
@@ -272,48 +270,48 @@
int video = -1;
flushloop=0;
//some debuging
- //fprintf(stderr,"\ndiff: %f\n",info.audiotime-info.videotime);
- while(!info.audio_only && (e_o_s ||
- ((info.videotime <= info.audiotime || info.video_only) && info.videoflag == 1))){
+ //fprintf(stderr,"\ndiff: %f\n",info->audiotime-info->videotime);
+ while(!info->audio_only && (e_o_s ||
+ ((info->videotime <= info->audiotime || info->video_only) && info->videoflag == 1))){
- info.videoflag = 0;
- while(ogg_stream_pageout (&info.to, &info.videopage) > 0){
- info.videotime=
- theora_granule_time (&info.td,ogg_page_granulepos(&info.videopage));
+ info->videoflag = 0;
+ while(ogg_stream_pageout (&info->to, &info->videopage) > 0){
+ info->videotime=
+ theora_granule_time (&info->td,ogg_page_granulepos(&info->videopage));
/* flush a video page */
- info.video_bytesout +=
- fwrite (info.videopage.header, 1,info.videopage.header_len, info.outfile);
- info.video_bytesout +=
- fwrite (info.videopage.body, 1,info.videopage.body_len, info.outfile);
+ info->video_bytesout +=
+ fwrite (info->videopage.header, 1,info->videopage.header_len, info->outfile);
+ info->video_bytesout +=
+ fwrite (info->videopage.body, 1,info->videopage.body_len, info->outfile);
- info.vkbps = rint (info.video_bytesout * 8. / info.videotime * .001);
+ info->vkbps = rint (info->video_bytesout * 8. / info->videotime * .001);
- print_stats(info.videotime);
+ print_stats(info, info->videotime);
video=1;
- info.videoflag = 1;
+ info->videoflag = 1;
flushloop=1;
}
if(e_o_s)
break;
}
- while (!info.video_only && (e_o_s ||
- ((info.audiotime < info.videotime || info.audio_only) && info.audioflag==1))){
+ while (!info->video_only && (e_o_s ||
+ ((info->audiotime < info->videotime || info->audio_only) && info->audioflag==1))){
- info.audioflag = 0;
- while(ogg_stream_pageout (&info.vo, &info.audiopage) > 0){
+ info->audioflag = 0;
+ while(ogg_stream_pageout (&info->vo, &info->audiopage) > 0){
/* flush an audio page */
- info.audiotime=
- vorbis_granule_time (&info.vd,ogg_page_granulepos(&info.audiopage));
- info.audio_bytesout +=
- fwrite (info.audiopage.header, 1,info.audiopage.header_len, info.outfile);
- info.audio_bytesout +=
- fwrite (info.audiopage.body, 1,info.audiopage.body_len, info.outfile);
+ info->audiotime=
+ vorbis_granule_time (&info->vd,ogg_page_granulepos(&info->audiopage));
+ info->audio_bytesout +=
+ fwrite (info->audiopage.header, 1,info->audiopage.header_len, info->outfile);
+ info->audio_bytesout +=
+ fwrite (info->audiopage.body, 1,info->audiopage.body_len, info->outfile);
- info.akbps = rint (info.audio_bytesout * 8. / info.audiotime * .001);
- print_stats(info.audiotime);
+ info->akbps = rint (info->audio_bytesout * 8. / info->audiotime * .001);
+ print_stats(info, info->audiotime);
video=0;
- info.audioflag = 1;
+ info->audioflag = 1;
flushloop=1;
}
if(e_o_s)
@@ -322,16 +320,16 @@
}
}
-void theoraframes_close (){
- ogg_stream_clear (&info.vo);
- vorbis_block_clear (&info.vb);
- vorbis_dsp_clear (&info.vd);
- vorbis_comment_clear (&info.vc);
- vorbis_info_clear (&info.vi);
+void theoraframes_close (theoraframes_info *info){
+ ogg_stream_clear (&info->vo);
+ vorbis_block_clear (&info->vb);
+ vorbis_dsp_clear (&info->vd);
+ vorbis_comment_clear (&info->vc);
+ vorbis_info_clear (&info->vi);
- ogg_stream_clear (&info.to);
- theora_clear (&info.td);
+ ogg_stream_clear (&info->to);
+ theora_clear (&info->td);
- if (info.outfile && info.outfile != stdout)
- fclose (info.outfile);
+ if (info->outfile && info->outfile != stdout)
+ fclose (info->outfile);
}
Modified: trunk/ffmpeg2theora/theorautils.h
===================================================================
--- trunk/ffmpeg2theora/theorautils.h 2004-11-17 22:31:42 UTC (rev 8215)
+++ trunk/ffmpeg2theora/theorautils.h 2004-11-18 11:41:29 UTC (rev 8216)
@@ -73,11 +73,10 @@
}
theoraframes_info;
-
-extern void theoraframes_init ();
-extern int theoraframes_add_video (uint8_t * data, int width, int height,
+extern void theoraframes_init (theoraframes_info *info);
+extern int theoraframes_add_video (theoraframes_info *info, uint8_t * data, int width, int height,
int linesize,int e_o_s);
-extern int theoraframes_add_audio (int16_t * readbuffer, int bytesread,
+extern int theoraframes_add_audio (theoraframes_info *info, int16_t * readbuffer, int bytesread,
int samplesread,int e_o_s);
-extern void theoraframes_flush (int e_o_s);
-extern void theoraframes_close ();
+extern void theoraframes_flush (theoraframes_info *info, int e_o_s);
+extern void theoraframes_close (theoraframes_info *info);
More information about the commits
mailing list