8 static cvar_t cl_capturevideo_ogg_theora_quality = {CVAR_SAVE, "cl_capturevideo_ogg_theora_quality", "16", "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);
120 // end of ogg.h stuff
122 // vorbis/codec.h stuff
123 typedef struct vorbis_info{
128 /* The below bitrate declarations are *hints*.
129 Combinations of the three values carry the following implications:
131 all three set to the same value:
132 implies a fixed rate bitstream
134 implies a VBR stream that averages the nominal bitrate. No hard
136 upper and or lower set:
137 implies a VBR bitstream that obeys the bitrate limits. nominal
138 may also be set to give a nominal rate.
140 the coder does not care to speculate.
144 long bitrate_nominal;
151 /* vorbis_dsp_state buffers the current vorbis audio
152 analysis/synthesis state. The DSP state belongs to a specific
153 logical bitstream ****************************************************/
154 typedef struct vorbis_dsp_state{
172 ogg_int64_t granulepos;
173 ogg_int64_t sequence;
175 ogg_int64_t glue_bits;
176 ogg_int64_t time_bits;
177 ogg_int64_t floor_bits;
178 ogg_int64_t res_bits;
183 typedef struct vorbis_block{
184 /* necessary stream state for linking to the framing abstraction */
185 float **pcm; /* this is a pointer into local storage */
195 ogg_int64_t granulepos;
196 ogg_int64_t sequence;
197 vorbis_dsp_state *vd; /* For read-only access of configuration */
199 /* local storage to avoid remallocing; it's up to the mapping to
205 struct alloc_chain *reap;
207 /* bitmetrics for the frame */
217 /* vorbis_block is a single block of data to be processed as part of
218 the analysis/synthesis stream; it belongs to a specific logical
219 bitstream, but is independant from other vorbis_blocks belonging to
220 that logical bitstream. *************************************************/
224 struct alloc_chain *next;
227 /* vorbis_info contains all the setup information specific to the
228 specific compression/decompression mode in progress (eg,
229 psychoacoustic settings, channel setup, options, codebook
230 etc). vorbis_info and substructures are in backends.h.
231 *********************************************************************/
233 /* the comments are not part of vorbis_info so that vorbis_info can be
235 typedef struct vorbis_comment{
236 /* unlimited user comment fields. libvorbis writes 'libvorbis'
237 whatever vendor is set to in encode */
238 char **user_comments;
239 int *comment_lengths;
246 /* libvorbis encodes in two abstraction layers; first we perform DSP
247 and produce a packet (see docs/analysis.txt). The packet is then
248 coded into a framed OggSquish bitstream by the second layer (see
249 docs/framing.txt). Decode is the reverse process; we sync/frame
250 the bitstream and extract individual packets, then decode the
251 packet back into PCM audio.
253 The extra framing/packetizing is used in streaming formats, such as
254 files. Over the net (such as with UDP), the framing and
255 packetization aren't necessary as they're provided by the transport
256 and the streaming layer is not used */
258 /* Vorbis PRIMITIVES: general ***************************************/
260 static void (*qvorbis_info_init) (vorbis_info *vi);
261 static void (*qvorbis_info_clear) (vorbis_info *vi);
262 static void (*qvorbis_comment_init) (vorbis_comment *vc);
263 static void (*qvorbis_comment_clear) (vorbis_comment *vc);
265 static int (*qvorbis_block_init) (vorbis_dsp_state *v, vorbis_block *vb);
266 static int (*qvorbis_block_clear) (vorbis_block *vb);
267 static void (*qvorbis_dsp_clear) (vorbis_dsp_state *v);
269 /* Vorbis PRIMITIVES: analysis/DSP layer ****************************/
271 static int (*qvorbis_analysis_init) (vorbis_dsp_state *v,vorbis_info *vi);
272 static int (*qvorbis_commentheader_out) (vorbis_comment *vc, ogg_packet *op);
273 static int (*qvorbis_analysis_headerout) (vorbis_dsp_state *v,
277 ogg_packet *op_code);
278 static float ** (*qvorbis_analysis_buffer) (vorbis_dsp_state *v,int vals);
279 static int (*qvorbis_analysis_wrote) (vorbis_dsp_state *v,int vals);
280 static int (*qvorbis_analysis_blockout) (vorbis_dsp_state *v,vorbis_block *vb);
281 static int (*qvorbis_analysis) (vorbis_block *vb,ogg_packet *op);
283 static int (*qvorbis_bitrate_addblock) (vorbis_block *vb);
284 static int (*qvorbis_bitrate_flushpacket) (vorbis_dsp_state *vd,
287 // end of vorbis/codec.h stuff
290 static int (*qvorbis_encode_init_vbr) (vorbis_info *vi,
294 float base_quality /* quality level from 0. (lo) to 1. (hi) */
296 // end of vorbisenc.h stuff
300 int y_width; /**< Width of the Y' luminance plane */
301 int y_height; /**< Height of the luminance plane */
302 int y_stride; /**< Offset in bytes between successive rows */
304 int uv_width; /**< Width of the Cb and Cr chroma planes */
305 int uv_height; /**< Height of the chroma planes */
306 int uv_stride; /**< Offset between successive chroma rows */
307 unsigned char *y; /**< Pointer to start of luminance data */
308 unsigned char *u; /**< Pointer to start of Cb data */
309 unsigned char *v; /**< Pointer to start of Cr data */
317 OC_CS_UNSPECIFIED, /**< The colorspace is unknown or unspecified */
318 OC_CS_ITU_REC_470M, /**< This is the best option for 'NTSC' content */
319 OC_CS_ITU_REC_470BG, /**< This is the best option for 'PAL' content */
320 OC_CS_NSPACES /**< This marks the end of the defined colorspaces */
324 * A Chroma subsampling
326 * These enumerate the available chroma subsampling options supported
327 * by the theora format. See Section 4.4 of the specification for
331 OC_PF_420, /**< Chroma subsampling by 2 in each direction (4:2:0) */
332 OC_PF_RSVD, /**< Reserved value */
333 OC_PF_422, /**< Horizonatal chroma subsampling by 2 (4:2:2) */
334 OC_PF_444, /**< No chroma subsampling at all (4:4:4) */
335 } theora_pixelformat;
337 * Theora bitstream info.
338 * Contains the basic playback parameters for a stream,
339 * corresponding to the initial 'info' header packet.
341 * Encoded theora frames must be a multiple of 16 in width and height.
342 * To handle other frame sizes, a crop rectangle is specified in
343 * frame_height and frame_width, offset_x and * offset_y. The offset
344 * and size should still be a multiple of 2 to avoid chroma sampling
345 * shifts. Offset values in this structure are measured from the
346 * upper left of the image.
348 * Frame rate, in frames per second, is stored as a rational
349 * fraction. Aspect ratio is also stored as a rational fraction, and
350 * refers to the aspect ratio of the frame pixels, not of the
351 * overall frame itself.
353 * See <a href="http://svn.xiph.org/trunk/theora/examples/encoder_example.c">
354 * examples/encoder_example.c</a> for usage examples of the
355 * other paramters and good default settings for the encoder parameters.
358 ogg_uint32_t width; /**< encoded frame width */
359 ogg_uint32_t height; /**< encoded frame height */
360 ogg_uint32_t frame_width; /**< display frame width */
361 ogg_uint32_t frame_height; /**< display frame height */
362 ogg_uint32_t offset_x; /**< horizontal offset of the displayed frame */
363 ogg_uint32_t offset_y; /**< vertical offset of the displayed frame */
364 ogg_uint32_t fps_numerator; /**< frame rate numerator **/
365 ogg_uint32_t fps_denominator; /**< frame rate denominator **/
366 ogg_uint32_t aspect_numerator; /**< pixel aspect ratio numerator */
367 ogg_uint32_t aspect_denominator; /**< pixel aspect ratio denominator */
368 theora_colorspace colorspace; /**< colorspace */
369 int target_bitrate; /**< nominal bitrate in bits per second */
370 int quality; /**< Nominal quality setting, 0-63 */
371 int quick_p; /**< Quick encode/decode */
374 unsigned char version_major;
375 unsigned char version_minor;
376 unsigned char version_subminor;
383 ogg_uint32_t keyframe_frequency;
384 ogg_uint32_t keyframe_frequency_force; /* also used for decode init to
385 get granpos shift correct */
386 ogg_uint32_t keyframe_data_target_bitrate;
387 ogg_int32_t keyframe_auto_threshold;
388 ogg_uint32_t keyframe_mindistance;
389 ogg_int32_t noise_sensitivity;
390 ogg_int32_t sharpness;
392 theora_pixelformat pixelformat; /**< chroma subsampling mode to expect */
396 /** Codec internal state and context.
400 ogg_int64_t granulepos;
402 void *internal_encode;
403 void *internal_decode;
408 * Comment header metadata.
410 * This structure holds the in-stream metadata corresponding to
411 * the 'comment' header packet.
413 * Meta data is stored as a series of (tag, value) pairs, in
414 * length-encoded string vectors. The first occurence of the
415 * '=' character delimits the tag and value. A particular tag
416 * may occur more than once. The character set encoding for
417 * the strings is always UTF-8, but the tag names are limited
418 * to case-insensitive ASCII. See the spec for details.
420 * In filling in this structure, qtheora_decode_header() will
421 * null-terminate the user_comment strings for safety. However,
422 * the bitstream format itself treats them as 8-bit clean,
423 * and so the length array should be treated as authoritative
426 typedef struct theora_comment{
427 char **user_comments; /**< An array of comment string vectors */
428 int *comment_lengths; /**< An array of corresponding string vector lengths in bytes */
429 int comments; /**< The total number of comment string vectors */
430 char *vendor; /**< The vendor string identifying the encoder, null terminated */
433 static int (*qtheora_encode_init) (theora_state *th, theora_info *ti);
434 static int (*qtheora_encode_YUVin) (theora_state *t, yuv_buffer *yuv);
435 static int (*qtheora_encode_packetout) ( theora_state *t, int last_p,
437 static int (*qtheora_encode_header) (theora_state *t, ogg_packet *op);
438 static int (*qtheora_encode_comment) (theora_comment *tc, ogg_packet *op);
439 static int (*qtheora_encode_tables) (theora_state *t, ogg_packet *op);
440 static void (*qtheora_info_init) (theora_info *c);
441 static void (*qtheora_info_clear) (theora_info *c);
442 static void (*qtheora_clear) (theora_state *t);
443 static void (*qtheora_comment_init) (theora_comment *tc);
444 static void (*qtheora_comment_clear) (theora_comment *tc);
445 // end of theora.h stuff
447 static dllfunction_t oggfuncs[] =
449 {"ogg_stream_packetin", (void **) &qogg_stream_packetin},
450 {"ogg_stream_pageout", (void **) &qogg_stream_pageout},
451 {"ogg_stream_flush", (void **) &qogg_stream_flush},
452 {"ogg_stream_init", (void **) &qogg_stream_init},
453 {"ogg_stream_clear", (void **) &qogg_stream_clear},
457 static dllfunction_t vorbisencfuncs[] =
459 {"vorbis_encode_init_vbr", (void **) &qvorbis_encode_init_vbr},
463 static dllfunction_t vorbisfuncs[] =
465 {"vorbis_info_init", (void **) &qvorbis_info_init},
466 {"vorbis_info_clear", (void **) &qvorbis_info_clear},
467 {"vorbis_comment_init", (void **) &qvorbis_comment_init},
468 {"vorbis_comment_clear", (void **) &qvorbis_comment_clear},
469 {"vorbis_block_init", (void **) &qvorbis_block_init},
470 {"vorbis_block_clear", (void **) &qvorbis_block_clear},
471 {"vorbis_dsp_clear", (void **) &qvorbis_dsp_clear},
472 {"vorbis_analysis_init", (void **) &qvorbis_analysis_init},
473 {"vorbis_commentheader_out", (void **) &qvorbis_commentheader_out},
474 {"vorbis_analysis_headerout", (void **) &qvorbis_analysis_headerout},
475 {"vorbis_analysis_buffer", (void **) &qvorbis_analysis_buffer},
476 {"vorbis_analysis_wrote", (void **) &qvorbis_analysis_wrote},
477 {"vorbis_analysis_blockout", (void **) &qvorbis_analysis_blockout},
478 {"vorbis_analysis", (void **) &qvorbis_analysis},
479 {"vorbis_bitrate_addblock", (void **) &qvorbis_bitrate_addblock},
480 {"vorbis_bitrate_flushpacket", (void **) &qvorbis_bitrate_flushpacket},
484 static dllfunction_t theorafuncs[] =
486 {"theora_info_init", (void **) &qtheora_info_init},
487 {"theora_info_clear", (void **) &qtheora_info_clear},
488 {"theora_comment_init", (void **) &qtheora_comment_init},
489 {"theora_comment_clear", (void **) &qtheora_comment_clear},
490 {"theora_encode_init", (void **) &qtheora_encode_init},
491 {"theora_encode_YUVin", (void **) &qtheora_encode_YUVin},
492 {"theora_encode_packetout", (void **) &qtheora_encode_packetout},
493 {"theora_encode_header", (void **) &qtheora_encode_header},
494 {"theora_encode_comment", (void **) &qtheora_encode_comment},
495 {"theora_encode_tables", (void **) &qtheora_encode_tables},
496 {"theora_clear", (void **) &qtheora_clear},
500 static dllhandle_t og_dll = NULL, vo_dll = NULL, ve_dll = NULL, th_dll = NULL;
502 qboolean SCR_CaptureVideo_Ogg_OpenLibrary()
504 const char* dllnames_og [] =
511 #elif defined(MACOSX)
519 const char* dllnames_vo [] =
526 #elif defined(MACOSX)
534 const char* dllnames_ve [] =
537 "libvorbisenc64.dll",
541 #elif defined(MACOSX)
542 "libvorbisenc.dylib",
549 const char* dllnames_th [] =
556 #elif defined(MACOSX)
566 Sys_LoadLibrary (dllnames_og, &og_dll, oggfuncs)
568 Sys_LoadLibrary (dllnames_th, &th_dll, theorafuncs)
570 Sys_LoadLibrary (dllnames_vo, &vo_dll, vorbisfuncs)
572 Sys_LoadLibrary (dllnames_ve, &ve_dll, vorbisencfuncs);
575 void SCR_CaptureVideo_Ogg_Init()
577 SCR_CaptureVideo_Ogg_OpenLibrary();
579 Cvar_RegisterVariable(&cl_capturevideo_ogg_theora_quality);
580 Cvar_RegisterVariable(&cl_capturevideo_ogg_theora_bitrate);
581 Cvar_RegisterVariable(&cl_capturevideo_ogg_theora_keyframe_bitrate_multiplier);
582 Cvar_RegisterVariable(&cl_capturevideo_ogg_theora_keyframe_frequency);
583 Cvar_RegisterVariable(&cl_capturevideo_ogg_theora_keyframe_mindistance);
584 Cvar_RegisterVariable(&cl_capturevideo_ogg_theora_keyframe_auto_threshold);
585 Cvar_RegisterVariable(&cl_capturevideo_ogg_theora_noise_sensitivity);
586 Cvar_RegisterVariable(&cl_capturevideo_ogg_vorbis_quality);
589 qboolean SCR_CaptureVideo_Ogg_Available()
591 return og_dll && th_dll && vo_dll && ve_dll;
594 void SCR_CaptureVideo_Ogg_CloseDLL()
596 Sys_UnloadLibrary (&ve_dll);
597 Sys_UnloadLibrary (&vo_dll);
598 Sys_UnloadLibrary (&th_dll);
599 Sys_UnloadLibrary (&og_dll);
602 typedef struct capturevideostate_ogg_formatspecific_s
604 ogg_stream_state to, vo;
605 int serial1, serial2;
613 capturevideostate_ogg_formatspecific_t;
614 #define LOAD_FORMATSPECIFIC_OGG() capturevideostate_ogg_formatspecific_t *format = (capturevideostate_ogg_formatspecific_t *) cls.capturevideo.formatspecific
616 static void SCR_CaptureVideo_Ogg_EndVideo()
618 LOAD_FORMATSPECIFIC_OGG();
622 // repeat the last frame so we can set the end-of-stream flag
623 qtheora_encode_YUVin(&format->ts, &format->yuv);
624 qtheora_encode_packetout(&format->ts, true, &pt);
625 qogg_stream_packetin(&format->to, &pt);
627 if(cls.capturevideo.soundrate)
629 qvorbis_analysis_wrote(&format->vd, 0);
630 while(qvorbis_analysis_blockout(&format->vd, &format->vb) == 1)
632 qvorbis_analysis(&format->vb, NULL);
633 qvorbis_bitrate_addblock(&format->vb);
634 while(qvorbis_bitrate_flushpacket(&format->vd, &pt))
635 qogg_stream_packetin(&format->vo, &pt);
639 while(qogg_stream_pageout(&format->to, &pg) > 0)
641 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
642 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
645 if(cls.capturevideo.soundrate)
647 while(qogg_stream_pageout(&format->vo, &pg) > 0)
649 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
650 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
655 int result = qogg_stream_flush (&format->to, &pg);
657 fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
660 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
661 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
664 if(cls.capturevideo.soundrate)
667 int result = qogg_stream_flush (&format->vo, &pg);
669 fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
672 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
673 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
676 qogg_stream_clear(&format->vo);
677 qvorbis_block_clear(&format->vb);
678 qvorbis_dsp_clear(&format->vd);
681 qogg_stream_clear(&format->to);
682 qtheora_clear(&format->ts);
683 qvorbis_info_clear(&format->vi);
685 Mem_Free(format->yuv.y);
686 Mem_Free(format->yuv.u);
687 Mem_Free(format->yuv.v);
690 FS_Close(cls.capturevideo.videofile);
691 cls.capturevideo.videofile = NULL;
694 static void SCR_CaptureVideo_Ogg_ConvertFrame_BGRA_to_YUV()
696 LOAD_FORMATSPECIFIC_OGG();
698 int blockr, blockg, blockb;
699 unsigned char *b = cls.capturevideo.outbuffer;
700 int w = cls.capturevideo.width;
701 int h = cls.capturevideo.height;
704 for(y = 0; y < h; ++y)
706 for(b = cls.capturevideo.outbuffer + (h-1-y)*w*4, x = 0; x < w; ++x)
711 format->yuv.y[x + format->yuv.y_stride * y] =
712 cls.capturevideo.yuvnormalizetable[0][cls.capturevideo.rgbtoyuvscaletable[0][0][blockr] + cls.capturevideo.rgbtoyuvscaletable[0][1][blockg] + cls.capturevideo.rgbtoyuvscaletable[0][2][blockb]];
718 for(b = cls.capturevideo.outbuffer + (h-2-y)*w*4, x = 0; x < w/2; ++x)
720 blockr = (b[2] + b[6] + b[inpitch+2] + b[inpitch+6]) >> 2;
721 blockg = (b[1] + b[5] + b[inpitch+1] + b[inpitch+5]) >> 2;
722 blockb = (b[0] + b[4] + b[inpitch+0] + b[inpitch+4]) >> 2;
723 format->yuv.u[x + format->yuv.uv_stride * (y/2)] =
724 cls.capturevideo.yuvnormalizetable[1][cls.capturevideo.rgbtoyuvscaletable[1][0][blockr] + cls.capturevideo.rgbtoyuvscaletable[1][1][blockg] + cls.capturevideo.rgbtoyuvscaletable[1][2][blockb] + 128];
725 format->yuv.v[x + format->yuv.uv_stride * (y/2)] =
726 cls.capturevideo.yuvnormalizetable[2][cls.capturevideo.rgbtoyuvscaletable[2][0][blockr] + cls.capturevideo.rgbtoyuvscaletable[2][1][blockg] + cls.capturevideo.rgbtoyuvscaletable[2][2][blockb] + 128];
733 static void SCR_CaptureVideo_Ogg_VideoFrames(int num)
735 LOAD_FORMATSPECIFIC_OGG();
739 // data is in cls.capturevideo.outbuffer as BGRA and has size width*height
741 SCR_CaptureVideo_Ogg_ConvertFrame_BGRA_to_YUV();
745 qtheora_encode_YUVin(&format->ts, &format->yuv);
746 qtheora_encode_packetout(&format->ts, false, &pt);
747 qogg_stream_packetin(&format->to, &pt);
749 while(qogg_stream_pageout(&format->to, &pg) > 0)
751 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
752 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
757 static void SCR_CaptureVideo_Ogg_SoundFrame(const portable_sampleframe_t *paintbuffer, size_t length)
759 LOAD_FORMATSPECIFIC_OGG();
760 float **vorbis_buffer;
766 vorbis_buffer = qvorbis_analysis_buffer(&format->vd, length);
767 for(i = 0; i < length; ++i)
769 for(j = 0; j < cls.capturevideo.soundchannels; ++j)
770 vorbis_buffer[j][i] = paintbuffer[i].sample[j] / 32768.0f;
772 qvorbis_analysis_wrote(&format->vd, length);
774 while(qvorbis_analysis_blockout(&format->vd, &format->vb) == 1)
776 qvorbis_analysis(&format->vb, NULL);
777 qvorbis_bitrate_addblock(&format->vb);
779 while(qvorbis_bitrate_flushpacket(&format->vd, &pt))
780 qogg_stream_packetin(&format->vo, &pt);
783 while(qogg_stream_pageout(&format->vo, &pg) > 0)
785 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
786 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
790 void SCR_CaptureVideo_Ogg_BeginVideo()
792 cls.capturevideo.format = CAPTUREVIDEOFORMAT_OGG_VORBIS_THEORA;
793 cls.capturevideo.videofile = FS_OpenRealFile(va("%s.ogv", cls.capturevideo.basename), "wb", false);
794 cls.capturevideo.endvideo = SCR_CaptureVideo_Ogg_EndVideo;
795 cls.capturevideo.videoframes = SCR_CaptureVideo_Ogg_VideoFrames;
796 cls.capturevideo.soundframe = SCR_CaptureVideo_Ogg_SoundFrame;
797 cls.capturevideo.formatspecific = Mem_Alloc(tempmempool, sizeof(capturevideostate_ogg_formatspecific_t));
799 LOAD_FORMATSPECIFIC_OGG();
802 ogg_packet pt, pt2, pt3;
807 format->serial1 = rand();
808 qogg_stream_init(&format->to, format->serial1);
810 if(cls.capturevideo.soundrate)
814 format->serial2 = rand();
816 while(format->serial1 == format->serial2);
817 qogg_stream_init(&format->vo, format->serial2);
820 qtheora_info_init(&ti);
821 ti.frame_width = cls.capturevideo.width;
822 ti.frame_height = cls.capturevideo.height;
823 ti.width = (ti.frame_width + 15) & ~15;
824 ti.height = (ti.frame_height + 15) & ~15;
825 //ti.offset_x = ((ti.width - ti.frame_width) / 2) & ~1;
826 //ti.offset_y = ((ti.height - ti.frame_height) / 2) & ~1;
828 format->yuv.y_width = ti.width;
829 format->yuv.y_height = ti.height;
830 format->yuv.y_stride = ti.width;
832 format->yuv.uv_width = ti.width / 2;
833 format->yuv.uv_height = ti.height / 2;
834 format->yuv.uv_stride = ti.width / 2;
836 format->yuv.y = Mem_Alloc(tempmempool, format->yuv.y_stride * format->yuv.y_height);
837 format->yuv.u = Mem_Alloc(tempmempool, format->yuv.uv_stride * format->yuv.uv_height);
838 format->yuv.v = Mem_Alloc(tempmempool, format->yuv.uv_stride * format->yuv.uv_height);
840 FindFraction(cls.capturevideo.framerate, &num, &denom, 1001);
841 ti.fps_numerator = num;
842 ti.fps_denominator = denom;
844 FindFraction(1 / vid_pixelheight.value, &num, &denom, 1000);
845 ti.aspect_numerator = num;
846 ti.aspect_denominator = denom;
848 ti.colorspace = OC_CS_UNSPECIFIED;
849 ti.pixelformat = OC_PF_420;
851 ti.quick_p = true; // http://mlblog.osdir.com/multimedia.ogg.theora.general/2004-07/index.shtml
852 ti.dropframes_p = false;
854 ti.target_bitrate = cl_capturevideo_ogg_theora_bitrate.integer * 1000;
855 ti.quality = cl_capturevideo_ogg_theora_quality.integer;
857 if(ti.target_bitrate <= 0)
861 ti.target_bitrate = -1;
862 ti.keyframe_data_target_bitrate = -1;
867 ti.target_bitrate = -1;
868 ti.keyframe_data_target_bitrate = -1;
869 ti.quality = bound(0, ti.quality, 63);
876 ti.target_bitrate = bound(45000, ti.target_bitrate, 2000000);
877 ti.keyframe_data_target_bitrate = ti.target_bitrate * max(1, cl_capturevideo_ogg_theora_keyframe_bitrate_multiplier.value);
882 ti.target_bitrate = bound(45000, ti.target_bitrate, 2000000);
883 ti.keyframe_data_target_bitrate = ti.target_bitrate * max(1, cl_capturevideo_ogg_theora_keyframe_bitrate_multiplier.value);
888 ti.keyframe_frequency = bound(1, cl_capturevideo_ogg_theora_keyframe_frequency.integer, 1000);
889 ti.keyframe_mindistance = bound(1, cl_capturevideo_ogg_theora_keyframe_mindistance.integer, (int) ti.keyframe_frequency);
890 ti.noise_sensitivity = bound(0, cl_capturevideo_ogg_theora_noise_sensitivity.integer, 6);
891 ti.sharpness = bound(0, cl_capturevideo_ogg_theora_sharpness.integer, 2);
892 ti.keyframe_auto_threshold = bound(0, cl_capturevideo_ogg_theora_keyframe_auto_threshold.integer, 100);
894 ti.keyframe_frequency_force = ti.keyframe_frequency;
895 ti.keyframe_auto_p = (ti.keyframe_frequency != ti.keyframe_mindistance);
897 qtheora_encode_init(&format->ts, &ti);
898 qtheora_info_clear(&ti);
901 if(cls.capturevideo.soundrate)
903 qvorbis_info_init(&format->vi);
904 qvorbis_encode_init_vbr(&format->vi, cls.capturevideo.soundchannels, cls.capturevideo.soundrate, bound(-1, cl_capturevideo_ogg_vorbis_quality.value, 10) * 0.099);
905 qvorbis_comment_init(&vc);
906 qvorbis_analysis_init(&format->vd, &format->vi);
907 qvorbis_block_init(&format->vd, &format->vb);
910 qtheora_comment_init(&tc);
912 /* create the remaining theora headers */
913 qtheora_encode_header(&format->ts, &pt);
914 qogg_stream_packetin(&format->to, &pt);
915 if (qogg_stream_pageout (&format->to, &pg) != 1)
916 fprintf (stderr, "Internal Ogg library error.\n");
917 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
918 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
920 qtheora_encode_comment(&tc, &pt);
921 qogg_stream_packetin(&format->to, &pt);
922 qtheora_encode_tables(&format->ts, &pt);
923 qogg_stream_packetin (&format->to, &pt);
925 qtheora_comment_clear(&tc);
927 if(cls.capturevideo.soundrate)
929 qvorbis_analysis_headerout(&format->vd, &vc, &pt, &pt2, &pt3);
930 qogg_stream_packetin(&format->vo, &pt);
931 if (qogg_stream_pageout (&format->vo, &pg) != 1)
932 fprintf (stderr, "Internal Ogg library error.\n");
933 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
934 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
936 qogg_stream_packetin(&format->vo, &pt2);
937 qogg_stream_packetin(&format->vo, &pt3);
939 qvorbis_comment_clear(&vc);
944 int result = qogg_stream_flush (&format->to, &pg);
946 fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
949 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
950 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
953 if(cls.capturevideo.soundrate)
956 int result = qogg_stream_flush (&format->vo, &pg);
958 fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
961 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
962 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);