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