]> icculus.org git repositories - divverent/darkplaces.git/blob - cap_ogg.c
forgot these two files
[divverent/darkplaces.git] / cap_ogg.c
1 #include <sys/types.h>
2
3 #include "quakedef.h"
4 #include "client.h"
5 #include "cap_ogg.h"
6
7 // ogg.h stuff
8 typedef int16_t ogg_int16_t;
9 typedef u_int16_t ogg_uint16_t;
10 typedef int32_t ogg_int32_t;
11 typedef u_int32_t ogg_uint32_t;
12 typedef int64_t ogg_int64_t;
13
14 typedef struct {
15   long endbyte;
16   int  endbit;
17
18   unsigned char *buffer;
19   unsigned char *ptr;
20   long storage;
21 } oggpack_buffer;
22
23 /* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/
24
25 typedef struct {
26   unsigned char *header;
27   long header_len;
28   unsigned char *body;
29   long body_len;
30 } ogg_page;
31
32 /* ogg_stream_state contains the current encode/decode state of a logical
33    Ogg bitstream **********************************************************/
34
35 typedef struct {
36   unsigned char   *body_data;    /* bytes from packet bodies */
37   long    body_storage;          /* storage elements allocated */
38   long    body_fill;             /* elements stored; fill mark */
39   long    body_returned;         /* elements of fill returned */
40
41
42   int     *lacing_vals;      /* The values that will go to the segment table */
43   ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact
44                                 this way, but it is simple coupled to the
45                                 lacing fifo */
46   long    lacing_storage;
47   long    lacing_fill;
48   long    lacing_packet;
49   long    lacing_returned;
50
51   unsigned char    header[282];      /* working space for header encode */
52   int              header_fill;
53
54   int     e_o_s;          /* set when we have buffered the last packet in the
55                              logical bitstream */
56   int     b_o_s;          /* set after we've written the initial page
57                              of a logical bitstream */
58   long    serialno;
59   long    pageno;
60   ogg_int64_t  packetno;      /* sequence number for decode; the framing
61                              knows where there's a hole in the data,
62                              but we need coupling so that the codec
63                              (which is in a seperate abstraction
64                              layer) also knows about the gap */
65   ogg_int64_t   granulepos;
66
67 } ogg_stream_state;
68
69 /* ogg_packet is used to encapsulate the data and metadata belonging
70    to a single raw Ogg/Vorbis packet *************************************/
71
72 typedef struct {
73   unsigned char *packet;
74   long  bytes;
75   long  b_o_s;
76   long  e_o_s;
77
78   ogg_int64_t  granulepos;
79   
80   ogg_int64_t  packetno;     /* sequence number for decode; the framing
81                                 knows where there's a hole in the data,
82                                 but we need coupling so that the codec
83                                 (which is in a seperate abstraction
84                                 layer) also knows about the gap */
85 } ogg_packet;
86
87 typedef struct {
88   unsigned char *data;
89   int storage;
90   int fill;
91   int returned;
92
93   int unsynced;
94   int headerbytes;
95   int bodybytes;
96 } ogg_sync_state;
97
98 /* Ogg BITSTREAM PRIMITIVES: encoding **************************/
99
100 static int      (*qogg_stream_packetin) (ogg_stream_state *os, ogg_packet *op);
101 static int      (*qogg_stream_pageout) (ogg_stream_state *os, ogg_page *og);
102 static int      (*qogg_stream_flush) (ogg_stream_state *os, ogg_page *og);
103
104 /* Ogg BITSTREAM PRIMITIVES: general ***************************/
105
106 static int      (*qogg_stream_init) (ogg_stream_state *os,int serialno);
107 static int      (*qogg_stream_clear) (ogg_stream_state *os);
108
109 // end of ogg.h stuff
110
111 // vorbis/codec.h stuff
112 typedef struct vorbis_info{
113   int version;
114   int channels;
115   long rate;
116
117   /* The below bitrate declarations are *hints*.
118      Combinations of the three values carry the following implications:
119
120      all three set to the same value:
121        implies a fixed rate bitstream
122      only nominal set:
123        implies a VBR stream that averages the nominal bitrate.  No hard
124        upper/lower limit
125      upper and or lower set:
126        implies a VBR bitstream that obeys the bitrate limits. nominal
127        may also be set to give a nominal rate.
128      none set:
129        the coder does not care to speculate.
130   */
131
132   long bitrate_upper;
133   long bitrate_nominal;
134   long bitrate_lower;
135   long bitrate_window;
136
137   void *codec_setup;
138 } vorbis_info;
139
140 /* vorbis_dsp_state buffers the current vorbis audio
141    analysis/synthesis state.  The DSP state belongs to a specific
142    logical bitstream ****************************************************/
143 typedef struct vorbis_dsp_state{
144   int analysisp;
145   vorbis_info *vi;
146
147   float **pcm;
148   float **pcmret;
149   int      pcm_storage;
150   int      pcm_current;
151   int      pcm_returned;
152
153   int  preextrapolate;
154   int  eofflag;
155
156   long lW;
157   long W;
158   long nW;
159   long centerW;
160
161   ogg_int64_t granulepos;
162   ogg_int64_t sequence;
163
164   ogg_int64_t glue_bits;
165   ogg_int64_t time_bits;
166   ogg_int64_t floor_bits;
167   ogg_int64_t res_bits;
168
169   void       *backend_state;
170 } vorbis_dsp_state;
171
172 typedef struct vorbis_block{
173   /* necessary stream state for linking to the framing abstraction */
174   float  **pcm;       /* this is a pointer into local storage */
175   oggpack_buffer opb;
176
177   long  lW;
178   long  W;
179   long  nW;
180   int   pcmend;
181   int   mode;
182
183   int         eofflag;
184   ogg_int64_t granulepos;
185   ogg_int64_t sequence;
186   vorbis_dsp_state *vd; /* For read-only access of configuration */
187
188   /* local storage to avoid remallocing; it's up to the mapping to
189      structure it */
190   void               *localstore;
191   long                localtop;
192   long                localalloc;
193   long                totaluse;
194   struct alloc_chain *reap;
195
196   /* bitmetrics for the frame */
197   long glue_bits;
198   long time_bits;
199   long floor_bits;
200   long res_bits;
201
202   void *internal;
203
204 } vorbis_block;
205
206 /* vorbis_block is a single block of data to be processed as part of
207 the analysis/synthesis stream; it belongs to a specific logical
208 bitstream, but is independant from other vorbis_blocks belonging to
209 that logical bitstream. *************************************************/
210
211 struct alloc_chain{
212   void *ptr;
213   struct alloc_chain *next;
214 };
215
216 /* vorbis_info contains all the setup information specific to the
217    specific compression/decompression mode in progress (eg,
218    psychoacoustic settings, channel setup, options, codebook
219    etc). vorbis_info and substructures are in backends.h.
220 *********************************************************************/
221
222 /* the comments are not part of vorbis_info so that vorbis_info can be
223    static storage */
224 typedef struct vorbis_comment{
225   /* unlimited user comment fields.  libvorbis writes 'libvorbis'
226      whatever vendor is set to in encode */
227   char **user_comments;
228   int   *comment_lengths;
229   int    comments;
230   char  *vendor;
231
232 } vorbis_comment;
233
234
235 /* libvorbis encodes in two abstraction layers; first we perform DSP
236    and produce a packet (see docs/analysis.txt).  The packet is then
237    coded into a framed OggSquish bitstream by the second layer (see
238    docs/framing.txt).  Decode is the reverse process; we sync/frame
239    the bitstream and extract individual packets, then decode the
240    packet back into PCM audio.
241
242    The extra framing/packetizing is used in streaming formats, such as
243    files.  Over the net (such as with UDP), the framing and
244    packetization aren't necessary as they're provided by the transport
245    and the streaming layer is not used */
246
247 /* Vorbis PRIMITIVES: general ***************************************/
248
249 static void     (*qvorbis_info_init) (vorbis_info *vi);
250 static void     (*qvorbis_info_clear) (vorbis_info *vi);
251 static void     (*qvorbis_comment_init) (vorbis_comment *vc);
252 static void     (*qvorbis_comment_clear) (vorbis_comment *vc);
253
254 static int      (*qvorbis_block_init) (vorbis_dsp_state *v, vorbis_block *vb);
255 static int      (*qvorbis_block_clear) (vorbis_block *vb);
256 static void     (*qvorbis_dsp_clear) (vorbis_dsp_state *v);
257
258 /* Vorbis PRIMITIVES: analysis/DSP layer ****************************/
259
260 static int      (*qvorbis_analysis_init) (vorbis_dsp_state *v,vorbis_info *vi);
261 static int      (*qvorbis_commentheader_out) (vorbis_comment *vc, ogg_packet *op);
262 static int      (*qvorbis_analysis_headerout) (vorbis_dsp_state *v,
263                                           vorbis_comment *vc,
264                                           ogg_packet *op,
265                                           ogg_packet *op_comm,
266                                           ogg_packet *op_code);
267 static float ** (*qvorbis_analysis_buffer) (vorbis_dsp_state *v,int vals);
268 static int      (*qvorbis_analysis_wrote) (vorbis_dsp_state *v,int vals);
269 static int      (*qvorbis_analysis_blockout) (vorbis_dsp_state *v,vorbis_block *vb);
270 static int      (*qvorbis_analysis) (vorbis_block *vb,ogg_packet *op);
271
272 static int      (*qvorbis_bitrate_addblock) (vorbis_block *vb);
273 static int      (*qvorbis_bitrate_flushpacket) (vorbis_dsp_state *vd,
274                                            ogg_packet *op);
275
276 // end of vorbis/codec.h stuff
277
278 // vorbisenc.h stuff
279 static int (*qvorbis_encode_init_vbr) (vorbis_info *vi,
280                                   long channels,
281                                   long rate,
282
283                                   float base_quality /* quality level from 0. (lo) to 1. (hi) */
284                                   );
285 // end of vorbisenc.h stuff
286
287 // theora.h stuff
288 typedef struct {
289     int   y_width;      /**< Width of the Y' luminance plane */
290     int   y_height;     /**< Height of the luminance plane */
291     int   y_stride;     /**< Offset in bytes between successive rows */
292
293     int   uv_width;     /**< Width of the Cb and Cr chroma planes */
294     int   uv_height;    /**< Height of the chroma planes */
295     int   uv_stride;    /**< Offset between successive chroma rows */
296     unsigned char *y;   /**< Pointer to start of luminance data */
297     unsigned char *u;   /**< Pointer to start of Cb data */
298     unsigned char *v;   /**< Pointer to start of Cr data */
299
300 } yuv_buffer;
301
302 /**
303  * A Colorspace.
304  */
305 typedef enum {
306   OC_CS_UNSPECIFIED,    /**< The colorspace is unknown or unspecified */
307   OC_CS_ITU_REC_470M,   /**< This is the best option for 'NTSC' content */
308   OC_CS_ITU_REC_470BG,  /**< This is the best option for 'PAL' content */
309   OC_CS_NSPACES         /**< This marks the end of the defined colorspaces */
310 } theora_colorspace;
311
312 /**
313  * A Chroma subsampling
314  *
315  * These enumerate the available chroma subsampling options supported
316  * by the theora format. See Section 4.4 of the specification for
317  * exact definitions.
318  */
319 typedef enum {
320   OC_PF_420,    /**< Chroma subsampling by 2 in each direction (4:2:0) */
321   OC_PF_RSVD,   /**< Reserved value */
322   OC_PF_422,    /**< Horizonatal chroma subsampling by 2 (4:2:2) */
323   OC_PF_444,    /**< No chroma subsampling at all (4:4:4) */
324 } theora_pixelformat;
325 /**
326  * Theora bitstream info.
327  * Contains the basic playback parameters for a stream,
328  * corresponding to the initial 'info' header packet.
329  * 
330  * Encoded theora frames must be a multiple of 16 in width and height.
331  * To handle other frame sizes, a crop rectangle is specified in
332  * frame_height and frame_width, offset_x and * offset_y. The offset
333  * and size should still be a multiple of 2 to avoid chroma sampling
334  * shifts. Offset values in this structure are measured from the
335  * upper left of the image.
336  *
337  * Frame rate, in frames per second, is stored as a rational
338  * fraction. Aspect ratio is also stored as a rational fraction, and
339  * refers to the aspect ratio of the frame pixels, not of the
340  * overall frame itself.
341  * 
342  * See <a href="http://svn.xiph.org/trunk/theora/examples/encoder_example.c">
343  * examples/encoder_example.c</a> for usage examples of the
344  * other paramters and good default settings for the encoder parameters.
345  */
346 typedef struct {
347   ogg_uint32_t  width;      /**< encoded frame width  */
348   ogg_uint32_t  height;     /**< encoded frame height */
349   ogg_uint32_t  frame_width;    /**< display frame width  */
350   ogg_uint32_t  frame_height;   /**< display frame height */
351   ogg_uint32_t  offset_x;   /**< horizontal offset of the displayed frame */
352   ogg_uint32_t  offset_y;   /**< vertical offset of the displayed frame */
353   ogg_uint32_t  fps_numerator;      /**< frame rate numerator **/
354   ogg_uint32_t  fps_denominator;    /**< frame rate denominator **/
355   ogg_uint32_t  aspect_numerator;   /**< pixel aspect ratio numerator */
356   ogg_uint32_t  aspect_denominator; /**< pixel aspect ratio denominator */
357   theora_colorspace colorspace;     /**< colorspace */
358   int           target_bitrate;     /**< nominal bitrate in bits per second */
359   int           quality;  /**< Nominal quality setting, 0-63 */
360   int           quick_p;  /**< Quick encode/decode */
361
362   /* decode only */
363   unsigned char version_major;
364   unsigned char version_minor;
365   unsigned char version_subminor;
366
367   void *codec_setup;
368
369   /* encode only */
370   int           dropframes_p;
371   int           keyframe_auto_p;
372   ogg_uint32_t  keyframe_frequency;
373   ogg_uint32_t  keyframe_frequency_force;  /* also used for decode init to
374                                               get granpos shift correct */
375   ogg_uint32_t  keyframe_data_target_bitrate;
376   ogg_int32_t   keyframe_auto_threshold;
377   ogg_uint32_t  keyframe_mindistance;
378   ogg_int32_t   noise_sensitivity;
379   ogg_int32_t   sharpness;
380
381   theora_pixelformat pixelformat;   /**< chroma subsampling mode to expect */
382
383 } theora_info;
384
385 /** Codec internal state and context.
386  */
387 typedef struct{
388   theora_info *i;
389   ogg_int64_t granulepos;
390
391   void *internal_encode;
392   void *internal_decode;
393
394 } theora_state;
395
396 /** 
397  * Comment header metadata.
398  *
399  * This structure holds the in-stream metadata corresponding to
400  * the 'comment' header packet.
401  *
402  * Meta data is stored as a series of (tag, value) pairs, in
403  * length-encoded string vectors. The first occurence of the 
404  * '=' character delimits the tag and value. A particular tag
405  * may occur more than once. The character set encoding for
406  * the strings is always UTF-8, but the tag names are limited
407  * to case-insensitive ASCII. See the spec for details.
408  *
409  * In filling in this structure, qtheora_decode_header() will
410  * null-terminate the user_comment strings for safety. However,
411  * the bitstream format itself treats them as 8-bit clean,
412  * and so the length array should be treated as authoritative
413  * for their length.
414  */
415 typedef struct theora_comment{
416   char **user_comments;         /**< An array of comment string vectors */
417   int   *comment_lengths;       /**< An array of corresponding string vector lengths in bytes */
418   int    comments;              /**< The total number of comment string vectors */
419   char  *vendor;                /**< The vendor string identifying the encoder, null terminated */
420
421 } theora_comment;
422 static int (*qtheora_encode_init) (theora_state *th, theora_info *ti);
423 static int (*qtheora_encode_YUVin) (theora_state *t, yuv_buffer *yuv);
424 static int (*qtheora_encode_packetout) ( theora_state *t, int last_p,
425                                     ogg_packet *op);
426 static int (*qtheora_encode_header) (theora_state *t, ogg_packet *op);
427 static int (*qtheora_encode_comment) (theora_comment *tc, ogg_packet *op);
428 static int (*qtheora_encode_tables) (theora_state *t, ogg_packet *op);
429 static void (*qtheora_info_init) (theora_info *c);
430 static void (*qtheora_info_clear) (theora_info *c);
431 static void (*qtheora_clear) (theora_state *t);
432 static void (*qtheora_comment_init) (theora_comment *tc);
433 static void  (*qtheora_comment_clear) (theora_comment *tc);
434 // end of theora.h stuff
435
436 static dllfunction_t oggfuncs[] =
437 {
438         {"ogg_stream_packetin", (void **) &qogg_stream_packetin},
439         {"ogg_stream_pageout", (void **) &qogg_stream_pageout},
440         {"ogg_stream_flush", (void **) &qogg_stream_flush},
441         {"ogg_stream_init", (void **) &qogg_stream_init},
442         {"ogg_stream_clear", (void **) &qogg_stream_clear},
443         {NULL, NULL}
444 };
445
446 static dllfunction_t vorbisencfuncs[] =
447 {
448         {"vorbis_encode_init_vbr", (void **) &qvorbis_encode_init_vbr},
449         {NULL, NULL}
450 };
451
452 static dllfunction_t vorbisfuncs[] =
453 {
454         {"vorbis_info_init", (void **) &qvorbis_info_init},
455         {"vorbis_info_clear", (void **) &qvorbis_info_clear},
456         {"vorbis_comment_init", (void **) &qvorbis_comment_init},
457         {"vorbis_comment_clear", (void **) &qvorbis_comment_clear},
458         {"vorbis_block_init", (void **) &qvorbis_block_init},
459         {"vorbis_block_clear", (void **) &qvorbis_block_clear},
460         {"vorbis_dsp_clear", (void **) &qvorbis_dsp_clear},
461         {"vorbis_analysis_init", (void **) &qvorbis_analysis_init},
462         {"vorbis_commentheader_out", (void **) &qvorbis_commentheader_out},
463         {"vorbis_analysis_headerout", (void **) &qvorbis_analysis_headerout},
464         {"vorbis_analysis_buffer", (void **) &qvorbis_analysis_buffer},
465         {"vorbis_analysis_wrote", (void **) &qvorbis_analysis_wrote},
466         {"vorbis_analysis_blockout", (void **) &qvorbis_analysis_blockout},
467         {"vorbis_analysis", (void **) &qvorbis_analysis},
468         {"vorbis_bitrate_addblock", (void **) &qvorbis_bitrate_addblock},
469         {"vorbis_bitrate_flushpacket", (void **) &qvorbis_bitrate_flushpacket},
470         {NULL, NULL}
471 };
472
473 static dllfunction_t theorafuncs[] =
474 {
475         {"theora_info_init", (void **) &qtheora_info_init},
476         {"theora_info_clear", (void **) &qtheora_info_clear},
477         {"theora_comment_init", (void **) &qtheora_comment_init},
478         {"theora_comment_clear", (void **) &qtheora_comment_clear},
479         {"theora_encode_init", (void **) &qtheora_encode_init},
480         {"theora_encode_YUVin", (void **) &qtheora_encode_YUVin},
481         {"theora_encode_packetout", (void **) &qtheora_encode_packetout},
482         {"theora_encode_header", (void **) &qtheora_encode_header},
483         {"theora_encode_comment", (void **) &qtheora_encode_comment},
484         {"theora_encode_tables", (void **) &qtheora_encode_tables},
485         {"theora_clear", (void **) &qtheora_clear},
486         {NULL, NULL}
487 };
488
489 static dllhandle_t og_dll = NULL, vo_dll = NULL, ve_dll = NULL, th_dll = NULL;
490
491 qboolean SCR_CaptureVideo_Ogg_OpenLibrary()
492 {
493         const char* dllnames_og [] =
494         {
495 #if defined(WIN64)
496                 "libogg64.dll",
497 #elif defined(WIN32)
498                 "libogg.dll",
499                 "ogg.dll",
500 #elif defined(MACOSX)
501                 "libogg.dylib",
502 #else
503                 "libogg.so.0",
504                 "libogg.so",
505 #endif
506                 NULL
507         };
508         const char* dllnames_vo [] =
509         {
510 #if defined(WIN64)
511                 "libvorbis64.dll",
512 #elif defined(WIN32)
513                 "libvorbis.dll",
514                 "vorbis.dll",
515 #elif defined(MACOSX)
516                 "libvorbis.dylib",
517 #else
518                 "libvorbis.so.0",
519                 "libvorbis.so",
520 #endif
521                 NULL
522         };
523         const char* dllnames_ve [] =
524         {
525 #if defined(WIN64)
526                 "libvorbisenc64.dll",
527 #elif defined(WIN32)
528                 "libvorbisenc.dll",
529                 "vorbisenc.dll",
530 #elif defined(MACOSX)
531                 "libvorbisenc.dylib",
532 #else
533                 "libvorbisenc.so.2",
534                 "libvorbisenc.so",
535 #endif
536                 NULL
537         };
538         const char* dllnames_th [] =
539         {
540 #if defined(WIN64)
541                 "libtheora64.dll",
542 #elif defined(WIN32)
543                 "libtheora.dll",
544                 "theora.dll",
545 #elif defined(MACOSX)
546                 "libtheora.dylib",
547 #else
548                 "libtheora.so.0",
549                 "libtheora.so",
550 #endif
551                 NULL
552         };
553
554         return
555                 Sys_LoadLibrary (dllnames_og, &og_dll, oggfuncs)
556                 &&
557                 Sys_LoadLibrary (dllnames_th, &th_dll, theorafuncs)
558                 &&
559                 Sys_LoadLibrary (dllnames_vo, &vo_dll, vorbisfuncs)
560                 &&
561                 Sys_LoadLibrary (dllnames_ve, &ve_dll, vorbisencfuncs);
562 }
563
564 void SCR_CaptureVideo_Ogg_Init()
565 {
566         SCR_CaptureVideo_Ogg_OpenLibrary();
567 }
568
569 qboolean SCR_CaptureVideo_Ogg_Available()
570 {
571         return og_dll && th_dll && vo_dll && ve_dll;
572 }
573
574 void SCR_CaptureVideo_Ogg_CloseDLL()
575 {
576         Sys_UnloadLibrary (&ve_dll);
577         Sys_UnloadLibrary (&vo_dll);
578         Sys_UnloadLibrary (&th_dll);
579         Sys_UnloadLibrary (&og_dll);
580 }
581
582 typedef struct capturevideostate_ogg_formatspecific_s
583 {
584         ogg_stream_state to, vo;
585         int serial1, serial2;
586         theora_info ti;
587         theora_state ts;
588         vorbis_info vi;
589         vorbis_dsp_state vd;
590         vorbis_block vb;
591         yuv_buffer yuv;
592         int channels;
593 }
594 capturevideostate_ogg_formatspecific_t;
595 #define LOAD_FORMATSPECIFIC() capturevideostate_ogg_formatspecific_t *format = (capturevideostate_ogg_formatspecific_t *) cls.capturevideo.formatspecific
596
597 void SCR_CaptureVideo_Ogg_Begin()
598 {
599         cls.capturevideo.videofile = FS_OpenRealFile(va("%s.ogv", cls.capturevideo.basename), "wb", false);
600         cls.capturevideo.formatspecific = Mem_Alloc(tempmempool, sizeof(capturevideostate_ogg_formatspecific_t));
601         {
602                 LOAD_FORMATSPECIFIC();
603                 int num, denom;
604                 ogg_page pg;
605                 ogg_packet pt, pt2, pt3;
606                 theora_comment tc;
607                 vorbis_comment vc;
608
609                 format->serial1 = rand();
610                 qogg_stream_init(&format->to, format->serial1);
611
612                 if(cls.capturevideo.soundrate)
613                 {
614                         do
615                         {
616                                 format->serial2 = rand();
617                         }
618                         while(format->serial1 == format->serial2);
619                         qogg_stream_init(&format->vo, format->serial2);
620                 }
621
622                 qtheora_info_init(&format->ti);
623                 format->ti.frame_width = cls.capturevideo.width;
624                 format->ti.frame_height = cls.capturevideo.height;
625                 format->ti.width = (format->ti.frame_width + 15) & ~15;
626                 format->ti.height = (format->ti.frame_height + 15) & ~15;
627                 format->ti.offset_x = ((format->ti.width - format->ti.frame_width) / 2) & ~1;
628                 format->ti.offset_y = ((format->ti.height - format->ti.frame_height) / 2) & ~1;
629
630                 format->yuv.y_width = format->ti.width;
631                 format->yuv.y_height = format->ti.height;
632                 format->yuv.y_stride = format->ti.width;
633
634                 format->yuv.uv_width = format->ti.width / 2;
635                 format->yuv.uv_height = format->ti.height / 2;
636                 format->yuv.uv_stride = format->ti.width / 2;
637
638                 format->yuv.y = Mem_Alloc(tempmempool, format->yuv.y_stride * format->yuv.y_height);
639                 format->yuv.u = Mem_Alloc(tempmempool, format->yuv.uv_stride * format->yuv.uv_height);
640                 format->yuv.v = Mem_Alloc(tempmempool, format->yuv.uv_stride * format->yuv.uv_height);
641
642                 FindFraction(cls.capturevideo.framerate, &num, &denom, 1001);
643                 format->ti.fps_numerator = num;
644                 format->ti.fps_denominator = denom;
645
646                 FindFraction(1 / vid_pixelheight.value, &num, &denom, 1000);
647                 format->ti.aspect_numerator = num;
648                 format->ti.aspect_denominator = denom;
649
650                 format->ti.colorspace = OC_CS_UNSPECIFIED;
651                 format->ti.pixelformat = OC_PF_420;
652
653                 format->ti.target_bitrate = -1;
654                 format->ti.quality = 63; // TODO find good values here later
655                 format->ti.quick_p = false;
656
657                 format->ti.dropframes_p = false;
658                 format->ti.keyframe_auto_p = false;
659                 format->ti.keyframe_frequency = 64;
660                 format->ti.keyframe_frequency_force = 64; // TODO
661                 format->ti.keyframe_data_target_bitrate = -1;
662                 format->ti.keyframe_auto_threshold = 80;
663                 format->ti.keyframe_mindistance = 8;
664                 format->ti.noise_sensitivity = 1; // TODO
665                 format->ti.sharpness = 0;
666
667                 qtheora_encode_init(&format->ts, &format->ti);
668
669                 // vorbis?
670                 if(cls.capturevideo.soundrate)
671                 {
672                         qvorbis_info_init(&format->vi);
673                         qvorbis_encode_init_vbr(&format->vi, cls.capturevideo.soundchannels, cls.capturevideo.soundrate, 9);
674                         qvorbis_comment_init(&vc);
675                         qvorbis_analysis_init(&format->vd, &format->vi);
676                         qvorbis_block_init(&format->vd, &format->vb);
677                 }
678
679                 qtheora_comment_init(&tc);
680
681                 /* create the remaining theora headers */
682                 qtheora_encode_header(&format->ts, &pt);
683                 qogg_stream_packetin(&format->to, &pt);
684                 if (qogg_stream_pageout (&format->to, &pg) != 1)
685                         fprintf (stderr, "Internal Ogg library error.\n");
686                 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
687                 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
688
689                 qtheora_encode_comment(&tc, &pt);
690                 qogg_stream_packetin(&format->to, &pt);
691                 qtheora_encode_tables(&format->ts, &pt);
692                 qogg_stream_packetin (&format->to, &pt);
693
694                 qtheora_comment_clear(&tc);
695
696                 if(cls.capturevideo.soundrate)
697                 {
698                         qvorbis_analysis_headerout(&format->vd, &vc, &pt, &pt2, &pt3);
699                         qogg_stream_packetin(&format->vo, &pt);
700                         if (qogg_stream_pageout (&format->vo, &pg) != 1)
701                                 fprintf (stderr, "Internal Ogg library error.\n");
702                         FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
703                         FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
704
705                         qogg_stream_packetin(&format->vo, &pt2);
706                         qogg_stream_packetin(&format->vo, &pt3);
707
708                         qvorbis_comment_clear(&vc);
709                 }
710
711                 for(;;)
712                 {
713                         int result = qogg_stream_flush (&format->to, &pg);
714                         if (result < 0)
715                                 fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
716                         if (result <= 0)
717                                 break;
718                         FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
719                         FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
720                 }
721
722                 if(cls.capturevideo.soundrate)
723                 for(;;)
724                 {
725                         int result = qogg_stream_flush (&format->vo, &pg);
726                         if (result < 0)
727                                 fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
728                         if (result <= 0)
729                                 break;
730                         FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
731                         FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
732                 }
733         }
734 }
735
736 void SCR_CaptureVideo_Ogg_EndVideo()
737 {
738         LOAD_FORMATSPECIFIC();
739         ogg_page pg;
740         ogg_packet pt;
741
742         // repeat the last frame so we can set the end-of-stream flag
743         qtheora_encode_YUVin(&format->ts, &format->yuv);
744         qtheora_encode_packetout(&format->ts, true, &pt);
745         qogg_stream_packetin(&format->to, &pt);
746
747         if(cls.capturevideo.soundrate)
748         {
749                 qvorbis_analysis_wrote(&format->vd, 0);
750                 while(qvorbis_analysis_blockout(&format->vd, &format->vb) == 1)
751                 {
752                         qvorbis_analysis(&format->vb, NULL);
753                         qvorbis_bitrate_addblock(&format->vb);
754                         while(qvorbis_bitrate_flushpacket(&format->vd, &pt))
755                                 qogg_stream_packetin(&format->vo, &pt);
756                 }
757         }
758
759         if(qogg_stream_pageout(&format->to, &pg) > 0)
760         {
761                 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
762                 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
763         }
764
765         if(cls.capturevideo.soundrate)
766         {
767                 if(qogg_stream_pageout(&format->vo, &pg) > 0)
768                 {
769                         FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
770                         FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
771                 }
772         }
773                 
774         while (1) {
775                 int result = qogg_stream_flush (&format->to, &pg);
776                 if (result < 0)
777                         fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
778                 if (result <= 0)
779                         break;
780                 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
781                 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
782         }
783
784         if(cls.capturevideo.soundrate)
785         {
786                 while (1) {
787                         int result = qogg_stream_flush (&format->vo, &pg);
788                         if (result < 0)
789                                 fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
790                         if (result <= 0)
791                                 break;
792                         FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
793                         FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
794                 }
795
796                 qogg_stream_clear(&format->vo);
797                 qvorbis_block_clear(&format->vb);
798                 qvorbis_dsp_clear(&format->vd);
799                 qvorbis_info_clear(&format->vi);
800         }
801
802         qogg_stream_clear(&format->to);
803         qtheora_clear(&format->ts);
804
805         Mem_Free(format);
806
807         // cl_screen.c does this
808         // FS_Close(cls.capturevideo.videofile);
809         // cls.capturevideo.videofile = NULL;
810 }
811
812 void SCR_CaptureVideo_Ogg_ConvertFrame_BGRA_to_YUV()
813 {
814         LOAD_FORMATSPECIFIC();
815         int x, y;
816         int blockr, blockg, blockb;
817         unsigned char *b = cls.capturevideo.outbuffer;
818         int w = cls.capturevideo.width;
819         int h = cls.capturevideo.height;
820         int inpitch = w*4;
821
822         for(y = 0; y < h; ++y)
823         {
824                 for(b = cls.capturevideo.outbuffer + (h-1-y)*w*4, x = 0; x < w; ++x)
825                 {
826                         blockr = b[2];
827                         blockg = b[1];
828                         blockb = b[0];
829                         format->yuv.y[x + format->yuv.y_stride * y] =
830                                 cls.capturevideo.yuvnormalizetable[0][cls.capturevideo.rgbtoyuvscaletable[0][0][blockr] + cls.capturevideo.rgbtoyuvscaletable[0][1][blockg] + cls.capturevideo.rgbtoyuvscaletable[0][2][blockb]];
831                         b += 4;
832                 }
833
834                 if((y & 1) == 0)
835                 {
836                         for(b = cls.capturevideo.outbuffer + (h-2-y)*w*4, x = 0; x < w/2; ++x)
837                         {
838                                 blockr = (b[2] + b[6] + b[inpitch+2] + b[inpitch+6]) >> 2;
839                                 blockg = (b[1] + b[5] + b[inpitch+1] + b[inpitch+5]) >> 2;
840                                 blockb = (b[0] + b[4] + b[inpitch+0] + b[inpitch+4]) >> 2;
841                                 format->yuv.u[x + format->yuv.uv_stride * (y/2)] =
842                                         cls.capturevideo.yuvnormalizetable[1][cls.capturevideo.rgbtoyuvscaletable[1][0][blockr] + cls.capturevideo.rgbtoyuvscaletable[1][1][blockg] + cls.capturevideo.rgbtoyuvscaletable[1][2][blockb] + 128];
843                                 format->yuv.v[x + format->yuv.uv_stride * (y/2)] =
844                                         cls.capturevideo.yuvnormalizetable[2][cls.capturevideo.rgbtoyuvscaletable[2][0][blockr] + cls.capturevideo.rgbtoyuvscaletable[2][1][blockg] + cls.capturevideo.rgbtoyuvscaletable[2][2][blockb] + 128];
845                                 b += 8;
846                         }
847                 }
848         }
849 }
850
851 void SCR_CaptureVideo_Ogg_VideoFrame()
852 {
853         LOAD_FORMATSPECIFIC();
854         ogg_page pg;
855         ogg_packet pt;
856
857         // data is in cls.capturevideo.outbuffer as BGRA and has size width*height
858
859         SCR_CaptureVideo_Ogg_ConvertFrame_BGRA_to_YUV();
860         qtheora_encode_YUVin(&format->ts, &format->yuv);
861         qtheora_encode_packetout(&format->ts, false, &pt);
862         qogg_stream_packetin(&format->to, &pt);
863
864         while(qogg_stream_pageout(&format->to, &pg) > 0)
865         {
866                 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
867                 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
868         }
869 }
870
871 void SCR_CaptureVideo_Ogg_SoundFrame(const portable_sampleframe_t *paintbuffer, size_t length)
872 {
873         LOAD_FORMATSPECIFIC();
874         float **vorbis_buffer;
875         size_t i;
876         int j;
877         ogg_page pg;
878         ogg_packet pt;
879
880         vorbis_buffer = qvorbis_analysis_buffer(&format->vd, length);
881         for(i = 0; i < length; ++i)
882         {
883                 for(j = 0; j < cls.capturevideo.soundchannels; ++j)
884                         vorbis_buffer[j][i] = paintbuffer[i].sample[j] / 32768.0f;
885         }
886         qvorbis_analysis_wrote(&format->vd, length);
887
888         while(qvorbis_analysis_blockout(&format->vd, &format->vb) == 1)
889         {
890                 qvorbis_analysis(&format->vb, NULL);
891                 qvorbis_bitrate_addblock(&format->vb);
892
893                 while(qvorbis_bitrate_flushpacket(&format->vd, &pt))
894                         qogg_stream_packetin(&format->vo, &pt);
895         }
896
897         while(qogg_stream_pageout(&format->vo, &pg) > 0)
898         {
899                 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
900                 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
901         }
902 }