]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cap_avi.c
Add GL_ExtensionSupported in vid_null.c because vid_shared.c relies on
[xonotic/darkplaces.git] / cap_avi.c
index df75c7d32eb7b9cc875b0cc8e234f1b35cf0f34a..fff2f7a5dcad3049029a57f81587fb53aa01f562 100644 (file)
--- a/cap_avi.c
+++ b/cap_avi.c
@@ -52,6 +52,18 @@ static void SCR_CaptureVideo_RIFF_Flush(void)
        }
 }
 
+static void SCR_CaptureVideo_RIFF_FlushNoIncrease(void)
+{
+       LOAD_FORMATSPECIFIC_AVI();
+       if (format->riffbuffer.cursize > 0)
+       {
+               if (!FS_Write(cls.capturevideo.videofile, format->riffbuffer.data, format->riffbuffer.cursize))
+                       cls.capturevideo.error = true;
+               format->riffbuffer.cursize = 0;
+               format->riffbuffer.overflowed = false;
+       }
+}
+
 static void SCR_CaptureVideo_RIFF_WriteBytes(const unsigned char *data, size_t size)
 {
        LOAD_FORMATSPECIFIC_AVI();
@@ -176,7 +188,7 @@ static void SCR_CaptureVideo_RIFF_IndexEntry(const char *chunkfourcc, int chunks
 {
        LOAD_FORMATSPECIFIC_AVI();
        if(!format->canseek)
-               Host_Error("SCR_CaptureVideo_RIFF_IndexEntry called on non-seekable AVI");
+               Sys_Error("SCR_CaptureVideo_RIFF_IndexEntry called on non-seekable AVI");
 
        if (format->riffstacklevel != 2)
                Sys_Error("SCR_Capturevideo_RIFF_IndexEntry: RIFF stack level is %i (should be 2)\n", format->riffstacklevel);
@@ -197,7 +209,7 @@ static void SCR_CaptureVideo_RIFF_MakeIxChunk(const char *fcc, const char *dwChu
        fs_offset_t pos, sz;
        
        if(!format->canseek)
-               Host_Error("SCR_CaptureVideo_RIFF_MakeIxChunk called on non-seekable AVI");
+               Sys_Error("SCR_CaptureVideo_RIFF_MakeIxChunk called on non-seekable AVI");
 
        if(*masteridx_count >= AVI_MASTER_INDEX_SIZE)
                return;
@@ -245,13 +257,13 @@ static void SCR_CaptureVideo_RIFF_MakeIxChunk(const char *fcc, const char *dwChu
                SCR_CaptureVideo_RIFF_Write32(((fs_offset_t) ix) >> 32);
                SCR_CaptureVideo_RIFF_Write32(pos - ix);
                SCR_CaptureVideo_RIFF_Write32(nMatching);
-               SCR_CaptureVideo_RIFF_Flush();
+               SCR_CaptureVideo_RIFF_FlushNoIncrease();
        }
 
        if(FS_Seek(cls.capturevideo.videofile, masteridx_counter, SEEK_SET) >= 0)
        {
                SCR_CaptureVideo_RIFF_Write32(++*masteridx_count);
-               SCR_CaptureVideo_RIFF_Flush();
+               SCR_CaptureVideo_RIFF_FlushNoIncrease();
        }
 
        FS_Seek(cls.capturevideo.videofile, 0, SEEK_END); // return value doesn't matter here
@@ -285,7 +297,7 @@ static void SCR_CaptureVideo_RIFF_Finish(qboolean final)
                if(FS_Seek(cls.capturevideo.videofile, format->videofile_firstchunkframes_offset, SEEK_SET) >= 0)
                {
                        SCR_CaptureVideo_RIFF_Write32(cls.capturevideo.frame);
-                       SCR_CaptureVideo_RIFF_Flush();
+                       SCR_CaptureVideo_RIFF_FlushNoIncrease();
                }
                FS_Seek(cls.capturevideo.videofile, 0, SEEK_END);
                format->videofile_firstchunkframes_offset = 0;
@@ -297,7 +309,8 @@ static void SCR_CaptureVideo_RIFF_Finish(qboolean final)
 static void SCR_CaptureVideo_RIFF_OverflowCheck(int framesize)
 {
        LOAD_FORMATSPECIFIC_AVI();
-       fs_offset_t cursize, curfilesize;
+       fs_offset_t cursize;
+       //fs_offset_t curfilesize;
        if (format->riffstacklevel != 2)
                Sys_Error("SCR_CaptureVideo_RIFF_OverflowCheck: chunk stack leakage!\n");
        
@@ -307,7 +320,7 @@ static void SCR_CaptureVideo_RIFF_OverflowCheck(int framesize)
        // check where we are in the file
        SCR_CaptureVideo_RIFF_Flush();
        cursize = SCR_CaptureVideo_RIFF_GetPosition() - format->riffstackstartoffset[0];
-       curfilesize = SCR_CaptureVideo_RIFF_GetPosition();
+       //curfilesize = SCR_CaptureVideo_RIFF_GetPosition();
 
        // if this would overflow the windows limit of 1GB per RIFF chunk, we need
        // to close the current RIFF chunk and open another for future frames
@@ -339,7 +352,7 @@ static void SCR_CaptureVideo_ConvertFrame_BGRA_to_I420_flip(int width, int heigh
                        blockb = b[0];
                        *out = cls.capturevideo.yuvnormalizetable[0][cls.capturevideo.rgbtoyuvscaletable[0][0][blockr] + cls.capturevideo.rgbtoyuvscaletable[0][1][blockg] + cls.capturevideo.rgbtoyuvscaletable[0][2][blockb]];
                }
-               if ((y & 1) == 0)
+               if ((y & 1) == 0 && y/2 < height/2) // if h is odd, this skips the last row
                {
                        // 2x2 Cr and Cb planes
                        int inpitch = width*4;
@@ -391,7 +404,7 @@ static void SCR_CaptureVideo_Avi_VideoFrames(int num)
        }
 }
 
-void SCR_CaptureVideo_Avi_EndVideo()
+static void SCR_CaptureVideo_Avi_EndVideo(void)
 {
        LOAD_FORMATSPECIFIC_AVI();
 
@@ -405,13 +418,13 @@ void SCR_CaptureVideo_Avi_EndVideo()
                        if(FS_Seek(cls.capturevideo.videofile, format->videofile_totalframes_offset1, SEEK_SET) >= 0)
                        {
                                SCR_CaptureVideo_RIFF_Write32(cls.capturevideo.frame);
-                               SCR_CaptureVideo_RIFF_Flush();
+                               SCR_CaptureVideo_RIFF_FlushNoIncrease();
                        }
                if(format->videofile_totalframes_offset2)
                        if(FS_Seek(cls.capturevideo.videofile, format->videofile_totalframes_offset2, SEEK_SET) >= 0)
                        {
                                SCR_CaptureVideo_RIFF_Write32(cls.capturevideo.frame);
-                               SCR_CaptureVideo_RIFF_Flush();
+                               SCR_CaptureVideo_RIFF_FlushNoIncrease();
                        }
                if (cls.capturevideo.soundrate)
                {
@@ -419,7 +432,7 @@ void SCR_CaptureVideo_Avi_EndVideo()
                                if(FS_Seek(cls.capturevideo.videofile, format->videofile_totalsampleframes_offset, SEEK_SET) >= 0)
                                {
                                        SCR_CaptureVideo_RIFF_Write32(cls.capturevideo.soundsampleframe);
-                                       SCR_CaptureVideo_RIFF_Flush();
+                                       SCR_CaptureVideo_RIFF_FlushNoIncrease();
                                }
                }
        }
@@ -436,7 +449,7 @@ void SCR_CaptureVideo_Avi_EndVideo()
        Mem_Free(format);
 }
 
-void SCR_CaptureVideo_Avi_SoundFrame(const portable_sampleframe_t *paintbuffer, size_t length)
+static void SCR_CaptureVideo_Avi_SoundFrame(const portable_sampleframe_t *paintbuffer, size_t length)
 {
        LOAD_FORMATSPECIFIC_AVI();
        int x;
@@ -449,18 +462,18 @@ void SCR_CaptureVideo_Avi_SoundFrame(const portable_sampleframe_t *paintbuffer,
        {
                int n0, n1;
 
-               n0 = paintbuffer[i].sample[0];
+               n0 = paintbuffer[i].sample[0] * 32768.0f;
                n0 = bound(-32768, n0, 32767);
                out_ptr[0] = (unsigned char)n0;
                out_ptr[1] = (unsigned char)(n0 >> 8);
 
-               n1 = paintbuffer[i].sample[1];
+               n1 = paintbuffer[i].sample[1] * 32768.0f;
                n1 = bound(-32768, n1, 32767);
                out_ptr[2] = (unsigned char)n1;
                out_ptr[3] = (unsigned char)(n1 >> 8);
        }
 
-       x = length*4;
+       x = (int)length*4;
        if(format->canseek)
        {
                SCR_CaptureVideo_RIFF_OverflowCheck(8 + x);
@@ -482,18 +495,20 @@ void SCR_CaptureVideo_Avi_SoundFrame(const portable_sampleframe_t *paintbuffer,
        }
 }
 
-void SCR_CaptureVideo_Avi_BeginVideo()
+void SCR_CaptureVideo_Avi_BeginVideo(void)
 {
        int width = cls.capturevideo.width;
        int height = cls.capturevideo.height;
        int n, d;
        unsigned int i;
        double aspect;
+       char vabuf[1024];
 
        aspect = vid.width / (vid.height * vid_pixelheight.value);
 
        cls.capturevideo.format = CAPTUREVIDEOFORMAT_AVI_I420;
-       cls.capturevideo.videofile = FS_OpenRealFile(va("%s.avi", cls.capturevideo.basename), "wb", false);
+       cls.capturevideo.formatextension = "avi";
+       cls.capturevideo.videofile = FS_OpenRealFile(va(vabuf, sizeof(vabuf), "%s.%s", cls.capturevideo.basename, cls.capturevideo.formatextension), "wb", false);
        cls.capturevideo.endvideo = SCR_CaptureVideo_Avi_EndVideo;
        cls.capturevideo.videoframes = SCR_CaptureVideo_Avi_VideoFrames;
        cls.capturevideo.soundframe = SCR_CaptureVideo_Avi_SoundFrame;
@@ -507,7 +522,7 @@ void SCR_CaptureVideo_Avi_BeginVideo()
                // AVI main header
                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));
                SCR_CaptureVideo_RIFF_Push("avih", NULL, 56);
-               SCR_CaptureVideo_RIFF_Write32((int)(1000000.0 / cls.capturevideo.framerate)); // microseconds per frame
+               SCR_CaptureVideo_RIFF_Write32((int)(1000000.0 / (cls.capturevideo.framerate / cls.capturevideo.framestep))); // microseconds per frame
                SCR_CaptureVideo_RIFF_Write32(0); // max bytes per second
                SCR_CaptureVideo_RIFF_Write32(0); // padding granularity
                SCR_CaptureVideo_RIFF_Write32(0x910); // flags (AVIF_HASINDEX | AVIF_ISINTERLEAVED | AVIF_TRUSTCKTYPE)
@@ -535,7 +550,7 @@ void SCR_CaptureVideo_Avi_BeginVideo()
                SCR_CaptureVideo_RIFF_Write16(0); // language
                SCR_CaptureVideo_RIFF_Write32(0); // initial frames
                // find an ideal divisor for the framerate
-               FindFraction(cls.capturevideo.framerate, &n, &d, 1000);
+               FindFraction(cls.capturevideo.framerate / cls.capturevideo.framestep, &n, &d, 1000);
                SCR_CaptureVideo_RIFF_Write32(d); // samples/second divisor
                SCR_CaptureVideo_RIFF_Write32(n); // samples/second multiplied by divisor
                SCR_CaptureVideo_RIFF_Write32(0); // start
@@ -584,7 +599,7 @@ void SCR_CaptureVideo_Avi_BeginVideo()
                SCR_CaptureVideo_RIFF_Push("vprp", NULL, 68);
                SCR_CaptureVideo_RIFF_Write32(0); // VideoFormatToken
                SCR_CaptureVideo_RIFF_Write32(0); // VideoStandard
-               SCR_CaptureVideo_RIFF_Write32((int)cls.capturevideo.framerate); // dwVerticalRefreshRate (bogus)
+               SCR_CaptureVideo_RIFF_Write32((int)(cls.capturevideo.framerate / cls.capturevideo.framestep)); // dwVerticalRefreshRate (bogus)
                SCR_CaptureVideo_RIFF_Write32(width); // dwHTotalInT
                SCR_CaptureVideo_RIFF_Write32(height); // dwVTotalInLines
                FindFraction(aspect, &n, &d, 1000);