9 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"};
10 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"};
11 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"};
12 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)"};
13 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)"};
14 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)"};
15 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"};
16 static cvar_t cl_capturevideo_ogg_theora_sharpness = {CVAR_SAVE, "cl_capturevideo_ogg_theora_sharpness", "0", "sharpness (0 to 2); lower is sharper"};
17 static cvar_t cl_capturevideo_ogg_vorbis_quality = {CVAR_SAVE, "cl_capturevideo_ogg_vorbis_quality", "1", "audio quality (-1 to 10); higher is better"};
21 typedef __int16 ogg_int16_t;
22 typedef unsigned __int16 ogg_uint16_t;
23 typedef __int32 ogg_int32_t;
24 typedef unsigned __int32 ogg_uint32_t;
25 typedef __int64 ogg_int64_t;
27 typedef int16_t ogg_int16_t;
28 typedef uint16_t ogg_uint16_t;
29 typedef int32_t ogg_int32_t;
30 typedef uint32_t ogg_uint32_t;
31 typedef int64_t ogg_int64_t;
38 unsigned char *buffer;
43 /* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/
46 unsigned char *header;
52 /* ogg_stream_state contains the current encode/decode state of a logical
53 Ogg bitstream **********************************************************/
56 unsigned char *body_data; /* bytes from packet bodies */
57 long body_storage; /* storage elements allocated */
58 long body_fill; /* elements stored; fill mark */
59 long body_returned; /* elements of fill returned */
62 int *lacing_vals; /* The values that will go to the segment table */
63 ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact
64 this way, but it is simple coupled to the
71 unsigned char header[282]; /* working space for header encode */
74 int e_o_s; /* set when we have buffered the last packet in the
76 int b_o_s; /* set after we've written the initial page
77 of a logical bitstream */
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_int64_t granulepos;
89 /* ogg_packet is used to encapsulate the data and metadata belonging
90 to a single raw Ogg/Vorbis packet *************************************/
93 unsigned char *packet;
98 ogg_int64_t granulepos;
100 ogg_int64_t packetno; /* sequence number for decode; the framing
101 knows where there's a hole in the data,
102 but we need coupling so that the codec
103 (which is in a seperate abstraction
104 layer) also knows about the gap */
118 /* Ogg BITSTREAM PRIMITIVES: encoding **************************/
120 static int (*qogg_stream_packetin) (ogg_stream_state *os, ogg_packet *op);
121 static int (*qogg_stream_pageout) (ogg_stream_state *os, ogg_page *og);
122 static int (*qogg_stream_flush) (ogg_stream_state *os, ogg_page *og);
124 /* Ogg BITSTREAM PRIMITIVES: general ***************************/
126 static int (*qogg_stream_init) (ogg_stream_state *os,int serialno);
127 static int (*qogg_stream_clear) (ogg_stream_state *os);
128 static ogg_int64_t (*qogg_page_granulepos) (ogg_page *og);
130 // end of ogg.h stuff
132 // vorbis/codec.h stuff
133 typedef struct vorbis_info{
138 /* The below bitrate declarations are *hints*.
139 Combinations of the three values carry the following implications:
141 all three set to the same value:
142 implies a fixed rate bitstream
144 implies a VBR stream that averages the nominal bitrate. No hard
146 upper and or lower set:
147 implies a VBR bitstream that obeys the bitrate limits. nominal
148 may also be set to give a nominal rate.
150 the coder does not care to speculate.
154 long bitrate_nominal;
161 /* vorbis_dsp_state buffers the current vorbis audio
162 analysis/synthesis state. The DSP state belongs to a specific
163 logical bitstream ****************************************************/
164 typedef struct vorbis_dsp_state{
182 ogg_int64_t granulepos;
183 ogg_int64_t sequence;
185 ogg_int64_t glue_bits;
186 ogg_int64_t time_bits;
187 ogg_int64_t floor_bits;
188 ogg_int64_t res_bits;
193 typedef struct vorbis_block{
194 /* necessary stream state for linking to the framing abstraction */
195 float **pcm; /* this is a pointer into local storage */
205 ogg_int64_t granulepos;
206 ogg_int64_t sequence;
207 vorbis_dsp_state *vd; /* For read-only access of configuration */
209 /* local storage to avoid remallocing; it's up to the mapping to
215 struct alloc_chain *reap;
217 /* bitmetrics for the frame */
227 /* vorbis_block is a single block of data to be processed as part of
228 the analysis/synthesis stream; it belongs to a specific logical
229 bitstream, but is independant from other vorbis_blocks belonging to
230 that logical bitstream. *************************************************/
234 struct alloc_chain *next;
237 /* vorbis_info contains all the setup information specific to the
238 specific compression/decompression mode in progress (eg,
239 psychoacoustic settings, channel setup, options, codebook
240 etc). vorbis_info and substructures are in backends.h.
241 *********************************************************************/
243 /* the comments are not part of vorbis_info so that vorbis_info can be
245 typedef struct vorbis_comment{
246 /* unlimited user comment fields. libvorbis writes 'libvorbis'
247 whatever vendor is set to in encode */
248 char **user_comments;
249 int *comment_lengths;
256 /* libvorbis encodes in two abstraction layers; first we perform DSP
257 and produce a packet (see docs/analysis.txt). The packet is then
258 coded into a framed OggSquish bitstream by the second layer (see
259 docs/framing.txt). Decode is the reverse process; we sync/frame
260 the bitstream and extract individual packets, then decode the
261 packet back into PCM audio.
263 The extra framing/packetizing is used in streaming formats, such as
264 files. Over the net (such as with UDP), the framing and
265 packetization aren't necessary as they're provided by the transport
266 and the streaming layer is not used */
268 /* Vorbis PRIMITIVES: general ***************************************/
270 static void (*qvorbis_info_init) (vorbis_info *vi);
271 static void (*qvorbis_info_clear) (vorbis_info *vi);
272 static void (*qvorbis_comment_init) (vorbis_comment *vc);
273 static void (*qvorbis_comment_clear) (vorbis_comment *vc);
275 static int (*qvorbis_block_init) (vorbis_dsp_state *v, vorbis_block *vb);
276 static int (*qvorbis_block_clear) (vorbis_block *vb);
277 static void (*qvorbis_dsp_clear) (vorbis_dsp_state *v);
278 static double (*qvorbis_granule_time) (vorbis_dsp_state *v,
279 ogg_int64_t granulepos);
281 /* Vorbis PRIMITIVES: analysis/DSP layer ****************************/
283 static int (*qvorbis_analysis_init) (vorbis_dsp_state *v,vorbis_info *vi);
284 static int (*qvorbis_commentheader_out) (vorbis_comment *vc, ogg_packet *op);
285 static int (*qvorbis_analysis_headerout) (vorbis_dsp_state *v,
289 ogg_packet *op_code);
290 static float ** (*qvorbis_analysis_buffer) (vorbis_dsp_state *v,int vals);
291 static int (*qvorbis_analysis_wrote) (vorbis_dsp_state *v,int vals);
292 static int (*qvorbis_analysis_blockout) (vorbis_dsp_state *v,vorbis_block *vb);
293 static int (*qvorbis_analysis) (vorbis_block *vb,ogg_packet *op);
295 static int (*qvorbis_bitrate_addblock) (vorbis_block *vb);
296 static int (*qvorbis_bitrate_flushpacket) (vorbis_dsp_state *vd,
299 // end of vorbis/codec.h stuff
302 static int (*qvorbis_encode_init_vbr) (vorbis_info *vi,
306 float base_quality /* quality level from 0. (lo) to 1. (hi) */
308 // end of vorbisenc.h stuff
312 int y_width; /**< Width of the Y' luminance plane */
313 int y_height; /**< Height of the luminance plane */
314 int y_stride; /**< Offset in bytes between successive rows */
316 int uv_width; /**< Width of the Cb and Cr chroma planes */
317 int uv_height; /**< Height of the chroma planes */
318 int uv_stride; /**< Offset between successive chroma rows */
319 unsigned char *y; /**< Pointer to start of luminance data */
320 unsigned char *u; /**< Pointer to start of Cb data */
321 unsigned char *v; /**< Pointer to start of Cr data */
329 OC_CS_UNSPECIFIED, /**< The colorspace is unknown or unspecified */
330 OC_CS_ITU_REC_470M, /**< This is the best option for 'NTSC' content */
331 OC_CS_ITU_REC_470BG, /**< This is the best option for 'PAL' content */
332 OC_CS_NSPACES /**< This marks the end of the defined colorspaces */
336 * A Chroma subsampling
338 * These enumerate the available chroma subsampling options supported
339 * by the theora format. See Section 4.4 of the specification for
343 OC_PF_420, /**< Chroma subsampling by 2 in each direction (4:2:0) */
344 OC_PF_RSVD, /**< Reserved value */
345 OC_PF_422, /**< Horizonatal chroma subsampling by 2 (4:2:2) */
346 OC_PF_444, /**< No chroma subsampling at all (4:4:4) */
347 } theora_pixelformat;
349 * Theora bitstream info.
350 * Contains the basic playback parameters for a stream,
351 * corresponding to the initial 'info' header packet.
353 * Encoded theora frames must be a multiple of 16 in width and height.
354 * To handle other frame sizes, a crop rectangle is specified in
355 * frame_height and frame_width, offset_x and * offset_y. The offset
356 * and size should still be a multiple of 2 to avoid chroma sampling
357 * shifts. Offset values in this structure are measured from the
358 * upper left of the image.
360 * Frame rate, in frames per second, is stored as a rational
361 * fraction. Aspect ratio is also stored as a rational fraction, and
362 * refers to the aspect ratio of the frame pixels, not of the
363 * overall frame itself.
365 * See <a href="http://svn.xiph.org/trunk/theora/examples/encoder_example.c">
366 * examples/encoder_example.c</a> for usage examples of the
367 * other paramters and good default settings for the encoder parameters.
370 ogg_uint32_t width; /**< encoded frame width */
371 ogg_uint32_t height; /**< encoded frame height */
372 ogg_uint32_t frame_width; /**< display frame width */
373 ogg_uint32_t frame_height; /**< display frame height */
374 ogg_uint32_t offset_x; /**< horizontal offset of the displayed frame */
375 ogg_uint32_t offset_y; /**< vertical offset of the displayed frame */
376 ogg_uint32_t fps_numerator; /**< frame rate numerator **/
377 ogg_uint32_t fps_denominator; /**< frame rate denominator **/
378 ogg_uint32_t aspect_numerator; /**< pixel aspect ratio numerator */
379 ogg_uint32_t aspect_denominator; /**< pixel aspect ratio denominator */
380 theora_colorspace colorspace; /**< colorspace */
381 int target_bitrate; /**< nominal bitrate in bits per second */
382 int quality; /**< Nominal quality setting, 0-63 */
383 int quick_p; /**< Quick encode/decode */
386 unsigned char version_major;
387 unsigned char version_minor;
388 unsigned char version_subminor;
395 ogg_uint32_t keyframe_frequency;
396 ogg_uint32_t keyframe_frequency_force; /* also used for decode init to
397 get granpos shift correct */
398 ogg_uint32_t keyframe_data_target_bitrate;
399 ogg_int32_t keyframe_auto_threshold;
400 ogg_uint32_t keyframe_mindistance;
401 ogg_int32_t noise_sensitivity;
402 ogg_int32_t sharpness;
404 theora_pixelformat pixelformat; /**< chroma subsampling mode to expect */
408 /** Codec internal state and context.
412 ogg_int64_t granulepos;
414 void *internal_encode;
415 void *internal_decode;
420 * Comment header metadata.
422 * This structure holds the in-stream metadata corresponding to
423 * the 'comment' header packet.
425 * Meta data is stored as a series of (tag, value) pairs, in
426 * length-encoded string vectors. The first occurence of the
427 * '=' character delimits the tag and value. A particular tag
428 * may occur more than once. The character set encoding for
429 * the strings is always UTF-8, but the tag names are limited
430 * to case-insensitive ASCII. See the spec for details.
432 * In filling in this structure, qtheora_decode_header() will
433 * null-terminate the user_comment strings for safety. However,
434 * the bitstream format itself treats them as 8-bit clean,
435 * and so the length array should be treated as authoritative
438 typedef struct theora_comment{
439 char **user_comments; /**< An array of comment string vectors */
440 int *comment_lengths; /**< An array of corresponding string vector lengths in bytes */
441 int comments; /**< The total number of comment string vectors */
442 char *vendor; /**< The vendor string identifying the encoder, null terminated */
445 static int (*qtheora_encode_init) (theora_state *th, theora_info *ti);
446 static int (*qtheora_encode_YUVin) (theora_state *t, yuv_buffer *yuv);
447 static int (*qtheora_encode_packetout) ( theora_state *t, int last_p,
449 static int (*qtheora_encode_header) (theora_state *t, ogg_packet *op);
450 static int (*qtheora_encode_comment) (theora_comment *tc, ogg_packet *op);
451 static int (*qtheora_encode_tables) (theora_state *t, ogg_packet *op);
452 static void (*qtheora_info_init) (theora_info *c);
453 static void (*qtheora_info_clear) (theora_info *c);
454 static void (*qtheora_clear) (theora_state *t);
455 static void (*qtheora_comment_init) (theora_comment *tc);
456 static void (*qtheora_comment_clear) (theora_comment *tc);
457 static double (*qtheora_granule_time) (theora_state *th,ogg_int64_t granulepos);
458 // end of theora.h stuff
460 static dllfunction_t oggfuncs[] =
462 {"ogg_stream_packetin", (void **) &qogg_stream_packetin},
463 {"ogg_stream_pageout", (void **) &qogg_stream_pageout},
464 {"ogg_stream_flush", (void **) &qogg_stream_flush},
465 {"ogg_stream_init", (void **) &qogg_stream_init},
466 {"ogg_stream_clear", (void **) &qogg_stream_clear},
467 {"ogg_page_granulepos", (void **) &qogg_page_granulepos},
471 static dllfunction_t vorbisencfuncs[] =
473 {"vorbis_encode_init_vbr", (void **) &qvorbis_encode_init_vbr},
477 static dllfunction_t vorbisfuncs[] =
479 {"vorbis_info_init", (void **) &qvorbis_info_init},
480 {"vorbis_info_clear", (void **) &qvorbis_info_clear},
481 {"vorbis_comment_init", (void **) &qvorbis_comment_init},
482 {"vorbis_comment_clear", (void **) &qvorbis_comment_clear},
483 {"vorbis_block_init", (void **) &qvorbis_block_init},
484 {"vorbis_block_clear", (void **) &qvorbis_block_clear},
485 {"vorbis_dsp_clear", (void **) &qvorbis_dsp_clear},
486 {"vorbis_analysis_init", (void **) &qvorbis_analysis_init},
487 {"vorbis_commentheader_out", (void **) &qvorbis_commentheader_out},
488 {"vorbis_analysis_headerout", (void **) &qvorbis_analysis_headerout},
489 {"vorbis_analysis_buffer", (void **) &qvorbis_analysis_buffer},
490 {"vorbis_analysis_wrote", (void **) &qvorbis_analysis_wrote},
491 {"vorbis_analysis_blockout", (void **) &qvorbis_analysis_blockout},
492 {"vorbis_analysis", (void **) &qvorbis_analysis},
493 {"vorbis_bitrate_addblock", (void **) &qvorbis_bitrate_addblock},
494 {"vorbis_bitrate_flushpacket", (void **) &qvorbis_bitrate_flushpacket},
495 {"vorbis_granule_time", (void **) &qvorbis_granule_time},
499 static dllfunction_t theorafuncs[] =
501 {"theora_info_init", (void **) &qtheora_info_init},
502 {"theora_info_clear", (void **) &qtheora_info_clear},
503 {"theora_comment_init", (void **) &qtheora_comment_init},
504 {"theora_comment_clear", (void **) &qtheora_comment_clear},
505 {"theora_encode_init", (void **) &qtheora_encode_init},
506 {"theora_encode_YUVin", (void **) &qtheora_encode_YUVin},
507 {"theora_encode_packetout", (void **) &qtheora_encode_packetout},
508 {"theora_encode_header", (void **) &qtheora_encode_header},
509 {"theora_encode_comment", (void **) &qtheora_encode_comment},
510 {"theora_encode_tables", (void **) &qtheora_encode_tables},
511 {"theora_clear", (void **) &qtheora_clear},
512 {"theora_granule_time", (void **) &qtheora_granule_time},
516 static dllhandle_t og_dll = NULL, vo_dll = NULL, ve_dll = NULL, th_dll = NULL;
518 qboolean SCR_CaptureVideo_Ogg_OpenLibrary()
520 const char* dllnames_og [] =
527 #elif defined(MACOSX)
535 const char* dllnames_vo [] =
542 #elif defined(MACOSX)
550 const char* dllnames_ve [] =
553 "libvorbisenc64.dll",
557 #elif defined(MACOSX)
558 "libvorbisenc.dylib",
565 const char* dllnames_th [] =
572 #elif defined(MACOSX)
582 Sys_LoadLibrary (dllnames_og, &og_dll, oggfuncs)
584 Sys_LoadLibrary (dllnames_th, &th_dll, theorafuncs)
586 Sys_LoadLibrary (dllnames_vo, &vo_dll, vorbisfuncs)
588 Sys_LoadLibrary (dllnames_ve, &ve_dll, vorbisencfuncs);
591 void SCR_CaptureVideo_Ogg_Init()
593 SCR_CaptureVideo_Ogg_OpenLibrary();
595 Cvar_RegisterVariable(&cl_capturevideo_ogg_theora_quality);
596 Cvar_RegisterVariable(&cl_capturevideo_ogg_theora_bitrate);
597 Cvar_RegisterVariable(&cl_capturevideo_ogg_theora_keyframe_bitrate_multiplier);
598 Cvar_RegisterVariable(&cl_capturevideo_ogg_theora_keyframe_frequency);
599 Cvar_RegisterVariable(&cl_capturevideo_ogg_theora_keyframe_mindistance);
600 Cvar_RegisterVariable(&cl_capturevideo_ogg_theora_keyframe_auto_threshold);
601 Cvar_RegisterVariable(&cl_capturevideo_ogg_theora_noise_sensitivity);
602 Cvar_RegisterVariable(&cl_capturevideo_ogg_vorbis_quality);
605 qboolean SCR_CaptureVideo_Ogg_Available()
607 return og_dll && th_dll && vo_dll && ve_dll;
610 void SCR_CaptureVideo_Ogg_CloseDLL()
612 Sys_UnloadLibrary (&ve_dll);
613 Sys_UnloadLibrary (&vo_dll);
614 Sys_UnloadLibrary (&th_dll);
615 Sys_UnloadLibrary (&og_dll);
618 typedef struct capturevideostate_ogg_formatspecific_s
620 ogg_stream_state to, vo;
621 int serial1, serial2;
632 qboolean have_videopage;
633 qboolean have_audiopage;
635 capturevideostate_ogg_formatspecific_t;
636 #define LOAD_FORMATSPECIFIC_OGG() capturevideostate_ogg_formatspecific_t *format = (capturevideostate_ogg_formatspecific_t *) cls.capturevideo.formatspecific
638 static void SCR_CaptureVideo_Ogg_Interleave()
640 LOAD_FORMATSPECIFIC_OGG();
642 //fprintf(stderr, "<");
644 if(!cls.capturevideo.soundrate)
648 // first: make sure we have a page of both types
649 if(!format->have_videopage)
650 if(qogg_stream_pageout(&format->to, &format->videopage) > 0)
651 format->have_videopage = true;
652 if(format->have_videopage)
654 FS_Write(cls.capturevideo.videofile, format->videopage.header, format->videopage.header_len);
655 FS_Write(cls.capturevideo.videofile, format->videopage.body, format->videopage.body_len);
656 format->have_videopage = false;
664 // first: make sure we have a page of both types
665 if(!format->have_videopage)
666 if(qogg_stream_pageout(&format->to, &format->videopage) > 0)
668 //fprintf(stderr, "V");
669 format->have_videopage = true;
671 // why do I have to do this? the code should work without the
672 // following three lines, which turn this attempt at correct
673 // interleaving back into the old stupid one that oggz-validate
675 FS_Write(cls.capturevideo.videofile, format->videopage.header, format->videopage.header_len);
676 FS_Write(cls.capturevideo.videofile, format->videopage.body, format->videopage.body_len);
677 format->have_videopage = false;
679 if(!format->have_audiopage)
680 if(qogg_stream_pageout(&format->vo, &format->audiopage) > 0)
682 //fprintf(stderr, "A");
683 format->have_audiopage = true;
685 // why do I have to do this? the code should work without the
686 // following three lines, which turn this attempt at correct
687 // interleaving back into the old stupid one that oggz-validate
689 FS_Write(cls.capturevideo.videofile, format->audiopage.header, format->audiopage.header_len);
690 FS_Write(cls.capturevideo.videofile, format->audiopage.body, format->audiopage.body_len);
691 format->have_audiopage = false;
694 if(format->have_videopage && format->have_audiopage)
696 // output the page that ends first
697 double audiotime = qvorbis_granule_time(&format->vd, qogg_page_granulepos(&format->audiopage));
698 double videotime = qtheora_granule_time(&format->ts, qogg_page_granulepos(&format->videopage));
699 if(audiotime < videotime)
701 FS_Write(cls.capturevideo.videofile, format->audiopage.header, format->audiopage.header_len);
702 FS_Write(cls.capturevideo.videofile, format->audiopage.body, format->audiopage.body_len);
703 format->have_audiopage = false;
705 //fprintf(stderr, "a");
709 FS_Write(cls.capturevideo.videofile, format->videopage.header, format->videopage.header_len);
710 FS_Write(cls.capturevideo.videofile, format->videopage.body, format->videopage.body_len);
711 format->have_videopage = false;
713 //fprintf(stderr, "v");
720 //fprintf(stderr, ">");
723 static void SCR_CaptureVideo_Ogg_FlushInterleaving()
725 LOAD_FORMATSPECIFIC_OGG();
727 if(cls.capturevideo.soundrate)
728 if(format->have_audiopage)
730 FS_Write(cls.capturevideo.videofile, format->audiopage.header, format->audiopage.header_len);
731 FS_Write(cls.capturevideo.videofile, format->audiopage.body, format->audiopage.body_len);
732 format->have_audiopage = false;
735 if(format->have_videopage)
737 FS_Write(cls.capturevideo.videofile, format->videopage.header, format->videopage.header_len);
738 FS_Write(cls.capturevideo.videofile, format->videopage.body, format->videopage.body_len);
739 format->have_videopage = false;
743 static void SCR_CaptureVideo_Ogg_EndVideo()
745 LOAD_FORMATSPECIFIC_OGG();
749 // repeat the last frame so we can set the end-of-stream flag
750 qtheora_encode_YUVin(&format->ts, &format->yuv);
751 qtheora_encode_packetout(&format->ts, true, &pt);
752 qogg_stream_packetin(&format->to, &pt);
753 SCR_CaptureVideo_Ogg_Interleave();
755 if(cls.capturevideo.soundrate)
757 qvorbis_analysis_wrote(&format->vd, 0);
758 while(qvorbis_analysis_blockout(&format->vd, &format->vb) == 1)
760 qvorbis_analysis(&format->vb, NULL);
761 qvorbis_bitrate_addblock(&format->vb);
762 while(qvorbis_bitrate_flushpacket(&format->vd, &pt))
763 qogg_stream_packetin(&format->vo, &pt);
764 SCR_CaptureVideo_Ogg_Interleave();
768 SCR_CaptureVideo_Ogg_FlushInterleaving();
770 while(qogg_stream_pageout(&format->to, &pg) > 0)
772 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
773 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
776 if(cls.capturevideo.soundrate)
778 while(qogg_stream_pageout(&format->vo, &pg) > 0)
780 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
781 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
786 int result = qogg_stream_flush (&format->to, &pg);
788 fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
791 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
792 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
795 if(cls.capturevideo.soundrate)
798 int result = qogg_stream_flush (&format->vo, &pg);
800 fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
803 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
804 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
807 qogg_stream_clear(&format->vo);
808 qvorbis_block_clear(&format->vb);
809 qvorbis_dsp_clear(&format->vd);
812 qogg_stream_clear(&format->to);
813 qtheora_clear(&format->ts);
814 qvorbis_info_clear(&format->vi);
816 Mem_Free(format->yuv.y);
817 Mem_Free(format->yuv.u);
818 Mem_Free(format->yuv.v);
821 FS_Close(cls.capturevideo.videofile);
822 cls.capturevideo.videofile = NULL;
825 static void SCR_CaptureVideo_Ogg_ConvertFrame_BGRA_to_YUV()
827 LOAD_FORMATSPECIFIC_OGG();
829 int blockr, blockg, blockb;
830 unsigned char *b = cls.capturevideo.outbuffer;
831 int w = cls.capturevideo.width;
832 int h = cls.capturevideo.height;
835 for(y = 0; y < h; ++y)
837 for(b = cls.capturevideo.outbuffer + (h-1-y)*w*4, x = 0; x < w; ++x)
842 format->yuv.y[x + format->yuv.y_stride * y] =
843 cls.capturevideo.yuvnormalizetable[0][cls.capturevideo.rgbtoyuvscaletable[0][0][blockr] + cls.capturevideo.rgbtoyuvscaletable[0][1][blockg] + cls.capturevideo.rgbtoyuvscaletable[0][2][blockb]];
849 for(b = cls.capturevideo.outbuffer + (h-2-y)*w*4, x = 0; x < w/2; ++x)
851 blockr = (b[2] + b[6] + b[inpitch+2] + b[inpitch+6]) >> 2;
852 blockg = (b[1] + b[5] + b[inpitch+1] + b[inpitch+5]) >> 2;
853 blockb = (b[0] + b[4] + b[inpitch+0] + b[inpitch+4]) >> 2;
854 format->yuv.u[x + format->yuv.uv_stride * (y/2)] =
855 cls.capturevideo.yuvnormalizetable[1][cls.capturevideo.rgbtoyuvscaletable[1][0][blockr] + cls.capturevideo.rgbtoyuvscaletable[1][1][blockg] + cls.capturevideo.rgbtoyuvscaletable[1][2][blockb] + 128];
856 format->yuv.v[x + format->yuv.uv_stride * (y/2)] =
857 cls.capturevideo.yuvnormalizetable[2][cls.capturevideo.rgbtoyuvscaletable[2][0][blockr] + cls.capturevideo.rgbtoyuvscaletable[2][1][blockg] + cls.capturevideo.rgbtoyuvscaletable[2][2][blockb] + 128];
864 static void SCR_CaptureVideo_Ogg_VideoFrames(int num)
866 LOAD_FORMATSPECIFIC_OGG();
869 // data is in cls.capturevideo.outbuffer as BGRA and has size width*height
871 SCR_CaptureVideo_Ogg_ConvertFrame_BGRA_to_YUV();
875 qtheora_encode_YUVin(&format->ts, &format->yuv);
877 while(qtheora_encode_packetout(&format->ts, false, &pt))
878 qogg_stream_packetin(&format->to, &pt);
880 SCR_CaptureVideo_Ogg_Interleave();
884 static void SCR_CaptureVideo_Ogg_SoundFrame(const portable_sampleframe_t *paintbuffer, size_t length)
886 LOAD_FORMATSPECIFIC_OGG();
887 float **vorbis_buffer;
892 vorbis_buffer = qvorbis_analysis_buffer(&format->vd, length);
893 for(i = 0; i < length; ++i)
895 for(j = 0; j < cls.capturevideo.soundchannels; ++j)
896 vorbis_buffer[j][i] = paintbuffer[i].sample[j] / 32768.0f;
898 qvorbis_analysis_wrote(&format->vd, length);
900 while(qvorbis_analysis_blockout(&format->vd, &format->vb) == 1)
902 qvorbis_analysis(&format->vb, NULL);
903 qvorbis_bitrate_addblock(&format->vb);
905 while(qvorbis_bitrate_flushpacket(&format->vd, &pt))
906 qogg_stream_packetin(&format->vo, &pt);
909 SCR_CaptureVideo_Ogg_Interleave();
912 void SCR_CaptureVideo_Ogg_BeginVideo()
914 cls.capturevideo.format = CAPTUREVIDEOFORMAT_OGG_VORBIS_THEORA;
915 cls.capturevideo.videofile = FS_OpenRealFile(va("%s.ogv", cls.capturevideo.basename), "wb", false);
916 cls.capturevideo.endvideo = SCR_CaptureVideo_Ogg_EndVideo;
917 cls.capturevideo.videoframes = SCR_CaptureVideo_Ogg_VideoFrames;
918 cls.capturevideo.soundframe = SCR_CaptureVideo_Ogg_SoundFrame;
919 cls.capturevideo.formatspecific = Mem_Alloc(tempmempool, sizeof(capturevideostate_ogg_formatspecific_t));
921 LOAD_FORMATSPECIFIC_OGG();
924 ogg_packet pt, pt2, pt3;
929 format->serial1 = rand();
930 qogg_stream_init(&format->to, format->serial1);
932 if(cls.capturevideo.soundrate)
936 format->serial2 = rand();
938 while(format->serial1 == format->serial2);
939 qogg_stream_init(&format->vo, format->serial2);
942 format->have_videopage = format->have_audiopage = false;
944 qtheora_info_init(&ti);
945 ti.frame_width = cls.capturevideo.width;
946 ti.frame_height = cls.capturevideo.height;
947 ti.width = (ti.frame_width + 15) & ~15;
948 ti.height = (ti.frame_height + 15) & ~15;
949 //ti.offset_x = ((ti.width - ti.frame_width) / 2) & ~1;
950 //ti.offset_y = ((ti.height - ti.frame_height) / 2) & ~1;
952 format->yuv.y_width = ti.width;
953 format->yuv.y_height = ti.height;
954 format->yuv.y_stride = ti.width;
956 format->yuv.uv_width = ti.width / 2;
957 format->yuv.uv_height = ti.height / 2;
958 format->yuv.uv_stride = ti.width / 2;
960 format->yuv.y = Mem_Alloc(tempmempool, format->yuv.y_stride * format->yuv.y_height);
961 format->yuv.u = Mem_Alloc(tempmempool, format->yuv.uv_stride * format->yuv.uv_height);
962 format->yuv.v = Mem_Alloc(tempmempool, format->yuv.uv_stride * format->yuv.uv_height);
964 FindFraction(cls.capturevideo.framerate, &num, &denom, 1001);
965 ti.fps_numerator = num;
966 ti.fps_denominator = denom;
968 FindFraction(1 / vid_pixelheight.value, &num, &denom, 1000);
969 ti.aspect_numerator = num;
970 ti.aspect_denominator = denom;
972 ti.colorspace = OC_CS_UNSPECIFIED;
973 ti.pixelformat = OC_PF_420;
975 ti.quick_p = true; // http://mlblog.osdir.com/multimedia.ogg.theora.general/2004-07/index.shtml
976 ti.dropframes_p = false;
978 ti.target_bitrate = cl_capturevideo_ogg_theora_bitrate.integer * 1000;
979 ti.quality = cl_capturevideo_ogg_theora_quality.integer;
981 if(ti.target_bitrate <= 0)
985 ti.target_bitrate = -1;
986 ti.keyframe_data_target_bitrate = -1;
991 ti.target_bitrate = -1;
992 ti.keyframe_data_target_bitrate = -1;
993 ti.quality = bound(0, ti.quality, 63);
1000 ti.target_bitrate = bound(45000, ti.target_bitrate, 2000000);
1001 ti.keyframe_data_target_bitrate = ti.target_bitrate * max(1, cl_capturevideo_ogg_theora_keyframe_bitrate_multiplier.value);
1006 ti.target_bitrate = bound(45000, ti.target_bitrate, 2000000);
1007 ti.keyframe_data_target_bitrate = ti.target_bitrate * max(1, cl_capturevideo_ogg_theora_keyframe_bitrate_multiplier.value);
1012 ti.keyframe_frequency = bound(1, cl_capturevideo_ogg_theora_keyframe_frequency.integer, 1000);
1013 ti.keyframe_mindistance = bound(1, cl_capturevideo_ogg_theora_keyframe_mindistance.integer, (int) ti.keyframe_frequency);
1014 ti.noise_sensitivity = bound(0, cl_capturevideo_ogg_theora_noise_sensitivity.integer, 6);
1015 ti.sharpness = bound(0, cl_capturevideo_ogg_theora_sharpness.integer, 2);
1016 ti.keyframe_auto_threshold = bound(0, cl_capturevideo_ogg_theora_keyframe_auto_threshold.integer, 100);
1018 ti.keyframe_frequency_force = ti.keyframe_frequency;
1019 ti.keyframe_auto_p = (ti.keyframe_frequency != ti.keyframe_mindistance);
1021 qtheora_encode_init(&format->ts, &ti);
1022 qtheora_info_clear(&ti);
1025 if(cls.capturevideo.soundrate)
1027 qvorbis_info_init(&format->vi);
1028 qvorbis_encode_init_vbr(&format->vi, cls.capturevideo.soundchannels, cls.capturevideo.soundrate, bound(-1, cl_capturevideo_ogg_vorbis_quality.value, 10) * 0.099);
1029 qvorbis_comment_init(&vc);
1030 qvorbis_analysis_init(&format->vd, &format->vi);
1031 qvorbis_block_init(&format->vd, &format->vb);
1034 qtheora_comment_init(&tc);
1036 /* create the remaining theora headers */
1037 qtheora_encode_header(&format->ts, &pt);
1038 qogg_stream_packetin(&format->to, &pt);
1039 if (qogg_stream_pageout (&format->to, &pg) != 1)
1040 fprintf (stderr, "Internal Ogg library error.\n");
1041 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
1042 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
1044 qtheora_encode_comment(&tc, &pt);
1045 qogg_stream_packetin(&format->to, &pt);
1046 qtheora_encode_tables(&format->ts, &pt);
1047 qogg_stream_packetin (&format->to, &pt);
1049 qtheora_comment_clear(&tc);
1051 if(cls.capturevideo.soundrate)
1053 qvorbis_analysis_headerout(&format->vd, &vc, &pt, &pt2, &pt3);
1054 qogg_stream_packetin(&format->vo, &pt);
1055 if (qogg_stream_pageout (&format->vo, &pg) != 1)
1056 fprintf (stderr, "Internal Ogg library error.\n");
1057 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
1058 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
1060 qogg_stream_packetin(&format->vo, &pt2);
1061 qogg_stream_packetin(&format->vo, &pt3);
1063 qvorbis_comment_clear(&vc);
1068 int result = qogg_stream_flush (&format->to, &pg);
1070 fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
1073 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
1074 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
1077 if(cls.capturevideo.soundrate)
1080 int result = qogg_stream_flush (&format->vo, &pg);
1082 fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
1085 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
1086 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);