This repository has been archived by the owner on Mar 3, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 75
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
50 changed files
with
9,968 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/**************************************************************************************************************** | ||
Filename : AMDEncoder.h | ||
Content : AMD Encoder implementation for creating h264 format video | ||
Created : Jan 26, 2017 | ||
Authors : Homin Lee | ||
Copyright : | ||
****************************************************************************************************************/ | ||
|
||
#pragma once | ||
#include <stdio.h> | ||
#include <tchar.h> | ||
#include <codecvt> | ||
#include <wincodec.h> | ||
#include "AMD/common/AMFFactory.h" | ||
#include "AMD/include/components/VideoEncoderVCE.h" | ||
#include "AMD/include/components/VideoEncoderHEVC.h" | ||
#include "AMD/common/Thread.h" | ||
#include "AMD/common/AMFSTL.h" | ||
#include "ScreenGrab.h" | ||
#include "Log.h" | ||
#include "Common.h" | ||
#include "ScopedCOMPtr.h" | ||
|
||
#define START_TIME_PROPERTY L"StartTimeProperty" // custom property ID to store submission time in a frame - all custom properties are copied from input to output | ||
#define MILLISEC_TIME 10000 | ||
#define ENABLE_4K 1 | ||
|
||
//-------------------------------------------------------------------------------------------------------------- | ||
// *** SAFE_RELEASE macro | ||
#ifndef SAFE_RELEASE | ||
#define SAFE_RELEASE(a) if (a) { a->Release(); a= NULL; } | ||
#endif | ||
|
||
using namespace FBCapture::Common; | ||
using namespace Directx; | ||
using namespace std; | ||
|
||
namespace FBCapture { | ||
namespace Video { | ||
|
||
class PollingThread : public amf::AMFThread { | ||
protected: | ||
amf::AMFContextPtr context_ = nullptr; | ||
amf::AMFComponentPtr encoder_ = nullptr; | ||
FILE *file_ = nullptr; | ||
public: | ||
PollingThread(amf::AMFContext *context, amf::AMFComponent *encoder, const wchar_t *pFileName); | ||
~PollingThread(); | ||
virtual void Run(); | ||
}; | ||
|
||
class AMDEncoder { | ||
public: | ||
FBCAPTURE_STATUS initAMDEncodingSession(); | ||
FBCAPTURE_STATUS encodeMain(const void* texturePtr, const wstring& fullSavePath, int bitrate, int fps, bool needFlipping); | ||
FBCAPTURE_STATUS flushInputTextures(); | ||
FBCAPTURE_STATUS saveScreenShot(const void* texturePtr, const wstring& fullSavePath, bool is360); | ||
AMDEncoder(ID3D11Device* device); // Constructor | ||
virtual ~AMDEncoder(); | ||
protected: | ||
PollingThread* thread_ = nullptr; | ||
|
||
wchar_t *codec_ = nullptr; | ||
|
||
// initialize AMF | ||
amf::AMFContextPtr context_ = nullptr; | ||
amf::AMFComponentPtr encoder_ = nullptr; | ||
amf::AMFSurfacePtr surfaceIn_ = nullptr; | ||
|
||
amf::AMF_MEMORY_TYPE memoryTypeIn_; | ||
amf::AMF_SURFACE_FORMAT formatIn_; | ||
|
||
amf_int32 widthIn_ = 0; | ||
amf_int32 heightIn_ = 0; | ||
amf_int32 frameRateIn_ = 0; | ||
amf_int64 bitRateIn_ = 0; // in bits, 5MBit | ||
bool maximumSpeed_ = false; | ||
bool encodingConfigInitiated_ = false; | ||
|
||
// DX 11 interfaces | ||
ID3D11Texture2D* fromTexturePtr_ = nullptr; | ||
ScopedCOMPtr<ID3D11Device> device_ = nullptr; | ||
D3D11_BOX dirtyRegion_ = {}; | ||
D3D11_TEXTURE2D_DESC globalTexDesc_ = {}; | ||
|
||
protected: | ||
FBCAPTURE_STATUS initializeEncodingComponents(const wstring& fullSavePath, int bitrate, int fps); | ||
FBCAPTURE_STATUS fillSurface(amf::AMFSurface *surface); | ||
FBCAPTURE_STATUS createD3D11Resources(ID3D11Texture2D* texture); | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
#include "AudioBuffer.h" | ||
|
||
#include "log.h" | ||
#include "Common.h" | ||
|
||
#include <string.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <limits> | ||
#include <assert.h> | ||
|
||
#define CHECK_HRESULT(hr, message) \ | ||
if (FAILED(hr)) \ | ||
{ \ | ||
LOG(message ": %x.\n", hr); \ | ||
return; \ | ||
} \ | ||
else \ | ||
void(0) | ||
|
||
using namespace FBCapture::Common; | ||
|
||
namespace FBCapture { | ||
namespace Audio { | ||
AudioBuffer::AudioBuffer() : buffers_(nullptr), numBuffers_(0), mixBuffer_(nullptr) {} | ||
|
||
AudioBuffer::~AudioBuffer() { | ||
releaseBuffers(); | ||
} | ||
|
||
void AudioBuffer::releaseBuffers() { | ||
|
||
if (buffers_ == nullptr) | ||
return; | ||
|
||
for (int i = 0; i < numBuffers_; ++i) { | ||
Buffer& buff = buffers_[i]; | ||
if (buff.data_ != nullptr) { | ||
free(buff.data_); | ||
} | ||
} | ||
|
||
delete[] buffers_; | ||
buffers_ = nullptr; | ||
|
||
if (mixBuffer_ != nullptr) { | ||
free(mixBuffer_); | ||
mixBuffer_ = nullptr; | ||
} | ||
} | ||
|
||
void AudioBuffer::initizalize(int numBuffers) { | ||
numBuffers_ = numBuffers; | ||
buffers_ = new Buffer[numBuffers]; | ||
memset(buffers_, 0, numBuffers * sizeof(Buffer)); | ||
mixBuffer_ = static_cast<int16_t*>(malloc(kMIX_BUFFER_LENGTH * kSTEREO * sizeof(int16_t))); | ||
} | ||
|
||
void AudioBuffer::initializeBuffer(int index, int channelCount) { | ||
if (index >= numBuffers_) { | ||
return; // out of bounds! | ||
} | ||
|
||
Buffer& buff = buffers_[index]; | ||
|
||
buff.channelCount_ = channelCount; | ||
} | ||
|
||
void AudioBuffer::write(int index, const int16_t* data, size_t lengthFrames) { | ||
if (index >= numBuffers_) { | ||
return; // out of bounds! | ||
} | ||
|
||
Buffer& buff = buffers_[index]; | ||
assert(buff.positionFrames_ >= 0); | ||
|
||
const int requiredLengthFrames = buff.positionFrames_ + lengthFrames; | ||
|
||
if (requiredLengthFrames > (1024 * 500)) { | ||
return; // sanity check! | ||
} | ||
|
||
if (buff.length_ < requiredLengthFrames) { | ||
buff.data_ = static_cast<int16_t*>(realloc(buff.data_, requiredLengthFrames * buff.channelCount_ * sizeof(int16_t))); | ||
buff.length_ = requiredLengthFrames; | ||
} | ||
|
||
memcpy(buff.data_ + (buff.positionFrames_ * buff.channelCount_), data, lengthFrames * buff.channelCount_ * sizeof(int16_t)); | ||
buff.positionFrames_ += lengthFrames; | ||
|
||
assert(buff.positionFrames_ >= 0); | ||
} | ||
|
||
void AudioBuffer::getBuffer(const int16_t** buffer, size_t* length, bool enabledAudioCapture, bool enabledMicCapture) { | ||
int len = kMIX_BUFFER_LENGTH; | ||
|
||
for (int i = 0; i < numBuffers_; ++i) { | ||
if (buffers_[i].positionFrames_ < len) { | ||
assert(buffers_[i].positionFrames_ >= 0); | ||
len = buffers_[i].positionFrames_; | ||
} | ||
} | ||
|
||
if (len <= 0) { | ||
return; | ||
} | ||
|
||
memset(mixBuffer_, 0, kMIX_BUFFER_LENGTH * sizeof(int16_t)); | ||
|
||
for (int i = 0; i < numBuffers_; ++i) { | ||
Buffer& buff = buffers_[i]; | ||
for (int frame = 0; frame < len; ++frame) { | ||
for (int chan = 0; chan < kSTEREO; ++chan) { | ||
if (enabledAudioCapture && !enabledMicCapture) { // Mix buffer for input audio data only | ||
if (i == BufferIndex_Headphones) { | ||
mixBuffer_[(frame * kSTEREO) + chan] += buff.data_[(frame * buff.channelCount_) + chan % buff.channelCount_]; | ||
} | ||
} else if (!enabledAudioCapture && enabledMicCapture) { // Mix buffer for output audio data only | ||
if (i == BufferIndex_Microphone) { | ||
mixBuffer_[(frame * kSTEREO) + chan] += buff.data_[(frame * buff.channelCount_) + chan % buff.channelCount_]; | ||
} | ||
} else if (enabledAudioCapture && enabledMicCapture) { // Mix buffer for both of input and output audio data | ||
mixBuffer_[(frame * kSTEREO) + chan] += buff.data_[(frame * buff.channelCount_) + chan % buff.channelCount_]; | ||
} | ||
} | ||
} | ||
|
||
// Compact the buffer | ||
memmove(buff.data_, buff.data_ + (len * buff.channelCount_), (buff.length_ - len) * sizeof(int16_t) * buff.channelCount_); | ||
buff.positionFrames_ -= len; | ||
assert(buff.positionFrames_ >= 0); | ||
} | ||
|
||
*length = len * kSTEREO; | ||
*buffer = mixBuffer_; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/**************************************************************************************************************** | ||
Filename : AdaptiveResampler.h | ||
Content : A adaptive resampling ringbuffer to sync to input signals at different and varying sample rates | ||
Created : June 16, 2017 | ||
Authors : Pete Stirling | ||
Copyright : | ||
****************************************************************************************************************/ | ||
|
||
#pragma once | ||
|
||
#define NOMINMAX | ||
#include <Audioclient.h> | ||
#include <stdint.h> | ||
|
||
namespace FBCapture { | ||
namespace Audio { | ||
|
||
enum BufferIndex { | ||
BufferIndex_Headphones = 0, | ||
BufferIndex_Microphone, | ||
BufferIndex_Max | ||
}; | ||
|
||
enum BufferNums { | ||
No_Device = 0, | ||
Output_Device_Only, | ||
Input_Output_Device | ||
}; | ||
|
||
class AudioBuffer { | ||
public: | ||
AudioBuffer(); | ||
~AudioBuffer(); | ||
|
||
void initizalize(int numBuffers); | ||
void initializeBuffer(int index, int channelCount); // WAVEFORMATEX *bufferFormat, IAudioClock* clock); | ||
void write(int index, const int16_t* data, size_t length); | ||
void getBuffer(const int16_t** buffer, size_t* length, bool enabledAudioCapture, bool enabledMicCapture); | ||
void releaseBuffers(); | ||
|
||
private: | ||
struct Buffer { | ||
int16_t* data_; | ||
int channelCount_; | ||
int length_; | ||
int positionFrames_; | ||
}; | ||
|
||
Buffer* buffers_; | ||
int numBuffers_; | ||
int16_t* mixBuffer_; | ||
static const size_t kMIX_BUFFER_LENGTH = 4096; // PAS | ||
static const int kSTEREO = 2; | ||
}; | ||
|
||
} | ||
} |
Oops, something went wrong.