diff --git a/OBS.rc b/OBS.rc index 52bba484..37b314e0 100644 --- a/OBS.rc +++ b/OBS.rc @@ -313,7 +313,7 @@ BEGIN "Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,17,173,10 RTEXT "Settings.Advanced.ProcessPriority",IDC_STATIC,7,31,136,8 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 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 @@ -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.UnlockHigherFPS",IDC_UNLOCKHIGHFPS, "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, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,173,332,10 - GROUPBOX "Settings.Advanced.Network",IDC_STATIC,4,197,418,67 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,187,332,10 + GROUPBOX "Settings.Advanced.Network",IDC_STATIC,4,211,418,67 CONTROL "Settings.Advanced.UseSendBuffer",IDC_USESENDBUFFER, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,212,277,10 - RTEXT "Settings.Advanced.SendBufferSize",IDC_STATIC,5,227,138,8 - COMBOBOX IDC_SENDBUFFERSIZE,145,225,158,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,226,277,10 + RTEXT "Settings.Advanced.SendBufferSize",IDC_STATIC,5,241,138,8 + 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 - RTEXT "Settings.Advanced.BindToIP",IDC_STATIC,5,244,138,8 - COMBOBOX IDC_BINDIP,145,242,87,62,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + RTEXT "Settings.Advanced.BindToIP",IDC_STATIC,5,258,138,8 + 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 IDD_CONFIGURETRANSITIONSOURCE DIALOGEX 0, 0, 338, 198 diff --git a/Source/D3D10OutputDuplicator.cpp b/Source/D3D10OutputDuplicator.cpp index 98c89513..e92454c8 100644 --- a/Source/D3D10OutputDuplicator.cpp +++ b/Source/D3D10OutputDuplicator.cpp @@ -75,6 +75,7 @@ bool D3D10OutputDuplicator::Init(UINT output) D3D10OutputDuplicator::~D3D10OutputDuplicator() { SafeRelease(duplicator); + delete copyTex; } DuplicatorInfo D3D10OutputDuplicator::AquireNextFrame(UINT timeout, POINT &mousePos, BOOL &mouseVisible) diff --git a/Source/DesktopImageSource.cpp b/Source/DesktopImageSource.cpp index 64ee821d..cc92b794 100644 --- a/Source/DesktopImageSource.cpp +++ b/Source/DesktopImageSource.cpp @@ -78,8 +78,7 @@ public: if(warningID) App->RemoveStreamInfo(warningID); - if(duplicator) - delete duplicator; + delete duplicator; delete alphaIgnoreShader; delete colorKeyShader; @@ -87,6 +86,9 @@ public: void PreprocessWindows8MonitorCapture() { + if(!duplicator) + duplicator = GS->CreateOutputDulicator(0); + if(duplicator) { Texture *newTex = NULL; @@ -103,6 +105,10 @@ public: } case DuplicatorInfo_Error: + delete duplicator; + duplicator = NULL; + return; + case DuplicatorInfo_Timeout: return; } @@ -362,7 +368,7 @@ public: captureRect.right = x+cx; captureRect.bottom = y+cy; - //bWindows8MonitorCapture = captureType == 0 && IsWindows8Up(); + bWindows8MonitorCapture = captureType == 0 && IsWindows8Up(); width = cx; height = cy; diff --git a/Source/Encoder_x264.cpp b/Source/Encoder_x264.cpp index 3326b5b4..39fa96e7 100644 --- a/Source/Encoder_x264.cpp +++ b/Source/Encoder_x264.cpp @@ -67,12 +67,12 @@ class X264Encoder : public VideoEncoder bool bFirstFrameProcessed; - bool bUseCBR; + bool bUseCBR, bUseCTSAdjust; List CurrentPackets; List HeaderPacket; - int delayOffset; + INT64 delayOffset; inline void ClearPackets() { @@ -125,7 +125,7 @@ public: } 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_height = height; paramData.vui.b_fullrange = 0; //specify full range input levels @@ -141,6 +141,7 @@ public: //paramData.pf_log = get_x264_log; //paramData.i_log_level = X264_LOG_INFO; + bUseCTSAdjust = !AppConfig->GetInt(TEXT("Video Encoding"), TEXT("DisableCTSAdjust")); BOOL bUseCustomParams = AppConfig->GetInt(TEXT("Video Encoding"), TEXT("UseCustomSettings")); if(bUseCustomParams) { @@ -217,23 +218,24 @@ public: if(!bFirstFrameProcessed && nalNum) { - if(picOut.i_dts < 0) - delayOffset = int(-picOut.i_dts); - //Log(TEXT("cts: %u, timestamp: %u"), ctsOffset, outputTimestamp); + delayOffset = -picOut.i_dts; bFirstFrameProcessed = true; } INT64 ts = INT64(outputTimestamp); - int timeOffset = int(picOut.i_pts+INT64(delayOffset)-ts); + int timeOffset = int((picOut.i_pts+delayOffset)-ts); - timeOffset += ctsOffset; - - //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) + if(bUseCTSAdjust) { - ctsOffset -= timeOffset; - timeOffset = 0; + timeOffset += ctsOffset; + + //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); diff --git a/Source/MMDeviceAudioSource.cpp b/Source/MMDeviceAudioSource.cpp index 4e7def81..b8041af9 100644 --- a/Source/MMDeviceAudioSource.cpp +++ b/Source/MMDeviceAudioSource.cpp @@ -56,7 +56,7 @@ class MMDeviceAudioSource : public AudioSource List audioSegments; bool bFirstFrameReceived; - QWORD lastUsedTimestamp; + QWORD lastUsedTimestamp, lastSentTimestamp; bool bBrokenTimestamp; //----------------------------------------- @@ -417,9 +417,9 @@ UINT MMDeviceAudioSource::GetNextBuffer() if(newTimestamp < (curTime-1000) || newTimestamp > (curTime+1000)) { 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 lastUsedTimestamp = newTimestamp; @@ -687,15 +687,25 @@ UINT MMDeviceAudioSource::GetNextBuffer() if(storageBuffer.Num() == 0 && numAudioFrames == 441) { - AudioSegment &newSegment = *audioSegments.CreateNew(); - newSegment.audioData.CopyArray(newBuffer, numAudioFrames*2); - - newSegment.timestamp = (lastUsedTimestamp += 10); + lastUsedTimestamp += 10; if(!bBrokenTimestamp) { - QWORD difVal = GetQWDif(newTimestamp, newSegment.timestamp); + QWORD difVal = GetQWDif(newTimestamp, lastUsedTimestamp); 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 @@ -705,19 +715,28 @@ UINT MMDeviceAudioSource::GetNextBuffer() storageBuffer.AppendArray(newBuffer, numAudioFrames*2); if(storageBuffer.Num() >= (441*2)) { - AudioSegment &newSegment = *audioSegments.CreateNew(); - newSegment.audioData.CopyArray(storageBuffer.Array(), (441*2)); - storageBuffer.RemoveRange(0, (441*2)); + lastUsedTimestamp += 10; + if(!bBrokenTimestamp) + { + QWORD difVal = GetQWDif(newTimestamp, lastUsedTimestamp); + if(difVal > 100) + lastUsedTimestamp = newTimestamp - (QWORD(storedFrames)/2*1000/44100); + } //------------------------ // add new data - newSegment.timestamp = (lastUsedTimestamp += 10); - if(!bBrokenTimestamp) + if(lastUsedTimestamp > lastSentTimestamp) { - QWORD difVal = GetQWDif(newTimestamp, newSegment.timestamp); - if(difVal > 100) - lastUsedTimestamp = newSegment.timestamp = newTimestamp - (QWORD(storedFrames)/2*1000/44100); + QWORD adjustVal = (lastUsedTimestamp-lastSentTimestamp); + if(adjustVal < 10) + 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)) { - AudioSegment &newSegment = *audioSegments.CreateNew(); - newSegment.audioData.CopyArray(storageBuffer.Array(), (441*2)); - storageBuffer.RemoveRange(0, (441*2)); + lastUsedTimestamp += 10; - 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; + } } } } diff --git a/Source/MP4FileStream.cpp b/Source/MP4FileStream.cpp index f530caa9..2cbfac1d 100644 --- a/Source/MP4FileStream.cpp +++ b/Source/MP4FileStream.cpp @@ -72,6 +72,7 @@ class MP4FileStream : public VideoFileStream bool bStreamOpened; bool bMP3; + bool bUseCTSAdjust; List endBuffer; List boxOffsets; @@ -130,6 +131,8 @@ public: if(!fileOut.Open(lpFile, XFILE_CREATEALWAYS, 1024*1024)) return false; + bUseCTSAdjust = !AppConfig->GetInt(TEXT("Video Encoding"), TEXT("DisableCTSAdjust")); + fileOut.OutputDword(DWORD_BE(0x20)); fileOut.OutputDword(DWORD_BE('ftyp')); fileOut.OutputDword(DWORD_BE('isom')); @@ -483,7 +486,11 @@ public: output.Serialize(IFrameIDs.Array(), IFrameIDs.Num()*sizeof(UINT)); PopBox(); //stss 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())); for(UINT i=0; i curSegment.timestamp) break; - //Log(TEXT("audioTimestamp: %u, curTimestamp: %u"), audioTimestamp, curSegment.timestamp); + //Log(TEXT("audioTimestamp: %llu"), audioTimestamp); List &audioData = pendingAudioFrames[0].audioData; @@ -2509,6 +2509,8 @@ void OBS::MainCaptureLoop() } } + //Log(TEXT("videoTimestamp: %llu"), curSegment.timestamp); + //Log(TEXT("no more audio to get")); OSLeaveMutex(hSoundDataMutex); diff --git a/Source/Settings.cpp b/Source/Settings.cpp index 3f6381c3..c1c854ed 100644 --- a/Source/Settings.cpp +++ b/Source/Settings.cpp @@ -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; 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; + case IDC_DISABLECTSADJUST: case IDC_USEHIGHQUALITYRESAMPLING: case IDC_USEMULTITHREADEDOPTIMIZATIONS: 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; AppConfig->SetInt (TEXT("Audio"), TEXT("UseHighQualityResampling"), bUseHQResampling); diff --git a/resource.h b/resource.h index 325e2186..6fd3d481 100644 --- a/resource.h +++ b/resource.h @@ -203,6 +203,8 @@ #define IDC_PRIORITY 1132 #define IDC_USECBR 1133 #define IDC_COMBO1 1139 +#define IDC_CHECK3 1140 +#define IDC_DISABLECTSADJUST 1140 #define IDA_SOURCE_MOVEUP 40018 #define IDA_SOURCE_MOVEDOWN 40019 #define IDA_SOURCE_MOVETOTOP 40020 @@ -233,7 +235,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 141 #define _APS_NEXT_COMMAND_VALUE 40044 -#define _APS_NEXT_CONTROL_VALUE 1140 +#define _APS_NEXT_CONTROL_VALUE 1141 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif