fix for stream death

This commit is contained in:
jp9000 2012-12-15 03:40:51 -07:00
parent 69c1c52e9f
commit c376aeab2b
10 changed files with 114 additions and 51 deletions

20
OBS.rc
View File

@ -313,7 +313,7 @@ BEGIN
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,17,173,10 "Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,17,173,10
RTEXT "Settings.Advanced.ProcessPriority",IDC_STATIC,7,31,136,8 RTEXT "Settings.Advanced.ProcessPriority",IDC_STATIC,7,31,136,8
COMBOBOX IDC_PRIORITY,145,29,82,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_PRIORITY,145,29,82,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
GROUPBOX "Settings.Video",IDC_STATIC,4,48,418,109 GROUPBOX "Settings.Video",IDC_STATIC,4,48,418,123
RTEXT "Settings.Advanced.VideoEncoderCPUTradeoff",IDC_STATIC,5,60,138,8 RTEXT "Settings.Advanced.VideoEncoderCPUTradeoff",IDC_STATIC,5,60,138,8
COMBOBOX IDC_PRESET,145,58,82,62,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_PRESET,145,58,82,62,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
CONTROL "Settings.Advanced.UseCBR",IDC_USECBR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,79,292,10 CONTROL "Settings.Advanced.UseCBR",IDC_USECBR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,79,292,10
@ -323,17 +323,19 @@ BEGIN
CONTROL "Settings.Advanced.UseSyncFix",IDC_USESYNCFIX,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,20,125,243,10 CONTROL "Settings.Advanced.UseSyncFix",IDC_USESYNCFIX,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,20,125,243,10
CONTROL "Settings.Advanced.UnlockHigherFPS",IDC_UNLOCKHIGHFPS, CONTROL "Settings.Advanced.UnlockHigherFPS",IDC_UNLOCKHIGHFPS,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,139,217,10 "Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,139,217,10
GROUPBOX "Settings.Audio",IDC_STATIC,4,160,418,29 GROUPBOX "Settings.Audio",IDC_STATIC,4,174,418,29
CONTROL "Settings.Advanced.UseHighQualityResampling",IDC_USEHIGHQUALITYRESAMPLING, CONTROL "Settings.Advanced.UseHighQualityResampling",IDC_USEHIGHQUALITYRESAMPLING,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,173,332,10 "Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,187,332,10
GROUPBOX "Settings.Advanced.Network",IDC_STATIC,4,197,418,67 GROUPBOX "Settings.Advanced.Network",IDC_STATIC,4,211,418,67
CONTROL "Settings.Advanced.UseSendBuffer",IDC_USESENDBUFFER, CONTROL "Settings.Advanced.UseSendBuffer",IDC_USESENDBUFFER,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,212,277,10 "Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,226,277,10
RTEXT "Settings.Advanced.SendBufferSize",IDC_STATIC,5,227,138,8 RTEXT "Settings.Advanced.SendBufferSize",IDC_STATIC,5,241,138,8
COMBOBOX IDC_SENDBUFFERSIZE,145,225,158,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_SENDBUFFERSIZE,145,239,158,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
LTEXT "Settings.Info",IDC_INFO,7,281,418,37,NOT WS_VISIBLE LTEXT "Settings.Info",IDC_INFO,7,281,418,37,NOT WS_VISIBLE
RTEXT "Settings.Advanced.BindToIP",IDC_STATIC,5,244,138,8 RTEXT "Settings.Advanced.BindToIP",IDC_STATIC,5,258,138,8
COMBOBOX IDC_BINDIP,145,242,87,62,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_BINDIP,145,256,87,62,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
CONTROL ".Allow negative CTS (for testing purposes)",IDC_DISABLECTSADJUST,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,154,286,10
END END
IDD_CONFIGURETRANSITIONSOURCE DIALOGEX 0, 0, 338, 198 IDD_CONFIGURETRANSITIONSOURCE DIALOGEX 0, 0, 338, 198

View File

@ -75,6 +75,7 @@ bool D3D10OutputDuplicator::Init(UINT output)
D3D10OutputDuplicator::~D3D10OutputDuplicator() D3D10OutputDuplicator::~D3D10OutputDuplicator()
{ {
SafeRelease(duplicator); SafeRelease(duplicator);
delete copyTex;
} }
DuplicatorInfo D3D10OutputDuplicator::AquireNextFrame(UINT timeout, POINT &mousePos, BOOL &mouseVisible) DuplicatorInfo D3D10OutputDuplicator::AquireNextFrame(UINT timeout, POINT &mousePos, BOOL &mouseVisible)

View File

@ -78,8 +78,7 @@ public:
if(warningID) if(warningID)
App->RemoveStreamInfo(warningID); App->RemoveStreamInfo(warningID);
if(duplicator) delete duplicator;
delete duplicator;
delete alphaIgnoreShader; delete alphaIgnoreShader;
delete colorKeyShader; delete colorKeyShader;
@ -87,6 +86,9 @@ public:
void PreprocessWindows8MonitorCapture() void PreprocessWindows8MonitorCapture()
{ {
if(!duplicator)
duplicator = GS->CreateOutputDulicator(0);
if(duplicator) if(duplicator)
{ {
Texture *newTex = NULL; Texture *newTex = NULL;
@ -103,6 +105,10 @@ public:
} }
case DuplicatorInfo_Error: case DuplicatorInfo_Error:
delete duplicator;
duplicator = NULL;
return;
case DuplicatorInfo_Timeout: case DuplicatorInfo_Timeout:
return; return;
} }
@ -362,7 +368,7 @@ public:
captureRect.right = x+cx; captureRect.right = x+cx;
captureRect.bottom = y+cy; captureRect.bottom = y+cy;
//bWindows8MonitorCapture = captureType == 0 && IsWindows8Up(); bWindows8MonitorCapture = captureType == 0 && IsWindows8Up();
width = cx; width = cx;
height = cy; height = cy;

View File

@ -67,12 +67,12 @@ class X264Encoder : public VideoEncoder
bool bFirstFrameProcessed; bool bFirstFrameProcessed;
bool bUseCBR; bool bUseCBR, bUseCTSAdjust;
List<VideoPacket> CurrentPackets; List<VideoPacket> CurrentPackets;
List<BYTE> HeaderPacket; List<BYTE> HeaderPacket;
int delayOffset; INT64 delayOffset;
inline void ClearPackets() inline void ClearPackets()
{ {
@ -125,7 +125,7 @@ public:
} }
paramData.b_vfr_input = 1; paramData.b_vfr_input = 1;
//paramData.i_keyint_max = fps*5; //keyframe every 5 sec, should make this an option paramData.i_keyint_max = fps*4; //keyframe every 4 sec, should make this an option
paramData.i_width = width; paramData.i_width = width;
paramData.i_height = height; paramData.i_height = height;
paramData.vui.b_fullrange = 0; //specify full range input levels paramData.vui.b_fullrange = 0; //specify full range input levels
@ -141,6 +141,7 @@ public:
//paramData.pf_log = get_x264_log; //paramData.pf_log = get_x264_log;
//paramData.i_log_level = X264_LOG_INFO; //paramData.i_log_level = X264_LOG_INFO;
bUseCTSAdjust = !AppConfig->GetInt(TEXT("Video Encoding"), TEXT("DisableCTSAdjust"));
BOOL bUseCustomParams = AppConfig->GetInt(TEXT("Video Encoding"), TEXT("UseCustomSettings")); BOOL bUseCustomParams = AppConfig->GetInt(TEXT("Video Encoding"), TEXT("UseCustomSettings"));
if(bUseCustomParams) if(bUseCustomParams)
{ {
@ -217,23 +218,24 @@ public:
if(!bFirstFrameProcessed && nalNum) if(!bFirstFrameProcessed && nalNum)
{ {
if(picOut.i_dts < 0) delayOffset = -picOut.i_dts;
delayOffset = int(-picOut.i_dts);
//Log(TEXT("cts: %u, timestamp: %u"), ctsOffset, outputTimestamp);
bFirstFrameProcessed = true; bFirstFrameProcessed = true;
} }
INT64 ts = INT64(outputTimestamp); INT64 ts = INT64(outputTimestamp);
int timeOffset = int(picOut.i_pts+INT64(delayOffset)-ts); int timeOffset = int((picOut.i_pts+delayOffset)-ts);
timeOffset += ctsOffset; if(bUseCTSAdjust)
//dynamically adjust the CTS for the stream if it gets lower than the current value
//(thanks to cyrus for suggesting to do this instead of a single shift)
if(nalNum && timeOffset < 0)
{ {
ctsOffset -= timeOffset; timeOffset += ctsOffset;
timeOffset = 0;
//dynamically adjust the CTS for the stream if it gets lower than the current value
//(thanks to cyrus for suggesting to do this instead of a single shift)
if(nalNum && timeOffset < 0)
{
ctsOffset -= timeOffset;
timeOffset = 0;
}
} }
//Log(TEXT("dts: %d, pts: %d, timestamp: %d, offset: %d"), picOut.i_dts, picOut.i_pts, outputTimestamp, timeOffset); //Log(TEXT("dts: %d, pts: %d, timestamp: %d, offset: %d"), picOut.i_dts, picOut.i_pts, outputTimestamp, timeOffset);

View File

@ -56,7 +56,7 @@ class MMDeviceAudioSource : public AudioSource
List<AudioSegment> audioSegments; List<AudioSegment> audioSegments;
bool bFirstFrameReceived; bool bFirstFrameReceived;
QWORD lastUsedTimestamp; QWORD lastUsedTimestamp, lastSentTimestamp;
bool bBrokenTimestamp; bool bBrokenTimestamp;
//----------------------------------------- //-----------------------------------------
@ -417,9 +417,9 @@ UINT MMDeviceAudioSource::GetNextBuffer()
if(newTimestamp < (curTime-1000) || newTimestamp > (curTime+1000)) if(newTimestamp < (curTime-1000) || newTimestamp > (curTime+1000))
{ {
bBrokenTimestamp = true; bBrokenTimestamp = true;
lastUsedTimestamp = newTimestamp = GetQPCTimeMS(clockFreq.QuadPart);
Log(TEXT("MMDeviceAudioSource::GetNextBuffer: Got bad audio timestamp offset %d from device: '%s', timestamps for this device will be calculated"), (int)(newTimestamp - curTime), GetDeviceName().Array()); Log(TEXT("MMDeviceAudioSource::GetNextBuffer: Got bad audio timestamp offset %lld from device: '%s', timestamps for this device will be calculated. curTime: %llu, newTimestamp: %llu"), (LONGLONG)(newTimestamp - curTime), GetDeviceName().Array(), curTime, newTimestamp);
lastUsedTimestamp = newTimestamp = curTime;
} }
else else
lastUsedTimestamp = newTimestamp; lastUsedTimestamp = newTimestamp;
@ -687,15 +687,25 @@ UINT MMDeviceAudioSource::GetNextBuffer()
if(storageBuffer.Num() == 0 && numAudioFrames == 441) if(storageBuffer.Num() == 0 && numAudioFrames == 441)
{ {
AudioSegment &newSegment = *audioSegments.CreateNew(); lastUsedTimestamp += 10;
newSegment.audioData.CopyArray(newBuffer, numAudioFrames*2);
newSegment.timestamp = (lastUsedTimestamp += 10);
if(!bBrokenTimestamp) if(!bBrokenTimestamp)
{ {
QWORD difVal = GetQWDif(newTimestamp, newSegment.timestamp); QWORD difVal = GetQWDif(newTimestamp, lastUsedTimestamp);
if(difVal > 100) if(difVal > 100)
lastUsedTimestamp = newSegment.timestamp = newTimestamp; lastUsedTimestamp = newTimestamp;
}
if(lastUsedTimestamp > lastSentTimestamp)
{
QWORD adjustVal = (lastUsedTimestamp-lastSentTimestamp);
if(adjustVal < 10)
lastUsedTimestamp += 10-adjustVal;
AudioSegment &newSegment = *audioSegments.CreateNew();
newSegment.audioData.CopyArray(newBuffer, numAudioFrames*2);
newSegment.timestamp = lastUsedTimestamp;
lastSentTimestamp = lastUsedTimestamp;
} }
} }
else else
@ -705,19 +715,28 @@ UINT MMDeviceAudioSource::GetNextBuffer()
storageBuffer.AppendArray(newBuffer, numAudioFrames*2); storageBuffer.AppendArray(newBuffer, numAudioFrames*2);
if(storageBuffer.Num() >= (441*2)) if(storageBuffer.Num() >= (441*2))
{ {
AudioSegment &newSegment = *audioSegments.CreateNew(); lastUsedTimestamp += 10;
newSegment.audioData.CopyArray(storageBuffer.Array(), (441*2)); if(!bBrokenTimestamp)
storageBuffer.RemoveRange(0, (441*2)); {
QWORD difVal = GetQWDif(newTimestamp, lastUsedTimestamp);
if(difVal > 100)
lastUsedTimestamp = newTimestamp - (QWORD(storedFrames)/2*1000/44100);
}
//------------------------ //------------------------
// add new data // add new data
newSegment.timestamp = (lastUsedTimestamp += 10); if(lastUsedTimestamp > lastSentTimestamp)
if(!bBrokenTimestamp)
{ {
QWORD difVal = GetQWDif(newTimestamp, newSegment.timestamp); QWORD adjustVal = (lastUsedTimestamp-lastSentTimestamp);
if(difVal > 100) if(adjustVal < 10)
lastUsedTimestamp = newSegment.timestamp = newTimestamp - (QWORD(storedFrames)/2*1000/44100); lastUsedTimestamp += 10-adjustVal;
AudioSegment &newSegment = *audioSegments.CreateNew();
newSegment.audioData.CopyArray(storageBuffer.Array(), (441*2));
newSegment.timestamp = lastUsedTimestamp;
storageBuffer.RemoveRange(0, (441*2));
} }
//------------------------ //------------------------
@ -725,11 +744,22 @@ UINT MMDeviceAudioSource::GetNextBuffer()
while(storageBuffer.Num() >= (441*2)) while(storageBuffer.Num() >= (441*2))
{ {
AudioSegment &newSegment = *audioSegments.CreateNew(); lastUsedTimestamp += 10;
newSegment.audioData.CopyArray(storageBuffer.Array(), (441*2));
storageBuffer.RemoveRange(0, (441*2));
newSegment.timestamp = (lastUsedTimestamp += 10); if(lastUsedTimestamp > lastSentTimestamp)
{
QWORD adjustVal = (lastUsedTimestamp-lastSentTimestamp);
if(adjustVal < 10)
lastUsedTimestamp += 10-adjustVal;
AudioSegment &newSegment = *audioSegments.CreateNew();
newSegment.audioData.CopyArray(storageBuffer.Array(), (441*2));
storageBuffer.RemoveRange(0, (441*2));
newSegment.timestamp = lastUsedTimestamp;
lastSentTimestamp = lastUsedTimestamp;
}
} }
} }
} }

View File

@ -72,6 +72,7 @@ class MP4FileStream : public VideoFileStream
bool bStreamOpened; bool bStreamOpened;
bool bMP3; bool bMP3;
bool bUseCTSAdjust;
List<BYTE> endBuffer; List<BYTE> endBuffer;
List<UINT> boxOffsets; List<UINT> boxOffsets;
@ -130,6 +131,8 @@ public:
if(!fileOut.Open(lpFile, XFILE_CREATEALWAYS, 1024*1024)) if(!fileOut.Open(lpFile, XFILE_CREATEALWAYS, 1024*1024))
return false; return false;
bUseCTSAdjust = !AppConfig->GetInt(TEXT("Video Encoding"), TEXT("DisableCTSAdjust"));
fileOut.OutputDword(DWORD_BE(0x20)); fileOut.OutputDword(DWORD_BE(0x20));
fileOut.OutputDword(DWORD_BE('ftyp')); fileOut.OutputDword(DWORD_BE('ftyp'));
fileOut.OutputDword(DWORD_BE('isom')); fileOut.OutputDword(DWORD_BE('isom'));
@ -483,7 +486,11 @@ public:
output.Serialize(IFrameIDs.Array(), IFrameIDs.Num()*sizeof(UINT)); output.Serialize(IFrameIDs.Array(), IFrameIDs.Num()*sizeof(UINT));
PopBox(); //stss PopBox(); //stss
PushBox(output, DWORD_BE('ctts')); //list of composition time offsets PushBox(output, DWORD_BE('ctts')); //list of composition time offsets
output.OutputDword(0); //version (0) and flags (none) if(bUseCTSAdjust)
output.OutputDword(0); //version (0) and flags (none)
else
output.OutputDword(DWORD_BE(0x01000000)); //version (1) and flags (none)
output.OutputDword(fastHtonl(compositionOffsets.Num())); output.OutputDword(fastHtonl(compositionOffsets.Num()));
for(UINT i=0; i<compositionOffsets.Num(); i++) for(UINT i=0; i<compositionOffsets.Num(); i++)
{ {

View File

@ -71,7 +71,7 @@ extern OBS *App;
extern TCHAR lpAppDataPath[MAX_PATH]; extern TCHAR lpAppDataPath[MAX_PATH];
#define OBS_VERSION 0x000457 #define OBS_VERSION 0x000457
#define OBS_VERSION_STRING_ANSI "Open Broadcaster Software v0.457a" #define OBS_VERSION_STRING_ANSI "Open Broadcaster Software v0.458a (pre-release 2)"
#define OBS_VERSION_STRING TEXT(OBS_VERSION_STRING_ANSI) #define OBS_VERSION_STRING TEXT(OBS_VERSION_STRING_ANSI)
#define OBS_WINDOW_CLASS TEXT("OBSWindowClass") #define OBS_WINDOW_CLASS TEXT("OBSWindowClass")

View File

@ -2488,7 +2488,7 @@ void OBS::MainCaptureLoop()
if(audioTimestamp > curSegment.timestamp) if(audioTimestamp > curSegment.timestamp)
break; break;
//Log(TEXT("audioTimestamp: %u, curTimestamp: %u"), audioTimestamp, curSegment.timestamp); //Log(TEXT("audioTimestamp: %llu"), audioTimestamp);
List<BYTE> &audioData = pendingAudioFrames[0].audioData; List<BYTE> &audioData = pendingAudioFrames[0].audioData;
@ -2509,6 +2509,8 @@ void OBS::MainCaptureLoop()
} }
} }
//Log(TEXT("videoTimestamp: %llu"), curSegment.timestamp);
//Log(TEXT("no more audio to get")); //Log(TEXT("no more audio to get"));
OSLeaveMutex(hSoundDataMutex); OSLeaveMutex(hSoundDataMutex);

View File

@ -1591,6 +1591,11 @@ INT_PTR CALLBACK OBS::AdvancedSettingsProc(HWND hwnd, UINT message, WPARAM wPara
//------------------------------------ //------------------------------------
bool bDisableCTSAdjust = AppConfig->GetInt(TEXT("Video Encoding"), TEXT("DisableCTSAdjust")) != 0;
SendMessage(GetDlgItem(hwnd, IDC_DISABLECTSADJUST), BM_SETCHECK, bDisableCTSAdjust ? BST_CHECKED : BST_UNCHECKED, 0);
//------------------------------------
/*bool bDisableD3DCompat = AppConfig->GetInt(TEXT("Video"), TEXT("DisableD3DCompatibilityMode")) != 0; /*bool bDisableD3DCompat = AppConfig->GetInt(TEXT("Video"), TEXT("DisableD3DCompatibilityMode")) != 0;
SendMessage(GetDlgItem(hwnd, IDC_DISABLED3DCOMPATIBILITY), BM_SETCHECK, bDisableD3DCompat ? BST_CHECKED : BST_UNCHECKED, 0); SendMessage(GetDlgItem(hwnd, IDC_DISABLED3DCOMPATIBILITY), BM_SETCHECK, bDisableD3DCompat ? BST_CHECKED : BST_UNCHECKED, 0);
@ -1767,6 +1772,7 @@ INT_PTR CALLBACK OBS::AdvancedSettingsProc(HWND hwnd, UINT message, WPARAM wPara
} }
break; break;
case IDC_DISABLECTSADJUST:
case IDC_USEHIGHQUALITYRESAMPLING: case IDC_USEHIGHQUALITYRESAMPLING:
case IDC_USEMULTITHREADEDOPTIMIZATIONS: case IDC_USEMULTITHREADEDOPTIMIZATIONS:
case IDC_USESYNCFIX: case IDC_USESYNCFIX:
@ -2061,6 +2067,11 @@ void OBS::ApplySettings()
//------------------------------------ //------------------------------------
BOOL bDisableCTSAdjust = SendMessage(GetDlgItem(hwndCurrentSettings, IDC_DISABLECTSADJUST), BM_GETCHECK, 0, 0) == BST_CHECKED;
AppConfig->SetInt (TEXT("Video Encoding"), TEXT("DisableCTSAdjust"), bDisableCTSAdjust);
//------------------------------------
BOOL bUseHQResampling = SendMessage(GetDlgItem(hwndCurrentSettings, IDC_USEHIGHQUALITYRESAMPLING), BM_GETCHECK, 0, 0) == BST_CHECKED; BOOL bUseHQResampling = SendMessage(GetDlgItem(hwndCurrentSettings, IDC_USEHIGHQUALITYRESAMPLING), BM_GETCHECK, 0, 0) == BST_CHECKED;
AppConfig->SetInt (TEXT("Audio"), TEXT("UseHighQualityResampling"), bUseHQResampling); AppConfig->SetInt (TEXT("Audio"), TEXT("UseHighQualityResampling"), bUseHQResampling);

View File

@ -203,6 +203,8 @@
#define IDC_PRIORITY 1132 #define IDC_PRIORITY 1132
#define IDC_USECBR 1133 #define IDC_USECBR 1133
#define IDC_COMBO1 1139 #define IDC_COMBO1 1139
#define IDC_CHECK3 1140
#define IDC_DISABLECTSADJUST 1140
#define IDA_SOURCE_MOVEUP 40018 #define IDA_SOURCE_MOVEUP 40018
#define IDA_SOURCE_MOVEDOWN 40019 #define IDA_SOURCE_MOVEDOWN 40019
#define IDA_SOURCE_MOVETOTOP 40020 #define IDA_SOURCE_MOVETOTOP 40020
@ -233,7 +235,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS #ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 141 #define _APS_NEXT_RESOURCE_VALUE 141
#define _APS_NEXT_COMMAND_VALUE 40044 #define _APS_NEXT_COMMAND_VALUE 40044
#define _APS_NEXT_CONTROL_VALUE 1140 #define _APS_NEXT_CONTROL_VALUE 1141
#define _APS_NEXT_SYMED_VALUE 101 #define _APS_NEXT_SYMED_VALUE 101
#endif #endif
#endif #endif