DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
cap_avi.h File Reference
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void SCR_CaptureVideo_Avi_BeginVideo (void)
 

Function Documentation

◆ SCR_CaptureVideo_Avi_BeginVideo()

void SCR_CaptureVideo_Avi_BeginVideo ( void )

Definition at line 496 of file cap_avi.c.

497{
498 int width = cls.capturevideo.width;
499 int height = cls.capturevideo.height;
500 int n, d;
501 unsigned int i;
502 double aspect;
503 char vabuf[1024];
504
506
507 cls.capturevideo.format = CAPTUREVIDEOFORMAT_AVI_I420;
508 cls.capturevideo.formatextension = "avi";
509 cls.capturevideo.videofile = FS_OpenRealFile(va(vabuf, sizeof(vabuf), "%s.%s", cls.capturevideo.basename, cls.capturevideo.formatextension), "wb", false);
510 if (!cls.capturevideo.videofile)
511 {
512 Con_Printf(CON_ERROR "Failed to open video file \"%s\", cancelling video capture.\n", vabuf);
513 cls.capturevideo.error = true;
514 return;
515 }
516 cls.capturevideo.writeEndVideo = SCR_CaptureVideo_Avi_EndVideo;
517 cls.capturevideo.writeVideoFrame = SCR_CaptureVideo_Avi_VideoFrames;
518 cls.capturevideo.writeSoundFrame = SCR_CaptureVideo_Avi_SoundFrame;
519 cls.capturevideo.formatspecific = Mem_Alloc(tempmempool, sizeof(capturevideostate_avi_formatspecific_t));
520 {
522 format->canseek = (FS_Seek(cls.capturevideo.videofile, 0, SEEK_SET) == 0);
524 // enclosing RIFF chunk (there can be multiple of these in >1GB files, the later ones are "AVIX" instead of "AVI " and have no header/stream info)
525 SCR_CaptureVideo_RIFF_Push("RIFF", "AVI ", format->canseek ? -1 : 12+(8+56+12+(12+52+8+40+8+68)+(cls.capturevideo.soundrate?(12+12+52+8+18):0)+12+(8+4))+12+(8+(((int) strlen(engineversion) | 1) + 1))+12);
526 // AVI main header
527 SCR_CaptureVideo_RIFF_Push("LIST", "hdrl", format->canseek ? -1 : 8+56+12+(12+52+8+40+8+68)+(cls.capturevideo.soundrate?(12+12+52+8+18):0)+12+(8+4));
528 SCR_CaptureVideo_RIFF_Push("avih", NULL, 56);
529 SCR_CaptureVideo_RIFF_Write32((int)(1000000.0 / (cls.capturevideo.framerate / cls.capturevideo.framestep))); // microseconds per frame
530 SCR_CaptureVideo_RIFF_Write32(0); // max bytes per second
531 SCR_CaptureVideo_RIFF_Write32(0); // padding granularity
532 SCR_CaptureVideo_RIFF_Write32(0x910); // flags (AVIF_HASINDEX | AVIF_ISINTERLEAVED | AVIF_TRUSTCKTYPE)
533 format->videofile_firstchunkframes_offset = SCR_CaptureVideo_RIFF_GetPosition();
534 SCR_CaptureVideo_RIFF_Write32(0); // total frames
535 SCR_CaptureVideo_RIFF_Write32(0); // initial frames
536 if (cls.capturevideo.soundrate)
537 SCR_CaptureVideo_RIFF_Write32(2); // number of streams
538 else
539 SCR_CaptureVideo_RIFF_Write32(1); // number of streams
540 SCR_CaptureVideo_RIFF_Write32(0); // suggested buffer size
543 SCR_CaptureVideo_RIFF_Write32(0); // reserved[0]
544 SCR_CaptureVideo_RIFF_Write32(0); // reserved[1]
545 SCR_CaptureVideo_RIFF_Write32(0); // reserved[2]
546 SCR_CaptureVideo_RIFF_Write32(0); // reserved[3]
548 // video stream info
549 SCR_CaptureVideo_RIFF_Push("LIST", "strl", format->canseek ? -1 : 12+52+8+40+8+68);
550 SCR_CaptureVideo_RIFF_Push("strh", "vids", 52);
551 SCR_CaptureVideo_RIFF_WriteFourCC("I420"); // stream fourcc (I420 colorspace, uncompressed)
553 SCR_CaptureVideo_RIFF_Write16(0); // priority
554 SCR_CaptureVideo_RIFF_Write16(0); // language
555 SCR_CaptureVideo_RIFF_Write32(0); // initial frames
556 // find an ideal divisor for the framerate
557 FindFraction(cls.capturevideo.framerate / cls.capturevideo.framestep, &n, &d, 1000);
558 SCR_CaptureVideo_RIFF_Write32(d); // samples/second divisor
559 SCR_CaptureVideo_RIFF_Write32(n); // samples/second multiplied by divisor
561 format->videofile_totalframes_offset1 = SCR_CaptureVideo_RIFF_GetPosition();
562 SCR_CaptureVideo_RIFF_Write32(0xFFFFFFFF); // length
563 SCR_CaptureVideo_RIFF_Write32(width*height+(width/2)*(height/2)*2); // suggested buffer size
564 SCR_CaptureVideo_RIFF_Write32(0); // quality
565 SCR_CaptureVideo_RIFF_Write32(0); // sample size
566 SCR_CaptureVideo_RIFF_Write16(0); // frame left
567 SCR_CaptureVideo_RIFF_Write16(0); // frame top
568 SCR_CaptureVideo_RIFF_Write16(width); // frame right
569 SCR_CaptureVideo_RIFF_Write16(height); // frame bottom
571 // video stream format
572 SCR_CaptureVideo_RIFF_Push("strf", NULL, 40);
573 SCR_CaptureVideo_RIFF_Write32(40); // BITMAPINFO struct size
577 SCR_CaptureVideo_RIFF_Write16(12); // bitcount
578 SCR_CaptureVideo_RIFF_WriteFourCC("I420"); // compression
579 SCR_CaptureVideo_RIFF_Write32(width*height+(width/2)*(height/2)*2); // size of image
580 SCR_CaptureVideo_RIFF_Write32(0); // x pixels per meter
581 SCR_CaptureVideo_RIFF_Write32(0); // y pixels per meter
582 SCR_CaptureVideo_RIFF_Write32(0); // color used
583 SCR_CaptureVideo_RIFF_Write32(0); // color important
585 // master index
586 if(format->canseek)
587 {
588 SCR_CaptureVideo_RIFF_Push("indx", NULL, -1);
589 SCR_CaptureVideo_RIFF_Write16(4); // wLongsPerEntry
590 SCR_CaptureVideo_RIFF_Write16(0); // bIndexSubType=0, bIndexType=0
591 format->videofile_ix_master_video_inuse_offset = SCR_CaptureVideo_RIFF_GetPosition();
592 SCR_CaptureVideo_RIFF_Write32(0); // nEntriesInUse
593 SCR_CaptureVideo_RIFF_WriteFourCC("00dc"); // dwChunkId
594 SCR_CaptureVideo_RIFF_Write32(0); // dwReserved1
595 SCR_CaptureVideo_RIFF_Write32(0); // dwReserved2
596 SCR_CaptureVideo_RIFF_Write32(0); // dwReserved3
597 format->videofile_ix_master_video_start_offset = SCR_CaptureVideo_RIFF_GetPosition();
598 for(i = 0; i < AVI_MASTER_INDEX_SIZE * 4; ++i)
599 SCR_CaptureVideo_RIFF_Write32(0); // fill up later
601 }
602 // extended format (aspect!)
603 SCR_CaptureVideo_RIFF_Push("vprp", NULL, 68);
604 SCR_CaptureVideo_RIFF_Write32(0); // VideoFormatToken
605 SCR_CaptureVideo_RIFF_Write32(0); // VideoStandard
606 SCR_CaptureVideo_RIFF_Write32((int)(cls.capturevideo.framerate / cls.capturevideo.framestep)); // dwVerticalRefreshRate (bogus)
607 SCR_CaptureVideo_RIFF_Write32(width); // dwHTotalInT
608 SCR_CaptureVideo_RIFF_Write32(height); // dwVTotalInLines
609 FindFraction(aspect, &n, &d, 1000);
610 SCR_CaptureVideo_RIFF_Write32((n << 16) | d); // dwFrameAspectRatio // TODO a word
611 SCR_CaptureVideo_RIFF_Write32(width); // dwFrameWidthInPixels
612 SCR_CaptureVideo_RIFF_Write32(height); // dwFrameHeightInLines
613 SCR_CaptureVideo_RIFF_Write32(1); // nFieldPerFrame
614 SCR_CaptureVideo_RIFF_Write32(width); // CompressedBMWidth
615 SCR_CaptureVideo_RIFF_Write32(height); // CompressedBMHeight
616 SCR_CaptureVideo_RIFF_Write32(width); // ValidBMHeight
617 SCR_CaptureVideo_RIFF_Write32(height); // ValidBMWidth
618 SCR_CaptureVideo_RIFF_Write32(0); // ValidBMXOffset
619 SCR_CaptureVideo_RIFF_Write32(0); // ValidBMYOffset
620 SCR_CaptureVideo_RIFF_Write32(0); // ValidBMXOffsetInT
621 SCR_CaptureVideo_RIFF_Write32(0); // ValidBMYValidStartLine
624 if (cls.capturevideo.soundrate)
625 {
626 // audio stream info
627 SCR_CaptureVideo_RIFF_Push("LIST", "strl", format->canseek ? -1 : 12+52+8+18);
628 SCR_CaptureVideo_RIFF_Push("strh", "auds", 52);
629 SCR_CaptureVideo_RIFF_Write32(1); // stream fourcc (PCM audio, uncompressed)
631 SCR_CaptureVideo_RIFF_Write16(0); // priority
632 SCR_CaptureVideo_RIFF_Write16(0); // language
633 SCR_CaptureVideo_RIFF_Write32(0); // initial frames
634 SCR_CaptureVideo_RIFF_Write32(1); // samples/second divisor
635 SCR_CaptureVideo_RIFF_Write32((int)(cls.capturevideo.soundrate)); // samples/second multiplied by divisor
637 format->videofile_totalsampleframes_offset = SCR_CaptureVideo_RIFF_GetPosition();
638 SCR_CaptureVideo_RIFF_Write32(0xFFFFFFFF); // length
639 SCR_CaptureVideo_RIFF_Write32(cls.capturevideo.soundrate * 2); // suggested buffer size (this is a half second)
640 SCR_CaptureVideo_RIFF_Write32(0); // quality
641 SCR_CaptureVideo_RIFF_Write32(4); // sample size
642 SCR_CaptureVideo_RIFF_Write16(0); // frame left
643 SCR_CaptureVideo_RIFF_Write16(0); // frame top
644 SCR_CaptureVideo_RIFF_Write16(0); // frame right
645 SCR_CaptureVideo_RIFF_Write16(0); // frame bottom
647 // audio stream format
648 SCR_CaptureVideo_RIFF_Push("strf", NULL, 18);
649 SCR_CaptureVideo_RIFF_Write16(1); // format (uncompressed PCM?)
650 SCR_CaptureVideo_RIFF_Write16(2); // channels (stereo)
651 SCR_CaptureVideo_RIFF_Write32(cls.capturevideo.soundrate); // sampleframes per second
652 SCR_CaptureVideo_RIFF_Write32(cls.capturevideo.soundrate * 4); // average bytes per second
653 SCR_CaptureVideo_RIFF_Write16(4); // block align
654 SCR_CaptureVideo_RIFF_Write16(16); // bits per sample
657 // master index
658 if(format->canseek)
659 {
660 SCR_CaptureVideo_RIFF_Push("indx", NULL, -1);
661 SCR_CaptureVideo_RIFF_Write16(4); // wLongsPerEntry
662 SCR_CaptureVideo_RIFF_Write16(0); // bIndexSubType=0, bIndexType=0
663 format->videofile_ix_master_audio_inuse_offset = SCR_CaptureVideo_RIFF_GetPosition();
664 SCR_CaptureVideo_RIFF_Write32(0); // nEntriesInUse
665 SCR_CaptureVideo_RIFF_WriteFourCC("01wb"); // dwChunkId
666 SCR_CaptureVideo_RIFF_Write32(0); // dwReserved1
667 SCR_CaptureVideo_RIFF_Write32(0); // dwReserved2
668 SCR_CaptureVideo_RIFF_Write32(0); // dwReserved3
669 format->videofile_ix_master_audio_start_offset = SCR_CaptureVideo_RIFF_GetPosition();
670 for(i = 0; i < AVI_MASTER_INDEX_SIZE * 4; ++i)
671 SCR_CaptureVideo_RIFF_Write32(0); // fill up later
673 }
675 }
676
677 format->videofile_ix_master_audio_inuse = format->videofile_ix_master_video_inuse = 0;
678
679 // extended header (for total #frames)
680 SCR_CaptureVideo_RIFF_Push("LIST", "odml", 8+4);
682 format->videofile_totalframes_offset2 = SCR_CaptureVideo_RIFF_GetPosition();
686
687 // close the AVI header list
689 // software that produced this AVI video file
690 SCR_CaptureVideo_RIFF_Push("LIST", "INFO", 8+((strlen(engineversion) | 1) + 1));
694 // enable this junk filler if you like the LIST movi to always begin at 4KB in the file (why?)
695#if 0
698 while (x > 0)
699 {
700 const char *junkfiller = "[ DarkPlaces junk data ]";
701 int i = min(x, (int)strlen(junkfiller));
702 SCR_CaptureVideo_RIFF_WriteBytes((const unsigned char *)junkfiller, i);
703 x -= i;
704 }
706#endif
708 // begin the actual video section now
709 SCR_CaptureVideo_RIFF_Push("LIST", "movi", format->canseek ? -1 : 0);
710 format->videofile_ix_movistart = format->riffstackstartoffset[1];
711 // we're done with the headers now...
713 if (format->riffstacklevel != 2)
714 Sys_Error("SCR_CaptureVideo_BeginVideo: broken AVI writing code (stack level is %i (should be 2) at end of headers)\n", format->riffstacklevel);
715
716 if(!format->canseek)
717 {
718 // close the movi immediately
720 // close the AVI immediately (we'll put all frames into AVIX)
722 }
723 }
724}
static void SCR_CaptureVideo_RIFF_WriteFourCC(const char *chunkfourcc)
Definition cap_avi.c:92
static void SCR_CaptureVideo_Avi_VideoFrames(int num, u8 *in)
Definition cap_avi.c:373
static void SCR_CaptureVideo_RIFF_Write32(int n)
Definition cap_avi.c:76
static void SCR_CaptureVideo_RIFF_WriteTerminatedString(const char *string)
Definition cap_avi.c:100
static void SCR_CaptureVideo_RIFF_Pop(void)
Definition cap_avi.c:132
static void SCR_CaptureVideo_RIFF_Start(void)
Definition cap_avi.c:33
#define LOAD_FORMATSPECIFIC_AVI()
Definition cap_avi.c:31
static fs_offset_t SCR_CaptureVideo_RIFF_GetPosition(void)
Definition cap_avi.c:108
static void SCR_CaptureVideo_Avi_EndVideo(void)
Definition cap_avi.c:405
static void SCR_CaptureVideo_RIFF_Flush(void)
Definition cap_avi.c:42
static void SCR_CaptureVideo_RIFF_WriteBytes(const unsigned char *data, size_t size)
Definition cap_avi.c:67
static void SCR_CaptureVideo_RIFF_Write16(int n)
Definition cap_avi.c:84
#define AVI_MASTER_INDEX_SIZE
Definition cap_avi.c:4
static void SCR_CaptureVideo_Avi_SoundFrame(const portable_sampleframe_t *paintbuffer, size_t length)
Definition cap_avi.c:450
static void SCR_CaptureVideo_RIFF_Push(const char *chunkfourcc, const char *listtypefourcc, fs_offset_t sizeHint)
Definition cap_avi.c:116
client_static_t cls
Definition cl_main.c:116
cvar_t vid_pixelheight
Definition cl_screen.c:58
char * va(char *buf, size_t buflen, const char *format,...)
Definition common.c:972
void FindFraction(double val, int *num, int *denom, int denomMax)
Definition common.c:1436
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
Definition console.c:1514
#define CON_ERROR
Definition console.h:102
char engineversion[128]
version string for the corner of the console, crash messages, status command, etc
Definition host.c:304
#define n(x, y)
int FS_Seek(qfile_t *file, fs_offset_t offset, int whence)
Definition fs.c:3359
qfile_t * FS_OpenRealFile(const char *filepath, const char *mode, qbool quiet)
Definition fs.c:2901
GLenum GLsizei width
Definition glquake.h:622
GLenum GLsizei GLsizei height
Definition glquake.h:622
GLint GLint GLint GLsizei GLsizei GLenum format
Definition glquake.h:649
GLint GLenum GLint x
Definition glquake.h:651
#define min(A, B)
Definition mathlib.h:37
float strlen(string s)
int i
#define NULL
Definition qtypes.h:12
float value
Definition cvar.h:74
int width
Definition vid.h:60
int height
Definition vid.h:61
viddef_mode_t mode
currently active video mode
Definition vid.h:73
void Sys_Error(const char *error,...) DP_FUNC_PRINTF(1) DP_FUNC_NORETURN
Causes the entire program to exit ASAP.
Definition sys_shared.c:724
viddef_t vid
global video state
Definition vid_shared.c:64
mempool_t * tempmempool
Definition zone.c:794
#define Mem_Alloc(pool, size)
Definition zone.h:92

References AVI_MASTER_INDEX_SIZE, cls, CON_ERROR, Con_Printf(), engineversion, FindFraction(), format, FS_OpenRealFile(), FS_Seek(), height, viddef_mode_t::height, i, LOAD_FORMATSPECIFIC_AVI, Mem_Alloc, min, viddef_t::mode, n, NULL, SCR_CaptureVideo_Avi_EndVideo(), SCR_CaptureVideo_Avi_SoundFrame(), SCR_CaptureVideo_Avi_VideoFrames(), SCR_CaptureVideo_RIFF_Flush(), SCR_CaptureVideo_RIFF_GetPosition(), SCR_CaptureVideo_RIFF_Pop(), SCR_CaptureVideo_RIFF_Push(), SCR_CaptureVideo_RIFF_Start(), SCR_CaptureVideo_RIFF_Write16(), SCR_CaptureVideo_RIFF_Write32(), SCR_CaptureVideo_RIFF_WriteBytes(), SCR_CaptureVideo_RIFF_WriteFourCC(), SCR_CaptureVideo_RIFF_WriteTerminatedString(), strlen(), Sys_Error(), tempmempool, va(), cvar_t::value, vid, vid_pixelheight, viddef_mode_t::width, width, and x.