added CTS padding, fixed graphics capture memory leak, fixed graphics capture crash

This commit is contained in:
jim 2012-11-25 00:44:06 -07:00
parent 30fab1a6b7
commit cb2a91d3be
8 changed files with 74 additions and 20 deletions

View File

@ -1,10 +1,31 @@
(yyyy-mm-dd)
-------------------------------
2012-11-25 - 0.448 (alpha)
* Fixed memory leak caused by the mouse cursor data not being
freed
* Fixed a potential crash that can happen to both the game and
the application in certain cases
* Padded CTS values by 75ms to compensate for any negative CTS
deviations
-------------------------------
2012-11-23 - 0.447 (alpha)
* Changed the game capture cursor to use a regular texture
rather than use a GDI texture, GDI texture went screwy
on some GPUs, so rendered it to a DIB section instead
and just copied the results
* More reverts and adjustments with the frame drop code to
prevent annoying frame drops, will add new frame drop code
later
* Fixed a bug in the new librtmp code that would cause it to
crash
-------------------------------
2012-11-22 - 0.446 (alpha)
* Finally just about completed game capture (wow was that a
crazy adventure)
* Added GIF supprot to bitmap image source
* Added GIF support to bitmap image source
* Added stream delay feature
* Adde option to allow users to use up to 120 FPS (if they're
crazy)

View File

@ -104,24 +104,31 @@ LRESULT WINAPI GraphicsCaptureSource::ReceiverWindowProc(HWND hwnd, UINT message
case RECEIVER_NEWCAPTURE:
{
GraphicsCaptureSource *source = (GraphicsCaptureSource*)GetWindowLongPtr(hwnd, 0);
if(source)
source->NewCapture((LPVOID)lParam);
CaptureWindowData *data = (CaptureWindowData*)GetWindowLongPtr(hwnd, 0);
if(data->source)
data->source->NewCapture((LPVOID)lParam);
}
return API->GetMaxFPS();
case RECEIVER_ENDCAPTURE:
{
GraphicsCaptureSource *source = (GraphicsCaptureSource*)GetWindowLongPtr(hwnd, 0);
if(source)
CaptureWindowData *data = (CaptureWindowData*)GetWindowLongPtr(hwnd, 0);
if(data->source)
{
API->EnterSceneMutex();
source->EndCapture();
data->source->EndCapture();
API->LeaveSceneMutex();
}
}
break;
case WM_DESTROY:
{
CaptureWindowData *data = (CaptureWindowData*)GetWindowLongPtr(hwnd, 0);
delete data;
}
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
@ -236,7 +243,8 @@ void GraphicsCaptureSource::BeginScene()
if(bCaptureMouse && data->GetInt(TEXT("invertMouse")))
invertShader = CreatePixelShaderFromFile(TEXT("shaders\\InvertTexture.pShader"));
hwndReceiver = CreateWindow(RECEIVER_WINDOWCLASS, NULL, 0, 0, 0, 0, 0, 0, 0, hinstMain, this);
windowData = new CaptureWindowData(this);
hwndReceiver = CreateWindow(RECEIVER_WINDOWCLASS, NULL, 0, 0, 0, 0, 0, 0, 0, hinstMain, windowData);
AttemptCapture();
}
@ -326,6 +334,9 @@ void GraphicsCaptureSource::EndScene()
hwndSender = NULL;
}
if(windowData)
windowData->source = NULL;
if(hwndReceiver)
{
DestroyWindow(hwndReceiver);
@ -461,6 +472,7 @@ void GraphicsCaptureSource::Render(const Vect2 &pos, const Vect2 &size)
else
{
HICON hIcon = CopyIcon(ci.hCursor);
hCurrentCursor = ci.hCursor;
delete cursorTexture;
cursorTexture = NULL;
@ -480,6 +492,8 @@ void GraphicsCaptureSource::Render(const Vect2 &pos, const Vect2 &size)
cursorTexture = CreateTexture(size, size, GS_BGRA, lpData, FALSE);
if(cursorTexture)
bMouseCaptured = true;
Free(lpData);
}
DeleteObject(ii.hbmColor);

View File

@ -19,8 +19,19 @@
#pragma once
class GraphicsCaptureSource;
struct CaptureWindowData
{
inline CaptureWindowData(GraphicsCaptureSource *source) : source(source) {}
GraphicsCaptureSource *source;
};
class GraphicsCaptureSource : public ImageSource
{
CaptureWindowData *windowData;
GraphicsCaptureMethod *capture;
UINT cx, cy;

8
OBS.rc
View File

@ -617,8 +617,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,4,4,7
PRODUCTVERSION 0,4,4,7
FILEVERSION 0,4,4,8
PRODUCTVERSION 0,4,4,8
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -634,12 +634,12 @@ BEGIN
BLOCK "041104b0"
BEGIN
VALUE "FileDescription", "Open Broadcaster Software"
VALUE "FileVersion", "0, 4, 4, 7"
VALUE "FileVersion", "0, 4, 4, 8"
VALUE "InternalName", "OBS"
VALUE "LegalCopyright", "Copyright (C) 2012"
VALUE "OriginalFilename", "OBS.exe"
VALUE "ProductName", "Open Broadcaster Software"
VALUE "ProductVersion", "0, 4, 4, 7"
VALUE "ProductVersion", "0, 4, 4, 8"
END
END
BLOCK "VarFileInfo"

View File

@ -208,6 +208,10 @@ public:
int timeOffset = int(INT64(picOut.i_pts+delayTime)-INT64(outputTimestamp));
//Log(TEXT("dts: %d, pts: %d, timestamp: %d, offset: %d"), picOut.i_dts, picOut.i_pts, outputTimestamp, timeOffset);
timeOffset += 75; //100 is negative CTS padding for VFR
if(timeOffset < 0) //this is very unlikely with the padding
timeOffset = 0;
timeOffset = htonl(timeOffset);
BYTE *timeOffsetAddr = ((BYTE*)&timeOffset)+1;
@ -233,7 +237,7 @@ public:
*(DWORD*)(SEIPacket+5) = htonl(newPayloadSize);
mcpy(SEIPacket+9, nal.p_payload+skipBytes, newPayloadSize);
}
else if(nal.i_type == NAL_SLICE_IDR || nal.i_type == NAL_SLICE)
else if(nal.i_type == NAL_SLICE_IDR || nal.i_type == NAL_SLICE /*|| nal.i_type == NAL_SEI*/)
{
VideoPacket *newPacket = CurrentPackets.CreateNew();
@ -244,7 +248,7 @@ public:
int newPayloadSize = (nal.i_payload-skipBytes);
newPacket->Packet.SetSize(9+newPayloadSize);
newPacket->Packet[0] = ((nal.i_type == NAL_SLICE_IDR) ? 0x17 : 0x27);
newPacket->Packet[0] = ((nal.i_type == NAL_SLICE_IDR || nal.i_type == NAL_SEI) ? 0x17 : 0x27);
newPacket->Packet[1] = 1;
mcpy(newPacket->Packet+2, timeOffsetAddr, 3);
*(DWORD*)(newPacket->Packet+5) = htonl(newPayloadSize);
@ -302,6 +306,9 @@ public:
x264_encoder_headers(x264, &nalOut, &nalNum);
int timeOffset = 0;//htonl(200);
BYTE *timeOffsetAddr = ((BYTE*)&timeOffset)+1;
for(int i=0; i<nalNum; i++)
{
x264_nal_t &nal = nalOut[i];
@ -312,6 +319,7 @@ public:
headerOut.OutputByte(0x17);
headerOut.OutputByte(0);
//headerOut.Serialize(timeOffsetAddr, 3);
headerOut.OutputByte(0);
headerOut.OutputByte(0);
headerOut.OutputByte(0);

View File

@ -481,7 +481,7 @@ public:
output.Serialize(IFrameIDs.Array(), IFrameIDs.Num()*sizeof(UINT));
PopBox(); //stss
PushBox(output, DWORD_BE('ctts')); //list of composition time offsets
output.OutputDword(DWORD_BE(0x01000000)); //version (1) and flags (none)
output.OutputDword(0); //version (0) and flags (none)
output.OutputDword(fastHtonl(compositionOffsets.Num()));
for(UINT i=0; i<compositionOffsets.Num(); i++)
{

View File

@ -61,8 +61,8 @@ extern ConfigFile *AppConfig;
extern OBS *App;
extern TCHAR lpAppDataPath[MAX_PATH];
#define OBS_VERSION 0x000447
#define OBS_VERSION_STRING_ANSI "Open Broadcaster Software v0.447a"
#define OBS_VERSION 0x000448
#define OBS_VERSION_STRING_ANSI "Open Broadcaster Software v0.448a"
#define OBS_VERSION_STRING TEXT(OBS_VERSION_STRING_ANSI)
#define OBS_WINDOW_CLASS TEXT("OBSWindowClass")

View File

@ -2255,15 +2255,15 @@ void OBS::MainCaptureLoop()
if(pendingAudioFrames.Num())
{
//Log(TEXT("pending frames %u, (in milliseconds): %u"), pendingAudioFrames.Num(), pendingAudioFrames.Last().timestamp-pendingAudioFrames[0].timestamp);
while(pendingAudioFrames.Num() && pendingAudioFrames[0].timestamp < curTimeStamp)
while(pendingAudioFrames.Num() && pendingAudioFrames[0].timestamp+75 < curTimeStamp)
{
List<BYTE> &audioData = pendingAudioFrames[0].audioData;
if(audioData.Num())
{
network->SendPacket(audioData.Array(), audioData.Num(), pendingAudioFrames[0].timestamp, PacketType_Audio);
network->SendPacket(audioData.Array(), audioData.Num(), pendingAudioFrames[0].timestamp+75, PacketType_Audio);
if(fileStream)
fileStream->AddPacket(audioData.Array(), audioData.Num(), pendingAudioFrames[0].timestamp, PacketType_Audio);
fileStream->AddPacket(audioData.Array(), audioData.Num(), pendingAudioFrames[0].timestamp+75, PacketType_Audio);
audioData.Clear();
}