8 typedef int16_t ogg_int16_t;
9 typedef u_int16_t ogg_uint16_t;
10 typedef int32_t ogg_int32_t;
11 typedef u_int32_t ogg_uint32_t;
12 typedef int64_t ogg_int64_t;
18 unsigned char *buffer;
23 /* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/
26 unsigned char *header;
32 /* ogg_stream_state contains the current encode/decode state of a logical
33 Ogg bitstream **********************************************************/
36 unsigned char *body_data; /* bytes from packet bodies */
37 long body_storage; /* storage elements allocated */
38 long body_fill; /* elements stored; fill mark */
39 long body_returned; /* elements of fill returned */
42 int *lacing_vals; /* The values that will go to the segment table */
43 ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact
44 this way, but it is simple coupled to the
51 unsigned char header[282]; /* working space for header encode */
54 int e_o_s; /* set when we have buffered the last packet in the
56 int b_o_s; /* set after we've written the initial page
57 of a logical bitstream */
60 ogg_int64_t packetno; /* sequence number for decode; the framing
61 knows where there's a hole in the data,
62 but we need coupling so that the codec
63 (which is in a seperate abstraction
64 layer) also knows about the gap */
65 ogg_int64_t granulepos;
69 /* ogg_packet is used to encapsulate the data and metadata belonging
70 to a single raw Ogg/Vorbis packet *************************************/
73 unsigned char *packet;
78 ogg_int64_t granulepos;
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 */
98 /* Ogg BITSTREAM PRIMITIVES: encoding **************************/
100 static int (*qogg_stream_packetin) (ogg_stream_state *os, ogg_packet *op);
101 static int (*qogg_stream_pageout) (ogg_stream_state *os, ogg_page *og);
102 static int (*qogg_stream_flush) (ogg_stream_state *os, ogg_page *og);
104 /* Ogg BITSTREAM PRIMITIVES: general ***************************/
106 static int (*qogg_stream_init) (ogg_stream_state *os,int serialno);
107 static int (*qogg_stream_clear) (ogg_stream_state *os);
109 // end of ogg.h stuff
111 // vorbis/codec.h stuff
112 typedef struct vorbis_info{
117 /* The below bitrate declarations are *hints*.
118 Combinations of the three values carry the following implications:
120 all three set to the same value:
121 implies a fixed rate bitstream
123 implies a VBR stream that averages the nominal bitrate. No hard
125 upper and or lower set:
126 implies a VBR bitstream that obeys the bitrate limits. nominal
127 may also be set to give a nominal rate.
129 the coder does not care to speculate.
133 long bitrate_nominal;
140 /* vorbis_dsp_state buffers the current vorbis audio
141 analysis/synthesis state. The DSP state belongs to a specific
142 logical bitstream ****************************************************/
143 typedef struct vorbis_dsp_state{
161 ogg_int64_t granulepos;
162 ogg_int64_t sequence;
164 ogg_int64_t glue_bits;
165 ogg_int64_t time_bits;
166 ogg_int64_t floor_bits;
167 ogg_int64_t res_bits;
172 typedef struct vorbis_block{
173 /* necessary stream state for linking to the framing abstraction */
174 float **pcm; /* this is a pointer into local storage */
184 ogg_int64_t granulepos;
185 ogg_int64_t sequence;
186 vorbis_dsp_state *vd; /* For read-only access of configuration */
188 /* local storage to avoid remallocing; it's up to the mapping to
194 struct alloc_chain *reap;
196 /* bitmetrics for the frame */
206 /* vorbis_block is a single block of data to be processed as part of
207 the analysis/synthesis stream; it belongs to a specific logical
208 bitstream, but is independant from other vorbis_blocks belonging to
209 that logical bitstream. *************************************************/
213 struct alloc_chain *next;
216 /* vorbis_info contains all the setup information specific to the
217 specific compression/decompression mode in progress (eg,
218 psychoacoustic settings, channel setup, options, codebook
219 etc). vorbis_info and substructures are in backends.h.
220 *********************************************************************/
222 /* the comments are not part of vorbis_info so that vorbis_info can be
224 typedef struct vorbis_comment{
225 /* unlimited user comment fields. libvorbis writes 'libvorbis'
226 whatever vendor is set to in encode */
227 char **user_comments;
228 int *comment_lengths;
235 /* libvorbis encodes in two abstraction layers; first we perform DSP
236 and produce a packet (see docs/analysis.txt). The packet is then
237 coded into a framed OggSquish bitstream by the second layer (see
238 docs/framing.txt). Decode is the reverse process; we sync/frame
239 the bitstream and extract individual packets, then decode the
240 packet back into PCM audio.
242 The extra framing/packetizing is used in streaming formats, such as
243 files. Over the net (such as with UDP), the framing and
244 packetization aren't necessary as they're provided by the transport
245 and the streaming layer is not used */
247 /* Vorbis PRIMITIVES: general ***************************************/
249 static void (*qvorbis_info_init) (vorbis_info *vi);
250 static void (*qvorbis_info_clear) (vorbis_info *vi);
251 static void (*qvorbis_comment_init) (vorbis_comment *vc);
252 static void (*qvorbis_comment_clear) (vorbis_comment *vc);
254 static int (*qvorbis_block_init) (vorbis_dsp_state *v, vorbis_block *vb);
255 static int (*qvorbis_block_clear) (vorbis_block *vb);
256 static void (*qvorbis_dsp_clear) (vorbis_dsp_state *v);
258 /* Vorbis PRIMITIVES: analysis/DSP layer ****************************/
260 static int (*qvorbis_analysis_init) (vorbis_dsp_state *v,vorbis_info *vi);
261 static int (*qvorbis_commentheader_out) (vorbis_comment *vc, ogg_packet *op);
262 static int (*qvorbis_analysis_headerout) (vorbis_dsp_state *v,
266 ogg_packet *op_code);
267 static float ** (*qvorbis_analysis_buffer) (vorbis_dsp_state *v,int vals);
268 static int (*qvorbis_analysis_wrote) (vorbis_dsp_state *v,int vals);
269 static int (*qvorbis_analysis_blockout) (vorbis_dsp_state *v,vorbis_block *vb);
270 static int (*qvorbis_analysis) (vorbis_block *vb,ogg_packet *op);
272 static int (*qvorbis_bitrate_addblock) (vorbis_block *vb);
273 static int (*qvorbis_bitrate_flushpacket) (vorbis_dsp_state *vd,
276 // end of vorbis/codec.h stuff
279 static int (*qvorbis_encode_init_vbr) (vorbis_info *vi,
283 float base_quality /* quality level from 0. (lo) to 1. (hi) */
285 // end of vorbisenc.h stuff
289 int y_width; /**< Width of the Y' luminance plane */
290 int y_height; /**< Height of the luminance plane */
291 int y_stride; /**< Offset in bytes between successive rows */
293 int uv_width; /**< Width of the Cb and Cr chroma planes */
294 int uv_height; /**< Height of the chroma planes */
295 int uv_stride; /**< Offset between successive chroma rows */
296 unsigned char *y; /**< Pointer to start of luminance data */
297 unsigned char *u; /**< Pointer to start of Cb data */
298 unsigned char *v; /**< Pointer to start of Cr data */
306 OC_CS_UNSPECIFIED, /**< The colorspace is unknown or unspecified */
307 OC_CS_ITU_REC_470M, /**< This is the best option for 'NTSC' content */
308 OC_CS_ITU_REC_470BG, /**< This is the best option for 'PAL' content */
309 OC_CS_NSPACES /**< This marks the end of the defined colorspaces */
313 * A Chroma subsampling
315 * These enumerate the available chroma subsampling options supported
316 * by the theora format. See Section 4.4 of the specification for
320 OC_PF_420, /**< Chroma subsampling by 2 in each direction (4:2:0) */
321 OC_PF_RSVD, /**< Reserved value */
322 OC_PF_422, /**< Horizonatal chroma subsampling by 2 (4:2:2) */
323 OC_PF_444, /**< No chroma subsampling at all (4:4:4) */
324 } theora_pixelformat;
326 * Theora bitstream info.
327 * Contains the basic playback parameters for a stream,
328 * corresponding to the initial 'info' header packet.
330 * Encoded theora frames must be a multiple of 16 in width and height.
331 * To handle other frame sizes, a crop rectangle is specified in
332 * frame_height and frame_width, offset_x and * offset_y. The offset
333 * and size should still be a multiple of 2 to avoid chroma sampling
334 * shifts. Offset values in this structure are measured from the
335 * upper left of the image.
337 * Frame rate, in frames per second, is stored as a rational
338 * fraction. Aspect ratio is also stored as a rational fraction, and
339 * refers to the aspect ratio of the frame pixels, not of the
340 * overall frame itself.
342 * See <a href="http://svn.xiph.org/trunk/theora/examples/encoder_example.c">
343 * examples/encoder_example.c</a> for usage examples of the
344 * other paramters and good default settings for the encoder parameters.
347 ogg_uint32_t width; /**< encoded frame width */
348 ogg_uint32_t height; /**< encoded frame height */
349 ogg_uint32_t frame_width; /**< display frame width */
350 ogg_uint32_t frame_height; /**< display frame height */
351 ogg_uint32_t offset_x; /**< horizontal offset of the displayed frame */
352 ogg_uint32_t offset_y; /**< vertical offset of the displayed frame */
353 ogg_uint32_t fps_numerator; /**< frame rate numerator **/
354 ogg_uint32_t fps_denominator; /**< frame rate denominator **/
355 ogg_uint32_t aspect_numerator; /**< pixel aspect ratio numerator */
356 ogg_uint32_t aspect_denominator; /**< pixel aspect ratio denominator */
357 theora_colorspace colorspace; /**< colorspace */
358 int target_bitrate; /**< nominal bitrate in bits per second */
359 int quality; /**< Nominal quality setting, 0-63 */
360 int quick_p; /**< Quick encode/decode */
363 unsigned char version_major;
364 unsigned char version_minor;
365 unsigned char version_subminor;
372 ogg_uint32_t keyframe_frequency;
373 ogg_uint32_t keyframe_frequency_force; /* also used for decode init to
374 get granpos shift correct */
375 ogg_uint32_t keyframe_data_target_bitrate;
376 ogg_int32_t keyframe_auto_threshold;
377 ogg_uint32_t keyframe_mindistance;
378 ogg_int32_t noise_sensitivity;
379 ogg_int32_t sharpness;
381 theora_pixelformat pixelformat; /**< chroma subsampling mode to expect */
385 /** Codec internal state and context.
389 ogg_int64_t granulepos;
391 void *internal_encode;
392 void *internal_decode;
397 * Comment header metadata.
399 * This structure holds the in-stream metadata corresponding to
400 * the 'comment' header packet.
402 * Meta data is stored as a series of (tag, value) pairs, in
403 * length-encoded string vectors. The first occurence of the
404 * '=' character delimits the tag and value. A particular tag
405 * may occur more than once. The character set encoding for
406 * the strings is always UTF-8, but the tag names are limited
407 * to case-insensitive ASCII. See the spec for details.
409 * In filling in this structure, qtheora_decode_header() will
410 * null-terminate the user_comment strings for safety. However,
411 * the bitstream format itself treats them as 8-bit clean,
412 * and so the length array should be treated as authoritative
415 typedef struct theora_comment{
416 char **user_comments; /**< An array of comment string vectors */
417 int *comment_lengths; /**< An array of corresponding string vector lengths in bytes */
418 int comments; /**< The total number of comment string vectors */
419 char *vendor; /**< The vendor string identifying the encoder, null terminated */
422 static int (*qtheora_encode_init) (theora_state *th, theora_info *ti);
423 static int (*qtheora_encode_YUVin) (theora_state *t, yuv_buffer *yuv);
424 static int (*qtheora_encode_packetout) ( theora_state *t, int last_p,
426 static int (*qtheora_encode_header) (theora_state *t, ogg_packet *op);
427 static int (*qtheora_encode_comment) (theora_comment *tc, ogg_packet *op);
428 static int (*qtheora_encode_tables) (theora_state *t, ogg_packet *op);
429 static void (*qtheora_info_init) (theora_info *c);
430 static void (*qtheora_info_clear) (theora_info *c);
431 static void (*qtheora_clear) (theora_state *t);
432 static void (*qtheora_comment_init) (theora_comment *tc);
433 static void (*qtheora_comment_clear) (theora_comment *tc);
434 // end of theora.h stuff
436 static dllfunction_t oggfuncs[] =
438 {"ogg_stream_packetin", (void **) &qogg_stream_packetin},
439 {"ogg_stream_pageout", (void **) &qogg_stream_pageout},
440 {"ogg_stream_flush", (void **) &qogg_stream_flush},
441 {"ogg_stream_init", (void **) &qogg_stream_init},
442 {"ogg_stream_clear", (void **) &qogg_stream_clear},
446 static dllfunction_t vorbisencfuncs[] =
448 {"vorbis_encode_init_vbr", (void **) &qvorbis_encode_init_vbr},
452 static dllfunction_t vorbisfuncs[] =
454 {"vorbis_info_init", (void **) &qvorbis_info_init},
455 {"vorbis_info_clear", (void **) &qvorbis_info_clear},
456 {"vorbis_comment_init", (void **) &qvorbis_comment_init},
457 {"vorbis_comment_clear", (void **) &qvorbis_comment_clear},
458 {"vorbis_block_init", (void **) &qvorbis_block_init},
459 {"vorbis_block_clear", (void **) &qvorbis_block_clear},
460 {"vorbis_dsp_clear", (void **) &qvorbis_dsp_clear},
461 {"vorbis_analysis_init", (void **) &qvorbis_analysis_init},
462 {"vorbis_commentheader_out", (void **) &qvorbis_commentheader_out},
463 {"vorbis_analysis_headerout", (void **) &qvorbis_analysis_headerout},
464 {"vorbis_analysis_buffer", (void **) &qvorbis_analysis_buffer},
465 {"vorbis_analysis_wrote", (void **) &qvorbis_analysis_wrote},
466 {"vorbis_analysis_blockout", (void **) &qvorbis_analysis_blockout},
467 {"vorbis_analysis", (void **) &qvorbis_analysis},
468 {"vorbis_bitrate_addblock", (void **) &qvorbis_bitrate_addblock},
469 {"vorbis_bitrate_flushpacket", (void **) &qvorbis_bitrate_flushpacket},
473 static dllfunction_t theorafuncs[] =
475 {"theora_info_init", (void **) &qtheora_info_init},
476 {"theora_info_clear", (void **) &qtheora_info_clear},
477 {"theora_comment_init", (void **) &qtheora_comment_init},
478 {"theora_comment_clear", (void **) &qtheora_comment_clear},
479 {"theora_encode_init", (void **) &qtheora_encode_init},
480 {"theora_encode_YUVin", (void **) &qtheora_encode_YUVin},
481 {"theora_encode_packetout", (void **) &qtheora_encode_packetout},
482 {"theora_encode_header", (void **) &qtheora_encode_header},
483 {"theora_encode_comment", (void **) &qtheora_encode_comment},
484 {"theora_encode_tables", (void **) &qtheora_encode_tables},
485 {"theora_clear", (void **) &qtheora_clear},
489 static dllhandle_t og_dll = NULL, vo_dll = NULL, ve_dll = NULL, th_dll = NULL;
491 qboolean SCR_CaptureVideo_Ogg_OpenLibrary()
493 const char* dllnames_og [] =
500 #elif defined(MACOSX)
508 const char* dllnames_vo [] =
515 #elif defined(MACOSX)
523 const char* dllnames_ve [] =
526 "libvorbisenc64.dll",
530 #elif defined(MACOSX)
531 "libvorbisenc.dylib",
538 const char* dllnames_th [] =
545 #elif defined(MACOSX)
555 Sys_LoadLibrary (dllnames_og, &og_dll, oggfuncs)
557 Sys_LoadLibrary (dllnames_th, &th_dll, theorafuncs)
559 Sys_LoadLibrary (dllnames_vo, &vo_dll, vorbisfuncs)
561 Sys_LoadLibrary (dllnames_ve, &ve_dll, vorbisencfuncs);
564 void SCR_CaptureVideo_Ogg_Init()
566 SCR_CaptureVideo_Ogg_OpenLibrary();
569 qboolean SCR_CaptureVideo_Ogg_Available()
571 return og_dll && th_dll && vo_dll && ve_dll;
574 void SCR_CaptureVideo_Ogg_CloseDLL()
576 Sys_UnloadLibrary (&ve_dll);
577 Sys_UnloadLibrary (&vo_dll);
578 Sys_UnloadLibrary (&th_dll);
579 Sys_UnloadLibrary (&og_dll);
582 typedef struct capturevideostate_ogg_formatspecific_s
584 ogg_stream_state to, vo;
585 int serial1, serial2;
594 capturevideostate_ogg_formatspecific_t;
595 #define LOAD_FORMATSPECIFIC() capturevideostate_ogg_formatspecific_t *format = (capturevideostate_ogg_formatspecific_t *) cls.capturevideo.formatspecific
597 void SCR_CaptureVideo_Ogg_Begin()
599 cls.capturevideo.videofile = FS_OpenRealFile(va("%s.ogv", cls.capturevideo.basename), "wb", false);
600 cls.capturevideo.formatspecific = Mem_Alloc(tempmempool, sizeof(capturevideostate_ogg_formatspecific_t));
602 LOAD_FORMATSPECIFIC();
605 ogg_packet pt, pt2, pt3;
609 format->serial1 = rand();
610 qogg_stream_init(&format->to, format->serial1);
612 if(cls.capturevideo.soundrate)
616 format->serial2 = rand();
618 while(format->serial1 == format->serial2);
619 qogg_stream_init(&format->vo, format->serial2);
622 qtheora_info_init(&format->ti);
623 format->ti.frame_width = cls.capturevideo.width;
624 format->ti.frame_height = cls.capturevideo.height;
625 format->ti.width = (format->ti.frame_width + 15) & ~15;
626 format->ti.height = (format->ti.frame_height + 15) & ~15;
627 format->ti.offset_x = ((format->ti.width - format->ti.frame_width) / 2) & ~1;
628 format->ti.offset_y = ((format->ti.height - format->ti.frame_height) / 2) & ~1;
630 format->yuv.y_width = format->ti.width;
631 format->yuv.y_height = format->ti.height;
632 format->yuv.y_stride = format->ti.width;
634 format->yuv.uv_width = format->ti.width / 2;
635 format->yuv.uv_height = format->ti.height / 2;
636 format->yuv.uv_stride = format->ti.width / 2;
638 format->yuv.y = Mem_Alloc(tempmempool, format->yuv.y_stride * format->yuv.y_height);
639 format->yuv.u = Mem_Alloc(tempmempool, format->yuv.uv_stride * format->yuv.uv_height);
640 format->yuv.v = Mem_Alloc(tempmempool, format->yuv.uv_stride * format->yuv.uv_height);
642 FindFraction(cls.capturevideo.framerate, &num, &denom, 1001);
643 format->ti.fps_numerator = num;
644 format->ti.fps_denominator = denom;
646 FindFraction(1 / vid_pixelheight.value, &num, &denom, 1000);
647 format->ti.aspect_numerator = num;
648 format->ti.aspect_denominator = denom;
650 format->ti.colorspace = OC_CS_UNSPECIFIED;
651 format->ti.pixelformat = OC_PF_420;
653 format->ti.target_bitrate = -1;
654 format->ti.quality = 63; // TODO find good values here later
655 format->ti.quick_p = false;
657 format->ti.dropframes_p = false;
658 format->ti.keyframe_auto_p = false;
659 format->ti.keyframe_frequency = 64;
660 format->ti.keyframe_frequency_force = 64; // TODO
661 format->ti.keyframe_data_target_bitrate = -1;
662 format->ti.keyframe_auto_threshold = 80;
663 format->ti.keyframe_mindistance = 8;
664 format->ti.noise_sensitivity = 1; // TODO
665 format->ti.sharpness = 0;
667 qtheora_encode_init(&format->ts, &format->ti);
670 if(cls.capturevideo.soundrate)
672 qvorbis_info_init(&format->vi);
673 qvorbis_encode_init_vbr(&format->vi, cls.capturevideo.soundchannels, cls.capturevideo.soundrate, 9);
674 qvorbis_comment_init(&vc);
675 qvorbis_analysis_init(&format->vd, &format->vi);
676 qvorbis_block_init(&format->vd, &format->vb);
679 qtheora_comment_init(&tc);
681 /* create the remaining theora headers */
682 qtheora_encode_header(&format->ts, &pt);
683 qogg_stream_packetin(&format->to, &pt);
684 if (qogg_stream_pageout (&format->to, &pg) != 1)
685 fprintf (stderr, "Internal Ogg library error.\n");
686 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
687 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
689 qtheora_encode_comment(&tc, &pt);
690 qogg_stream_packetin(&format->to, &pt);
691 qtheora_encode_tables(&format->ts, &pt);
692 qogg_stream_packetin (&format->to, &pt);
694 qtheora_comment_clear(&tc);
696 if(cls.capturevideo.soundrate)
698 qvorbis_analysis_headerout(&format->vd, &vc, &pt, &pt2, &pt3);
699 qogg_stream_packetin(&format->vo, &pt);
700 if (qogg_stream_pageout (&format->vo, &pg) != 1)
701 fprintf (stderr, "Internal Ogg library error.\n");
702 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
703 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
705 qogg_stream_packetin(&format->vo, &pt2);
706 qogg_stream_packetin(&format->vo, &pt3);
708 qvorbis_comment_clear(&vc);
713 int result = qogg_stream_flush (&format->to, &pg);
715 fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
718 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
719 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
722 if(cls.capturevideo.soundrate)
725 int result = qogg_stream_flush (&format->vo, &pg);
727 fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
730 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
731 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
736 void SCR_CaptureVideo_Ogg_EndVideo()
738 LOAD_FORMATSPECIFIC();
742 // repeat the last frame so we can set the end-of-stream flag
743 qtheora_encode_YUVin(&format->ts, &format->yuv);
744 qtheora_encode_packetout(&format->ts, true, &pt);
745 qogg_stream_packetin(&format->to, &pt);
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);
759 if(qogg_stream_pageout(&format->to, &pg) > 0)
761 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
762 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
765 if(cls.capturevideo.soundrate)
767 if(qogg_stream_pageout(&format->vo, &pg) > 0)
769 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
770 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
775 int result = qogg_stream_flush (&format->to, &pg);
777 fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
780 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
781 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
784 if(cls.capturevideo.soundrate)
787 int result = qogg_stream_flush (&format->vo, &pg);
789 fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
792 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
793 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
796 qogg_stream_clear(&format->vo);
797 qvorbis_block_clear(&format->vb);
798 qvorbis_dsp_clear(&format->vd);
799 qvorbis_info_clear(&format->vi);
802 qogg_stream_clear(&format->to);
803 qtheora_clear(&format->ts);
807 // cl_screen.c does this
808 // FS_Close(cls.capturevideo.videofile);
809 // cls.capturevideo.videofile = NULL;
812 void SCR_CaptureVideo_Ogg_ConvertFrame_BGRA_to_YUV()
814 LOAD_FORMATSPECIFIC();
816 int blockr, blockg, blockb;
817 unsigned char *b = cls.capturevideo.outbuffer;
818 int w = cls.capturevideo.width;
819 int h = cls.capturevideo.height;
822 for(y = 0; y < h; ++y)
824 for(b = cls.capturevideo.outbuffer + (h-1-y)*w*4, x = 0; x < w; ++x)
829 format->yuv.y[x + format->yuv.y_stride * y] =
830 cls.capturevideo.yuvnormalizetable[0][cls.capturevideo.rgbtoyuvscaletable[0][0][blockr] + cls.capturevideo.rgbtoyuvscaletable[0][1][blockg] + cls.capturevideo.rgbtoyuvscaletable[0][2][blockb]];
836 for(b = cls.capturevideo.outbuffer + (h-2-y)*w*4, x = 0; x < w/2; ++x)
838 blockr = (b[2] + b[6] + b[inpitch+2] + b[inpitch+6]) >> 2;
839 blockg = (b[1] + b[5] + b[inpitch+1] + b[inpitch+5]) >> 2;
840 blockb = (b[0] + b[4] + b[inpitch+0] + b[inpitch+4]) >> 2;
841 format->yuv.u[x + format->yuv.uv_stride * (y/2)] =
842 cls.capturevideo.yuvnormalizetable[1][cls.capturevideo.rgbtoyuvscaletable[1][0][blockr] + cls.capturevideo.rgbtoyuvscaletable[1][1][blockg] + cls.capturevideo.rgbtoyuvscaletable[1][2][blockb] + 128];
843 format->yuv.v[x + format->yuv.uv_stride * (y/2)] =
844 cls.capturevideo.yuvnormalizetable[2][cls.capturevideo.rgbtoyuvscaletable[2][0][blockr] + cls.capturevideo.rgbtoyuvscaletable[2][1][blockg] + cls.capturevideo.rgbtoyuvscaletable[2][2][blockb] + 128];
851 void SCR_CaptureVideo_Ogg_VideoFrame()
853 LOAD_FORMATSPECIFIC();
857 // data is in cls.capturevideo.outbuffer as BGRA and has size width*height
859 SCR_CaptureVideo_Ogg_ConvertFrame_BGRA_to_YUV();
860 qtheora_encode_YUVin(&format->ts, &format->yuv);
861 qtheora_encode_packetout(&format->ts, false, &pt);
862 qogg_stream_packetin(&format->to, &pt);
864 while(qogg_stream_pageout(&format->to, &pg) > 0)
866 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
867 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
871 void SCR_CaptureVideo_Ogg_SoundFrame(const portable_sampleframe_t *paintbuffer, size_t length)
873 LOAD_FORMATSPECIFIC();
874 float **vorbis_buffer;
880 vorbis_buffer = qvorbis_analysis_buffer(&format->vd, length);
881 for(i = 0; i < length; ++i)
883 for(j = 0; j < cls.capturevideo.soundchannels; ++j)
884 vorbis_buffer[j][i] = paintbuffer[i].sample[j] / 32768.0f;
886 qvorbis_analysis_wrote(&format->vd, length);
888 while(qvorbis_analysis_blockout(&format->vd, &format->vb) == 1)
890 qvorbis_analysis(&format->vb, NULL);
891 qvorbis_bitrate_addblock(&format->vb);
893 while(qvorbis_bitrate_flushpacket(&format->vd, &pt))
894 qogg_stream_packetin(&format->vo, &pt);
897 while(qogg_stream_pageout(&format->vo, &pg) > 0)
899 FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
900 FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);