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"};
19 typedef int16_t ogg_int16_t;
20 typedef u_int16_t ogg_uint16_t;
21 typedef int32_t ogg_int32_t;
22 typedef u_int32_t ogg_uint32_t;
23 typedef int64_t ogg_int64_t;
29 unsigned char *buffer;
34 /* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/
37 unsigned char *header;
43 /* ogg_stream_state contains the current encode/decode state of a logical
44 Ogg bitstream **********************************************************/
47 unsigned char *body_data; /* bytes from packet bodies */
48 long body_storage; /* storage elements allocated */
49 long body_fill; /* elements stored; fill mark */
50 long body_returned; /* elements of fill returned */
53 int *lacing_vals; /* The values that will go to the segment table */
54 ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact
55 this way, but it is simple coupled to the
62 unsigned char header[282]; /* working space for header encode */
65 int e_o_s; /* set when we have buffered the last packet in the
67 int b_o_s; /* set after we've written the initial page
68 of a logical bitstream */
71 ogg_int64_t packetno; /* sequence number for decode; the framing
72 knows where there's a hole in the data,
73 but we need coupling so that the codec
74 (which is in a seperate abstraction
75 layer) also knows about the gap */
76 ogg_int64_t granulepos;
80 /* ogg_packet is used to encapsulate the data and metadata belonging
81 to a single raw Ogg/Vorbis packet *************************************/
84 unsigned char *packet;
89 ogg_int64_t granulepos;
91 ogg_int64_t packetno; /* sequence number for decode; the framing
92 knows where there's a hole in the data,
93 but we need coupling so that the codec
94 (which is in a seperate abstraction
95 layer) also knows about the gap */
109 /* Ogg BITSTREAM PRIMITIVES: encoding **************************/
111 static int (*qogg_stream_packetin) (ogg_stream_state *os, ogg_packet *op);
112 static int (*qogg_stream_pageout) (ogg_stream_state *os, ogg_page *og);
113 static int (*qogg_stream_flush) (ogg_stream_state *os, ogg_page *og);
115 /* Ogg BITSTREAM PRIMITIVES: general ***************************/
117 static int (*qogg_stream_init) (ogg_stream_state *os,int serialno);
118 static int (*qogg_stream_clear) (ogg_stream_state *os);
119 static ogg_int64_t (*qogg_page_granulepos) (ogg_page *og);
121 // end of ogg.h stuff
123 // vorbis/codec.h stuff
124 typedef struct vorbis_info{
129 /* The below bitrate declarations are *hints*.
130 Combinations of the three values carry the following implications:
132 all three set to the same value:
133 implies a fixed rate bitstream
135 implies a VBR stream that averages the nominal bitrate. No hard
137 upper and or lower set:
138 implies a VBR bitstream that obeys the bitrate limits. nominal
139 may also be set to give a nominal rate.
141 the coder does not care to speculate.
145 long bitrate_nominal;
152 /* vorbis_dsp_state buffers the current vorbis audio
153 analysis/synthesis state. The DSP state belongs to a specific
154 logical bitstream ****************************************************/
155 typedef struct vorbis_dsp_state{
173 ogg_int64_t granulepos;
174 ogg_int64_t sequence;
176 ogg_int64_t glue_bits;
177 ogg_int64_t time_bits;
178 ogg_int64_t floor_bits;
179 ogg_int64_t res_bits;
184 typedef struct vorbis_block{
185 /* necessary stream state for linking to the framing abstraction */
186 float **pcm; /* this is a pointer into local storage */
196 ogg_int64_t granulepos;
197 ogg_int64_t sequence;
198 vorbis_dsp_state *vd; /* For read-only access of configuration */
200 /* local storage to avoid remallocing; it's up to the mapping to
206 struct alloc_chain *reap;
208 /* bitmetrics for the frame */
218 /* vorbis_block is a single block of data to be processed as part of
219 the analysis/synthesis stream; it belongs to a specific logical
220 bitstream, but is independant from other vorbis_blocks belonging to
221 that logical bitstream. *************************************************/
225 struct alloc_chain *next;
228 /* vorbis_info contains all the setup information specific to the
229 specific compression/decompression mode in progress (eg,
230 psychoacoustic settings, channel setup, options, codebook
231 etc). vorbis_info and substructures are in backends.h.
232 *********************************************************************/
234 /* the comments are not part of vorbis_info so that vorbis_info can be
236 typedef struct vorbis_comment{
237 /* unlimited user comment fields. libvorbis writes 'libvorbis'
238 whatever vendor is set to in encode */
239 char **user_comments;
240 int *comment_lengths;
247 /* libvorbis encodes in two abstraction layers; first we perform DSP
248 and produce a packet (see docs/analysis.txt). The packet is then
249 coded into a framed OggSquish bitstream by the second layer (see
250 docs/framing.txt). Decode is the reverse process; we sync/frame
251 the bitstream and extract individual packets, then decode the
252 packet back into PCM audio.
254 The extra framing/packetizing is used in streaming formats, such as
255 files. Over the net (such as with UDP), the framing and
256 packetization aren't necessary as they're provided by the transport
257 and the streaming layer is not used */
259 /* Vorbis PRIMITIVES: general ***************************************/
261 static void (*qvorbis_info_init) (vorbis_info *vi);
262 static void (*qvorbis_info_clear) (vorbis_info *vi);
263 static void (*qvorbis_comment_init) (vorbis_comment *vc);
264 static void (*qvorbis_comment_clear) (vorbis_comment *vc);
266 static int (*qvorbis_block_init) (vorbis_dsp_state *v, vorbis_block *vb);
267 static int (*qvorbis_block_clear) (vorbis_block *vb);
268 static void (*qvorbis_dsp_clear) (vorbis_dsp_state *v);
269 static double (*qvorbis_granule_time) (vorbis_dsp_state *v,
270 ogg_int64_t granulepos);
272 /* Vorbis PRIMITIVES: analysis/DSP layer ****************************/
274 static int (*qvorbis_analysis_init) (vorbis_dsp_state *v,vorbis_info *vi);
275 static int (*qvorbis_commentheader_out) (vorbis_comment *vc, ogg_packet *op);
276 static int (*qvorbis_analysis_headerout) (vorbis_dsp_state *v,
280 ogg_packet *op_code);
281 static float ** (*qvorbis_analysis_buffer) (vorbis_dsp_state *v,int vals);
282 static int (*qvorbis_analysis_wrote) (vorbis_dsp_state *v,int vals);
283 static int (*qvorbis_analysis_blockout) (vorbis_dsp_state *v,vorbis_block *vb);
284 static int (*qvorbis_analysis) (vorbis_block *vb,ogg_packet *op);
286 static int (*qvorbis_bitrate_addblock) (vorbis_block *vb);
287 static int (*qvorbis_bitrate_flushpacket) (vorbis_dsp_state *vd,
290 // end of vorbis/codec.h stuff
293 static int (*qvorbis_encode_init_vbr) (vorbis_info *vi,
297 float base_quality /* quality level from 0. (lo) to 1. (hi) */
299 // end of vorbisenc.h stuff
303 int y_width; /**< Width of the Y' luminance plane */
304 int y_height; /**< Height of the luminance plane */
305 int y_stride; /**< Offset in bytes between successive rows */
307 int uv_width; /**< Width of the Cb and Cr chroma planes */
308 int uv_height; /**< Height of the chroma planes */
309 int uv_stride; /**< Offset between successive chroma rows */
310 unsigned char *y; /**< Pointer to start of luminance data */
311 unsigned char *u; /**< Pointer to start of Cb data */
312 unsigned char *v; /**< Pointer to start of Cr data */
320 OC_CS_UNSPECIFIED, /**< The colorspace is unknown or unspecified */
321 OC_CS_ITU_REC_470M, /**< This is the best option for 'NTSC' content */
322 OC_CS_ITU_REC_470BG, /**< This is the best option for 'PAL' content */
323 OC_CS_NSPACES /**< This marks the end of the defined colorspaces */
327 * A Chroma subsampling
329 * These enumerate the available chroma subsampling options supported
330 * by the theora format. See Section 4.4 of the specification for
334 OC_PF_420, /**< Chroma subsampling by 2 in each direction (4:2:0) */
335 OC_PF_RSVD, /**< Reserved value */
336 OC_PF_422, /**< Horizonatal chroma subsampling by 2 (4:2:2) */
337 OC_PF_444, /**< No chroma subsampling at all (4:4:4) */
338 } theora_pixelformat;
340 * Theora bitstream info.
341 * Contains the basic playback parameters for a stream,
342 * corresponding to the initial 'info' header packet.
344 * Encoded theora frames must be a multiple of 16 in width and height.
345 * To handle other frame sizes, a crop rectangle is specified in
346 * frame_height and frame_width, offset_x and * offset_y. The offset
347 * and size should still be a multiple of 2 to avoid chroma sampling
348 * shifts. Offset values in this structure are measured from the
349 * upper left of the image.
351 * Frame rate, in frames per second, is stored as a rational
352 * fraction. Aspect ratio is also stored as a rational fraction, and
353 * refers to the aspect ratio of the frame pixels, not of the
354 * overall frame itself.
356 * See <a href="http://svn.xiph.org/trunk/theora/examples/encoder_example.c">
357 * examples/encoder_example.c</a> for usage examples of the
358 * other paramters and good default settings for the encoder parameters.
361 ogg_uint32_t width; /**< encoded frame width */
362 ogg_uint32_t height; /**< encoded frame height */
363 ogg_uint32_t frame_width; /**< display frame width */
364 ogg_uint32_t frame_height; /**< display frame height */
365 ogg_uint32_t offset_x; /**< horizontal offset of the displayed frame */
366 ogg_uint32_t offset_y; /**< vertical offset of the displayed frame */
367 ogg_uint32_t fps_numerator; /**< frame rate numerator **/
368 ogg_uint32_t fps_denominator; /**< frame rate denominator **/
369 ogg_uint32_t aspect_numerator; /**< pixel aspect ratio numerator */
370 ogg_uint32_t aspect_denominator; /**< pixel aspect ratio denominator */
371 theora_colorspace colorspace; /**< colorspace */
372 int target_bitrate; /**< nominal bitrate in bits per second */
373 int quality; /**< Nominal quality setting, 0-63 */
374 int quick_p; /**< Quick encode/decode */
377 unsigned char version_major;
378 unsigned char version_minor;
379 unsigned char version_subminor;
386 ogg_uint32_t keyframe_frequency;
387 ogg_uint32_t keyframe_frequency_force; /* also used for decode init to
388 get granpos shift correct */
389 ogg_uint32_t keyframe_data_target_bitrate;
390 ogg_int32_t keyframe_auto_threshold;
391 ogg_uint32_t keyframe_mindistance;
392 ogg_int32_t noise_sensitivity;
393 ogg_int32_t sharpness;
395 theora_pixelformat pixelformat; /**< chroma subsampling mode to expect */
399 /** Codec internal state and context.
403 ogg_int64_t granulepos;
405 void *internal_encode;
406 void *internal_decode;
411 * Comment header metadata.
413 * This structure holds the in-stream metadata corresponding to
414 * the 'comment' header packet.
416 * Meta data is stored as a series of (tag, value) pairs, in
417 * length-encoded string vectors. The first occurence of the
418 * '=' character delimits the tag and value. A particular tag
419 * may occur more than once. The character set encoding for
420 * the strings is always UTF-8, but the tag names are limited
421 * to case-insensitive ASCII. See the spec for details.
423 * In filling in this structure, qtheora_decode_header() will
424 * null-terminate the user_comment strings for safety. However,
425 * the bitstream format itself treats them as 8-bit clean,
426 * and so the length array should be treated as authoritative
429 typedef struct theora_comment{
430 char **user_comments; /**< An array of comment string vectors */
431 int *comment_lengths; /**< An array of corresponding string vector lengths in bytes */
432 int comments; /**< The total number of comment string vectors */
433 char *vendor; /**< The vendor string identifying the encoder, null terminated */
436 static int (*qtheora_encode_init) (theora_state *th, theora_info *ti);
437 static int (*qtheora_encode_YUVin) (theora_state *t, yuv_buffer *yuv);
438 static int (*qtheora_encode_packetout) ( theora_state *t, int last_p,
440 static int (*qtheora_encode_header) (theora_state *t, ogg_packet *op);
441 static int (*qtheora_encode_comment) (theora_comment *tc, ogg_packet *op);
442 static int (*qtheora_encode_tables) (theora_state *t, ogg_packet *op);
443 static void (*qtheora_info_init) (theora_info *c);
444 static void (*qtheora_info_clear) (theora_info *c);
445 static void (*qtheora_clear) (theora_state *t);
446 static void (*qtheora_comment_init) (theora_comment *tc);
447 static void (*qtheora_comment_clear) (theora_comment *tc);
448 static double (*qtheora_granule_time) (theora_state *th,ogg_int64_t granulepos);
449 // end of theora.h stuff
451 static dllfunction_t oggfuncs[] =
453 {"ogg_stream_packetin", (void **) &qogg_stream_packetin},
454 {"ogg_stream_pageout", (void **) &qogg_stream_pageout},
455 {"ogg_stream_flush", (void **) &qogg_stream_flush},
456 {"ogg_stream_init", (void **) &qogg_stream_init},
457 {"ogg_stream_clear", (void **) &qogg_stream_clear},
458 {"ogg_page_granulepos", (void **) &qogg_page_granulepos},
462 static dllfunction_t vorbisencfuncs[] =
464 {"vorbis_encode_init_vbr", (void **) &qvorbis_encode_init_vbr},
468 static dllfunction_t vorbisfuncs[] =
470 {"vorbis_info_init", (void **) &qvorbis_info_init},
471 {"vorbis_info_clear", (void **) &qvorbis_info_clear},
472 {"vorbis_comment_init", (void **) &qvorbis_comment_init},
473 {"vorbis_comment_clear", (void **) &qvorbis_comment_clear},
474 {"vorbis_block_init", (void **) &qvorbis_block_init},
475 {"vorbis_block_clear", (void **) &qvorbis_block_clear},
476 {"vorbis_dsp_clear", (void **) &qvorbis_dsp_clear},
477 {"vorbis_analysis_init", (void **) &qvorbis_analysis_init},
478 {"vorbis_commentheader_out", (void **) &qvorbis_commentheader_out},
479 {"vorbis_analysis_headerout", (void **) &qvorbis_analysis_headerout},
480 {"vorbis_analysis_buffer", (void **) &qvorbis_analysis_buffer},
481 {"vorbis_analysis_wrote", (void **) &qvorbis_analysis_wrote},
482 {"vorbis_analysis_blockout", (void **) &qvorbis_analysis_blockout},
483 {"vorbis_analysis", (void **) &qvorbis_analysis},
484 {"vorbis_bitrate_addblock", (void **) &qvorbis_bitrate_addblock},
485 {"vorbis_bitrate_flushpacket", (void **) &qvorbis_bitrate_flushpacket},
486 {"vorbis_granule_time", (void **) &qvorbis_granule_time},
490 static dllfunction_t theorafuncs[] =
492 {"theora_info_init", (void **) &qtheora_info_init},
493 {"theora_info_clear", (void **) &qtheora_info_clear},
494 {"theora_comment_init", (void **) &qtheora_comment_init},
495 {"theora_comment_clear", (void **) &qtheora_comment_clear},
496 {"theora_encode_init", (void **) &qtheora_encode_init},
497 {"theora_encode_YUVin", (void **) &qtheora_encode_YUVin},
498 {"theora_encode_packetout", (void **) &qtheora_encode_packetout},
499 {"theora_encode_header", (void **) &qtheora_encode_header},
500 {"theora_encode_comment", (void **) &qtheora_encode_comment},
501 {"theora_encode_tables", (void **) &qtheora_encode_tables},
502 {"theora_clear", (void **) &qtheora_clear},
503 {"theora_granule_time", (void **) &qtheora_granule_time},
507 static dllhandle_t og_dll = NULL, vo_dll = NULL, ve_dll = NULL, th_dll = NULL;
509 qboolean SCR_CaptureVideo_Ogg_OpenLibrary()
511 const char* dllnames_og [] =
518 #elif defined(MACOSX)
526 const char* dllnames_vo [] =
533 #elif defined(MACOSX)
541 const char* dllnames_ve [] =
544 "libvorbisenc64.dll",
548 #elif defined(MACOSX)
549 "libvorbisenc.dylib",
556 const char* dllnames_th [] =
563 #elif defined(MACOSX)
573 Sys_LoadLibrary (dllnames_og, &og_dll, oggfuncs)
575 Sys_LoadLibrary (dllnames_th, &th_dll, theorafuncs)
577 Sys_LoadLibrary (dllnames_vo, &vo_dll, vorbisfuncs)
579 Sys_LoadLibrary (dllnames_ve, &ve_dll, vorbisencfuncs);
582 void SCR_CaptureVideo_Ogg_Init()
584 SCR_CaptureVideo_Ogg_OpenLibrary();
586 Cvar_RegisterVariable(&cl_capturevideo_ogg_theora_quality);
587 Cvar_RegisterVariable(&cl_capturevideo_ogg_theora_bitrate);
588 Cvar_RegisterVariable(&cl_capturevideo_ogg_theora_keyframe_bitrate_multiplier);
589 Cvar_RegisterVariable(&cl_capturevideo_ogg_theora_keyframe_frequency);
590 Cvar_RegisterVariable(&cl_capturevideo_ogg_theora_keyframe_mindistance);
591 Cvar_RegisterVariable(&cl_capturevideo_ogg_theora_keyframe_auto_threshold);
592 Cvar_RegisterVariable(&cl_capturevideo_ogg_theora_noise_sensitivity);
593 Cvar_RegisterVariable(&cl_capturevideo_ogg_vorbis_quality);
596 qboolean SCR_CaptureVideo_Ogg_Available()
598 return og_dll && th_dll && vo_dll && ve_dll;
601 void SCR_CaptureVideo_Ogg_CloseDLL()
603 Sys_UnloadLibrary (&ve_dll);
604 Sys_UnloadLibrary (&vo_dll);
605 Sys_UnloadLibrary (&th_dll);
606 Sys_UnloadLibrary (&og_dll);
609 typedef struct capturevideostate_ogg_formatspecific_s
611 ogg_stream_state to, vo;
612 int serial1, serial2;
623 qboolean have_videopage;
624 qboolean have_audiopage;
626 capturevideostate_ogg_formatspecific_t;
627 #define LOAD_FORMATSPECIFIC_OGG() capturevideostate_ogg_formatspecific_t *format = (capturevideostate_ogg_formatspecific_t *) cls.capturevideo.formatspecific
629 static void SCR_CaptureVideo_Ogg_Interleave()
631 LOAD_FORMATSPECIFIC_OGG();
633 //fprintf(stderr, "<");
635 if(!cls.capturevideo.soundrate)
639 // first: make sure we have a page of both types
640 if(!format->have_videopage)
641 if(qogg_stream_pageout(&format->to, &format->videopage) > 0)
642 format->have_videopage = true;
643 if(format->have_videopage)
645 FS_Write(cls.capturevideo.videofile, format->videopage.header, format->videopage.header_len);
646 FS_Write(cls.capturevideo.videofile, format->videopage.body, format->videopage.body_len);
647 format->have_videopage = false;
655 // first: make sure we have a page of both types
656 if(!format->have_videopage)
657 if(qogg_stream_pageout(&format->to, &format->videopage) > 0)
659 //fprintf(stderr, "V");
660 format->have_videopage = true;
662 // why do I have to do this? the code should work without the
663 // following three lines, which turn this attempt at correct
664 // interleaving back into the old stupid one that oggz-validate
666 FS_Write(cls.capturevideo.videofile, format->videopage.header, format->videopage.header_len);
667 FS_Write(cls.capturevideo.videofile, format->videopage.body, format->videopage.body_len);
668 format->have_videopage = false;
670 if(!format->have_audiopage)
671 if(qogg_stream_pageout(&format->vo, &format->audiopage) > 0)
673 //fprintf(stderr, "A");
674 format->have_audiopage = true;
676 // why do I have to do this? the code should work without the
677 // following three lines, which turn this attempt at correct
678 // interleaving back into the old stupid one that oggz-validate
680 FS_Write(cls.capturevideo.videofile, format->audiopage.header, format->audiopage.header_len);
681 FS_Write(cls.capturevideo.videofile, format->audiopage.body, format->audiopage.body_len);
682 format->have_audiopage = false;
685 if(format->have_videopage && format->have_audiopage)
687 // output the page that ends first
688 double audiotime = qvorbis_granule_time(&format->vd, qogg_page_granulepos(&format->audiopage));
689 double videotime = qtheora_granule_time(&format->ts, qogg_page_granulepos(&format->videopage));
690 if(audiotime < videotime)
692 FS_Write(cls.capturevideo.videofile, format->audiopage.header, format->audiopage.header_len);
693 FS_Write(cls.capturevideo.videofile, format->audiopage.body, format->audiopage.body_len);
694 format->have_audiopage = false;
696 //fprintf(stderr, "a");
700 FS_Write(cls.capturevideo.videofile, format->videopage.header, format->videopage.header_len);
701 FS_Write(cls.capturevideo.videofile, format->videopage.body, format->videopage.body_len);
702 format->have_videopage = false;
704 //fprintf(stderr, "v");
711 fprintf(stderr, ">");
715 static void SCR_CaptureVideo_Ogg_FlushInterleaving()
717 LOAD_FORMATSPECIFIC_OGG();
719 if(cls.capturevideo.soundrate)
720 if(format->have_audiopage)
722 FS_Write(cls.capturevideo.videofile, format->audiopage.header, format->audiopage.header_len);
723 FS_Write(cls.capturevideo.videofile, format->audiopage.body, format->audiopage.body_len);
724 format->have_audiopage = false;
727 if(format->have_videopage)
729 FS_Write(cls.capturevideo.videofile, format->videopage.header, format->videopage.header_len);
730 FS_Write(cls.capturevideo.videofile, format->videopage.body, format->videopage.body_len);
731 format->have_videopage = false;
735 static void SCR_CaptureVideo_Ogg_EndVideo()
737 LOAD_FORMATSPECIFIC_OGG();
741 // repeat the last frame so we can set the end-of-stream flag
742 qtheora_encode_YUVin(&format->ts, &format->yuv);
743 qtheora_encode_packetout(&format->ts, true, &pt);
744 qogg_stream_packetin(&format->to, &pt);
745 SCR_CaptureVideo_Ogg_Interleave();
747 if(cls.capturevideo.soundrate)
749 qvorbis_analysis_wrote(&format->vd, 0);
750 while(qvorbis_analysis_blockout(&format->vd, &format->vb) == 1)
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 SCR_CaptureVideo_Ogg_Interleave();
760 SCR_CaptureVideo_Ogg_FlushInterleaving();
762 while(qogg_stream_pageout(&format->to, &pg) > 0)
764 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
765 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
768 if(cls.capturevideo.soundrate)
770 while(qogg_stream_pageout(&format->vo, &pg) > 0)
772 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
773 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
778 int result = qogg_stream_flush (&format->to, &pg);
780 fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
783 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
784 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
787 if(cls.capturevideo.soundrate)
790 int result = qogg_stream_flush (&format->vo, &pg);
792 fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
795 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
796 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
799 qogg_stream_clear(&format->vo);
800 qvorbis_block_clear(&format->vb);
801 qvorbis_dsp_clear(&format->vd);
804 qogg_stream_clear(&format->to);
805 qtheora_clear(&format->ts);
806 qvorbis_info_clear(&format->vi);
808 Mem_Free(format->yuv.y);
809 Mem_Free(format->yuv.u);
810 Mem_Free(format->yuv.v);
813 FS_Close(cls.capturevideo.videofile);
814 cls.capturevideo.videofile = NULL;
817 static void SCR_CaptureVideo_Ogg_ConvertFrame_BGRA_to_YUV()
819 LOAD_FORMATSPECIFIC_OGG();
821 int blockr, blockg, blockb;
822 unsigned char *b = cls.capturevideo.outbuffer;
823 int w = cls.capturevideo.width;
824 int h = cls.capturevideo.height;
827 for(y = 0; y < h; ++y)
829 for(b = cls.capturevideo.outbuffer + (h-1-y)*w*4, x = 0; x < w; ++x)
834 format->yuv.y[x + format->yuv.y_stride * y] =
835 cls.capturevideo.yuvnormalizetable[0][cls.capturevideo.rgbtoyuvscaletable[0][0][blockr] + cls.capturevideo.rgbtoyuvscaletable[0][1][blockg] + cls.capturevideo.rgbtoyuvscaletable[0][2][blockb]];
841 for(b = cls.capturevideo.outbuffer + (h-2-y)*w*4, x = 0; x < w/2; ++x)
843 blockr = (b[2] + b[6] + b[inpitch+2] + b[inpitch+6]) >> 2;
844 blockg = (b[1] + b[5] + b[inpitch+1] + b[inpitch+5]) >> 2;
845 blockb = (b[0] + b[4] + b[inpitch+0] + b[inpitch+4]) >> 2;
846 format->yuv.u[x + format->yuv.uv_stride * (y/2)] =
847 cls.capturevideo.yuvnormalizetable[1][cls.capturevideo.rgbtoyuvscaletable[1][0][blockr] + cls.capturevideo.rgbtoyuvscaletable[1][1][blockg] + cls.capturevideo.rgbtoyuvscaletable[1][2][blockb] + 128];
848 format->yuv.v[x + format->yuv.uv_stride * (y/2)] =
849 cls.capturevideo.yuvnormalizetable[2][cls.capturevideo.rgbtoyuvscaletable[2][0][blockr] + cls.capturevideo.rgbtoyuvscaletable[2][1][blockg] + cls.capturevideo.rgbtoyuvscaletable[2][2][blockb] + 128];
856 static void SCR_CaptureVideo_Ogg_VideoFrames(int num)
858 LOAD_FORMATSPECIFIC_OGG();
861 // data is in cls.capturevideo.outbuffer as BGRA and has size width*height
863 SCR_CaptureVideo_Ogg_ConvertFrame_BGRA_to_YUV();
867 qtheora_encode_YUVin(&format->ts, &format->yuv);
869 while(qtheora_encode_packetout(&format->ts, false, &pt))
870 qogg_stream_packetin(&format->to, &pt);
872 SCR_CaptureVideo_Ogg_Interleave();
876 static void SCR_CaptureVideo_Ogg_SoundFrame(const portable_sampleframe_t *paintbuffer, size_t length)
878 LOAD_FORMATSPECIFIC_OGG();
879 float **vorbis_buffer;
884 vorbis_buffer = qvorbis_analysis_buffer(&format->vd, length);
885 for(i = 0; i < length; ++i)
887 for(j = 0; j < cls.capturevideo.soundchannels; ++j)
888 vorbis_buffer[j][i] = paintbuffer[i].sample[j] / 32768.0f;
890 qvorbis_analysis_wrote(&format->vd, length);
892 while(qvorbis_analysis_blockout(&format->vd, &format->vb) == 1)
894 qvorbis_analysis(&format->vb, NULL);
895 qvorbis_bitrate_addblock(&format->vb);
897 while(qvorbis_bitrate_flushpacket(&format->vd, &pt))
898 qogg_stream_packetin(&format->vo, &pt);
901 SCR_CaptureVideo_Ogg_Interleave();
904 void SCR_CaptureVideo_Ogg_BeginVideo()
906 cls.capturevideo.format = CAPTUREVIDEOFORMAT_OGG_VORBIS_THEORA;
907 cls.capturevideo.videofile = FS_OpenRealFile(va("%s.ogv", cls.capturevideo.basename), "wb", false);
908 cls.capturevideo.endvideo = SCR_CaptureVideo_Ogg_EndVideo;
909 cls.capturevideo.videoframes = SCR_CaptureVideo_Ogg_VideoFrames;
910 cls.capturevideo.soundframe = SCR_CaptureVideo_Ogg_SoundFrame;
911 cls.capturevideo.formatspecific = Mem_Alloc(tempmempool, sizeof(capturevideostate_ogg_formatspecific_t));
913 LOAD_FORMATSPECIFIC_OGG();
916 ogg_packet pt, pt2, pt3;
921 format->serial1 = rand();
922 qogg_stream_init(&format->to, format->serial1);
924 if(cls.capturevideo.soundrate)
928 format->serial2 = rand();
930 while(format->serial1 == format->serial2);
931 qogg_stream_init(&format->vo, format->serial2);
934 format->have_videopage = format->have_audiopage = false;
936 qtheora_info_init(&ti);
937 ti.frame_width = cls.capturevideo.width;
938 ti.frame_height = cls.capturevideo.height;
939 ti.width = (ti.frame_width + 15) & ~15;
940 ti.height = (ti.frame_height + 15) & ~15;
941 //ti.offset_x = ((ti.width - ti.frame_width) / 2) & ~1;
942 //ti.offset_y = ((ti.height - ti.frame_height) / 2) & ~1;
944 format->yuv.y_width = ti.width;
945 format->yuv.y_height = ti.height;
946 format->yuv.y_stride = ti.width;
948 format->yuv.uv_width = ti.width / 2;
949 format->yuv.uv_height = ti.height / 2;
950 format->yuv.uv_stride = ti.width / 2;
952 format->yuv.y = Mem_Alloc(tempmempool, format->yuv.y_stride * format->yuv.y_height);
953 format->yuv.u = Mem_Alloc(tempmempool, format->yuv.uv_stride * format->yuv.uv_height);
954 format->yuv.v = Mem_Alloc(tempmempool, format->yuv.uv_stride * format->yuv.uv_height);
956 FindFraction(cls.capturevideo.framerate, &num, &denom, 1001);
957 ti.fps_numerator = num;
958 ti.fps_denominator = denom;
960 FindFraction(1 / vid_pixelheight.value, &num, &denom, 1000);
961 ti.aspect_numerator = num;
962 ti.aspect_denominator = denom;
964 ti.colorspace = OC_CS_UNSPECIFIED;
965 ti.pixelformat = OC_PF_420;
967 ti.quick_p = true; // http://mlblog.osdir.com/multimedia.ogg.theora.general/2004-07/index.shtml
968 ti.dropframes_p = false;
970 ti.target_bitrate = cl_capturevideo_ogg_theora_bitrate.integer * 1000;
971 ti.quality = cl_capturevideo_ogg_theora_quality.integer;
973 if(ti.target_bitrate <= 0)
977 ti.target_bitrate = -1;
978 ti.keyframe_data_target_bitrate = -1;
983 ti.target_bitrate = -1;
984 ti.keyframe_data_target_bitrate = -1;
985 ti.quality = bound(0, ti.quality, 63);
992 ti.target_bitrate = bound(45000, ti.target_bitrate, 2000000);
993 ti.keyframe_data_target_bitrate = ti.target_bitrate * max(1, cl_capturevideo_ogg_theora_keyframe_bitrate_multiplier.value);
998 ti.target_bitrate = bound(45000, ti.target_bitrate, 2000000);
999 ti.keyframe_data_target_bitrate = ti.target_bitrate * max(1, cl_capturevideo_ogg_theora_keyframe_bitrate_multiplier.value);
1004 ti.keyframe_frequency = bound(1, cl_capturevideo_ogg_theora_keyframe_frequency.integer, 1000);
1005 ti.keyframe_mindistance = bound(1, cl_capturevideo_ogg_theora_keyframe_mindistance.integer, (int) ti.keyframe_frequency);
1006 ti.noise_sensitivity = bound(0, cl_capturevideo_ogg_theora_noise_sensitivity.integer, 6);
1007 ti.sharpness = bound(0, cl_capturevideo_ogg_theora_sharpness.integer, 2);
1008 ti.keyframe_auto_threshold = bound(0, cl_capturevideo_ogg_theora_keyframe_auto_threshold.integer, 100);
1010 ti.keyframe_frequency_force = ti.keyframe_frequency;
1011 ti.keyframe_auto_p = (ti.keyframe_frequency != ti.keyframe_mindistance);
1013 qtheora_encode_init(&format->ts, &ti);
1014 qtheora_info_clear(&ti);
1017 if(cls.capturevideo.soundrate)
1019 qvorbis_info_init(&format->vi);
1020 qvorbis_encode_init_vbr(&format->vi, cls.capturevideo.soundchannels, cls.capturevideo.soundrate, bound(-1, cl_capturevideo_ogg_vorbis_quality.value, 10) * 0.099);
1021 qvorbis_comment_init(&vc);
1022 qvorbis_analysis_init(&format->vd, &format->vi);
1023 qvorbis_block_init(&format->vd, &format->vb);
1026 qtheora_comment_init(&tc);
1028 /* create the remaining theora headers */
1029 qtheora_encode_header(&format->ts, &pt);
1030 qogg_stream_packetin(&format->to, &pt);
1031 if (qogg_stream_pageout (&format->to, &pg) != 1)
1032 fprintf (stderr, "Internal Ogg library error.\n");
1033 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
1034 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
1036 qtheora_encode_comment(&tc, &pt);
1037 qogg_stream_packetin(&format->to, &pt);
1038 qtheora_encode_tables(&format->ts, &pt);
1039 qogg_stream_packetin (&format->to, &pt);
1041 qtheora_comment_clear(&tc);
1043 if(cls.capturevideo.soundrate)
1045 qvorbis_analysis_headerout(&format->vd, &vc, &pt, &pt2, &pt3);
1046 qogg_stream_packetin(&format->vo, &pt);
1047 if (qogg_stream_pageout (&format->vo, &pg) != 1)
1048 fprintf (stderr, "Internal Ogg library error.\n");
1049 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
1050 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
1052 qogg_stream_packetin(&format->vo, &pt2);
1053 qogg_stream_packetin(&format->vo, &pt3);
1055 qvorbis_comment_clear(&vc);
1060 int result = qogg_stream_flush (&format->to, &pg);
1062 fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
1065 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
1066 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
1069 if(cls.capturevideo.soundrate)
1072 int result = qogg_stream_flush (&format->vo, &pg);
1074 fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
1077 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
1078 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);