Commit a07c84f7 by 景炳强

1.音视频同步

parent 46675251
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -29,7 +29,7 @@ class DeckLinkOutputDevice : public QObject, public IDeckLinkVideoOutputCallback ...@@ -29,7 +29,7 @@ class DeckLinkOutputDevice : public QObject, public IDeckLinkVideoOutputCallback
using ScheduledFramesList = std::list<ComPtr<DeckLinkOutputVideoFrame>>; using ScheduledFramesList = std::list<ComPtr<DeckLinkOutputVideoFrame>>;
public: public:
DeckLinkOutputDevice(ComPtr<IDeckLink>& decklink, int videoPrerollSize); DeckLinkOutputDevice(ComPtr<IDeckLink>& decklink, int videoPrerollSize,int index);
virtual ~DeckLinkOutputDevice() = default; virtual ~DeckLinkOutputDevice() = default;
// IUnknown interface // IUnknown interface
...@@ -95,4 +95,9 @@ private: ...@@ -95,4 +95,9 @@ private:
void outputAudioFrameFunc(void); void outputAudioFrameFunc(void);
bool waitForReferenceSignalToLock(void); bool waitForReferenceSignalToLock(void);
void checkEndOfPreroll(void); void checkEndOfPreroll(void);
//
int64_t current_video_time = 0;
int64_t current_sleep_ms = 0;
qint32 Index;
}; };
...@@ -35,9 +35,10 @@ public: ...@@ -35,9 +35,10 @@ public:
DeckLinkOpenGLWidget* GetPreviewView(void) const { return PreviewView; } DeckLinkOpenGLWidget* GetPreviewView(void) const { return PreviewView; }
ComPtr<DeckLinkOutputDevice> GetSelectedDevice(void) const { return SelectedDevice; } ComPtr<DeckLinkOutputDevice> GetSelectedDevice(void) const { return SelectedDevice; }
void BindInputPage(DeckLinkInputPage* inputPage, std::shared_ptr<ProcessThread> process) { void BindInputPage(DeckLinkInputPage* inputPage, std::shared_ptr<ProcessThread> process,int index) {
BindingInputPage = inputPage; BindingInputPage = inputPage;
Process = process; Process = process;
Index = index;
} }
...@@ -63,6 +64,7 @@ private: ...@@ -63,6 +64,7 @@ private:
DeckLinkInputPage* BindingInputPage; DeckLinkInputPage* BindingInputPage;
std::shared_ptr<ProcessThread> Process; std::shared_ptr<ProcessThread> Process;
qint32 Index;
ComPtr<DeckLinkOutputDevice> SelectedDevice; ComPtr<DeckLinkOutputDevice> SelectedDevice;
......
...@@ -5,10 +5,11 @@ ...@@ -5,10 +5,11 @@
#include "BlackMagicDesign/ReferenceTime.h" #include "BlackMagicDesign/ReferenceTime.h"
extern int OutputDeleyTime; extern int OutputDeleyTime;
extern int OutputPlayMode;
#define OUTPUT_1080 1 #define OUTPUT_1080 1
DeckLinkOutputDevice::DeckLinkOutputDevice(ComPtr<IDeckLink>& decklink, int videoPrerollSize) DeckLinkOutputDevice::DeckLinkOutputDevice(ComPtr<IDeckLink>& decklink, int videoPrerollSize,int index)
: RefCount(1), : RefCount(1),
state(PlaybackState::Idle), state(PlaybackState::Idle),
deckLink(decklink), deckLink(decklink),
...@@ -17,11 +18,13 @@ DeckLinkOutputDevice::DeckLinkOutputDevice(ComPtr<IDeckLink>& decklink, int vide ...@@ -17,11 +18,13 @@ DeckLinkOutputDevice::DeckLinkOutputDevice(ComPtr<IDeckLink>& decklink, int vide
seenFirstVideoFrame(false), seenFirstVideoFrame(false),
startPlaybackTime(0), startPlaybackTime(0),
scheduledFrameCompletedCallback(nullptr), scheduledFrameCompletedCallback(nullptr),
first_sleep(false) first_sleep(false),
Index(index)
{ {
// Check that device has an output interface, this will throw an error if using a capture-only device such as DeckLink Mini Recorder // Check that device has an output interface, this will throw an error if using a capture-only device such as DeckLink Mini Recorder
if (!deckLinkOutput) if (!deckLinkOutput)
throw std::runtime_error("DeckLink device does not have an output interface."); throw std::runtime_error("DeckLink device does not have an output interface.");
current_sleep_ms = OutputDeleyTime * 1000;
} }
// IUnknown methods // IUnknown methods
...@@ -120,8 +123,17 @@ HRESULT DeckLinkOutputDevice::ScheduledPlaybackHasStopped() ...@@ -120,8 +123,17 @@ HRESULT DeckLinkOutputDevice::ScheduledPlaybackHasStopped()
bool DeckLinkOutputDevice::StartPlayback(BMDDisplayMode displayMode, bool enable3D, BMDPixelFormat pixelFormat, bool requireReferenceLocked, IDeckLinkScreenPreviewCallback* screenPreviewCallback) bool DeckLinkOutputDevice::StartPlayback(BMDDisplayMode displayMode, bool enable3D, BMDPixelFormat pixelFormat, bool requireReferenceLocked, IDeckLinkScreenPreviewCallback* screenPreviewCallback)
{ {
BMDDisplayMode outputDisplayMode; BMDDisplayMode outputDisplayMode;
#if OUTPUT_1080 #if OUTPUT_1080
switch (OutputPlayMode)
{
case 1:
outputDisplayMode = bmdModeHD1080i50;
break;
default:
outputDisplayMode = displayMode; outputDisplayMode = displayMode;
break;
}
#else #else
outputDisplayMode = BMDDisplayMode::bmdModeHD720p50; outputDisplayMode = BMDDisplayMode::bmdModeHD720p50;
#endif #endif
...@@ -302,17 +314,17 @@ bool DeckLinkOutputDevice::getReferenceSignalMode(BMDDisplayMode* mode) ...@@ -302,17 +314,17 @@ bool DeckLinkOutputDevice::getReferenceSignalMode(BMDDisplayMode* mode)
if(outputVideoFrameQueue.WaitFor(outputImage)) if(outputVideoFrameQueue.WaitFor(outputImage))
{ {
auto now_time = QDateTime::currentMSecsSinceEpoch(); auto now_time = QDateTime::currentMSecsSinceEpoch();
auto input_time = outputImage->getInputFrameCurTimeStamp(); auto dever_time = now_time - outputImage->getInputFrameCurTimeStamp();
auto dever_time = now_time - input_time; qDebug() << "index:"<<Index << "input frame cur time:" << outputImage->getInputFrameCurTimeStamp() << " now time:" << now_time << " dever time:" << dever_time << "\n";
qDebug() << "input frame cur time:" << input_time << " now time:" <<now_time << " dever time:"<<dever_time << "\n";
if (dever_time < OutputDeleyTime * 1000) if (dever_time < OutputDeleyTime * 1000)
{ {
std::this_thread::sleep_for(std::chrono::milliseconds(OutputDeleyTime * 1000 - dever_time)); current_sleep_ms = OutputDeleyTime * 1000 - dever_time;
std::this_thread::sleep_for(std::chrono::milliseconds(current_sleep_ms));
} }
END_WAIT_TIME_COUNTER END_WAIT_TIME_COUNTER
//std::lock_guard<std::mutex> locker(mutex); //std::lock_guard<std::mutex> locker(mutex);
current_video_time = outputImage->getInputFrameCurTimeStamp();
ComPtr<DeckLinkOutputVideoFrame> videoFrame = MakeComPtr<DeckLinkOutputVideoFrame>(outputImage); ComPtr<DeckLinkOutputVideoFrame> videoFrame = MakeComPtr<DeckLinkOutputVideoFrame>(outputImage);
// Record the stream time of the first frame, so we can start playing from the point // Record the stream time of the first frame, so we can start playing from the point
...@@ -353,6 +365,27 @@ bool DeckLinkOutputDevice::getReferenceSignalMode(BMDDisplayMode* mode) ...@@ -353,6 +365,27 @@ bool DeckLinkOutputDevice::getReferenceSignalMode(BMDDisplayMode* mode)
{ {
auto data = audio_packet->audio_data.data(); auto data = audio_packet->audio_data.data();
auto sample = audio_packet->sample; auto sample = audio_packet->sample;
auto audio_tm = audio_packet->frame_time_stamp;
qint32 duration = sample * 1000 / 48000;
while(true)
{
/*if (!current_video_time) {
std::this_thread::sleep_for(std::chrono::milliseconds(current_sleep_ms));
}*/
if(audio_tm > current_video_time && audio_tm - current_video_time > duration)
{
std::this_thread::sleep_for(std::chrono::milliseconds(duration));
}
else if ( (audio_tm > current_video_time && audio_tm - current_video_time <= duration) || audio_tm <= current_video_time)
{
break;
}
else {
qDebug() << "send audio other--------------\n";
}
}
qDebug() << "index:"<<Index << "send sdi audio timestamp:" << audio_tm << ",video timestamp:"<<current_video_time << "\n";
quint32 sampleFramesWritten; quint32 sampleFramesWritten;
HRESULT ret = deckLinkOutput->WriteAudioSamplesSync(data,sample,&sampleFramesWritten); HRESULT ret = deckLinkOutput->WriteAudioSamplesSync(data,sample,&sampleFramesWritten);
if(ret == S_OK) if(ret == S_OK)
......
...@@ -245,7 +245,7 @@ void DeckLinkOutputPage::RequestedDeviceGranted(ComPtr<IDeckLink>& device) ...@@ -245,7 +245,7 @@ void DeckLinkOutputPage::RequestedDeviceGranted(ComPtr<IDeckLink>& device)
{ {
START_SLOT_TIME_COUNTER START_SLOT_TIME_COUNTER
SelectedDevice = MakeComPtr<DeckLinkOutputDevice>(device, 1); SelectedDevice = MakeComPtr<DeckLinkOutputDevice>(device, 1,Index);
// Register profile callback with newly selected device`s profile manager // Register profile callback with newly selected device`s profile manager
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
int OutputDeleyTime = 5; int OutputDeleyTime = 5;
int FrameRate = 50; int FrameRate = 50;
int PrvwFlag = 0; int PrvwFlag = 0;
int OutputPlayMode = 0;
qint64 StartTimeStamp = 0; qint64 StartTimeStamp = 0;
MomentaMedia::MomentaMedia(QWidget *parent) MomentaMedia::MomentaMedia(QWidget *parent)
: QMainWindow(parent) : QMainWindow(parent)
...@@ -71,7 +72,7 @@ MomentaMedia::MomentaMedia(QWidget *parent) ...@@ -71,7 +72,7 @@ MomentaMedia::MomentaMedia(QWidget *parent)
if( i < InputDevicePages.size()) if( i < InputDevicePages.size())
{ {
OutputDevicePages[i]->BindInputPage(InputDevicePages[i], ProcessThreads[i]); OutputDevicePages[i]->BindInputPage(InputDevicePages[i], ProcessThreads[i],i);
} }
connect(OutputDevicePages[i], &DeckLinkOutputPage::RequestDeckLink, this, std::bind(&MomentaMedia::RequestOutputDevice, this, OutputDevicePages[i], std::placeholders::_1)); connect(OutputDevicePages[i], &DeckLinkOutputPage::RequestDeckLink, this, std::bind(&MomentaMedia::RequestOutputDevice, this, OutputDevicePages[i], std::placeholders::_1));
...@@ -194,9 +195,12 @@ void MomentaMedia::closeEvent(QCloseEvent* event) ...@@ -194,9 +195,12 @@ void MomentaMedia::closeEvent(QCloseEvent* event)
// DeckLinkDiscovery->Disable(); // DeckLinkDiscovery->Disable();
// exit(0); // exit(0);
qint64 pid = QCoreApplication::applicationPid(); //qint64 pid = QCoreApplication::applicationPid();
QString cmd = QString("TASKKILL /PID %1 /F").arg(pid);//Windows 系统下,杀死当前进程命令,不杀死其开启的子进程 //QString cmd = QString("TASKKILL /PID %1 /F").arg(pid);//Windows 系统下,杀死当前进程命令,不杀死其开启的子进程
WinExec(cmd.toLocal8Bit().data(), SW_HIDE);//SW_HIDE:控制运行cmd时,不弹出cmd运行窗口 //WinExec(cmd.toLocal8Bit().data(), SW_HIDE);//SW_HIDE:控制运行cmd时,不弹出cmd运行窗口
HANDLE hself = GetCurrentProcess();
TerminateProcess(hself, 0);
} }
...@@ -509,6 +513,8 @@ void MomentaMedia::ReadSettings() ...@@ -509,6 +513,8 @@ void MomentaMedia::ReadSettings()
FrameRate = settings.value("FRAME_RATE", "").toInt(); FrameRate = settings.value("FRAME_RATE", "").toInt();
if (FrameRate < 25) FrameRate = 25; if (FrameRate < 25) FrameRate = 25;
PrvwFlag = settings.value("PRVW_FLAG", "").toInt(); PrvwFlag = settings.value("PRVW_FLAG", "").toInt();
OutputPlayMode = settings.value("OUTPUT_PLAY_MODE", "").toInt();
//qDebug() << "deleyTime=" << deleyTime << endl; //qDebug() << "deleyTime=" << deleyTime << endl;
settings.endGroup(); settings.endGroup();
} }
\ No newline at end of file
...@@ -403,6 +403,7 @@ void ProcessThread::WorkCutImage(std::shared_ptr<Image>& pImage, RoiMessage& roi ...@@ -403,6 +403,7 @@ void ProcessThread::WorkCutImage(std::shared_ptr<Image>& pImage, RoiMessage& roi
roi.X(), roi.Y(), 1920, 1080, roi.Width(), roi.Height(), roi.X(), roi.Y(), 1920, 1080, roi.Width(), roi.Height(),
libyuv::kRotate90, libyuv::FOURCC_ARGB); libyuv::kRotate90, libyuv::FOURCC_ARGB);
uint8_t* buff2 = new uint8_t[1440 * 1080 << 2]; uint8_t* buff2 = new uint8_t[1440 * 1080 << 2];
libyuv::ARGBScale(buff1, (roi.Height() << 2), roi.Height(), roi.Width(), libyuv::ARGBScale(buff1, (roi.Height() << 2), roi.Height(), roi.Width(),
buff2, 1440 << 2, 1440, 1080, libyuv::FilterMode::kFilterNone); buff2, 1440 << 2, 1440, 1080, libyuv::FilterMode::kFilterNone);
......
[DELEYTIME] [DELEYTIME]
DELEY_TIME=10 DELEY_TIME=2
\ No newline at end of file FRAME_RATE=25
PRVW_FLAG=0
OUTPUT_PLAY_MODE=0
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
[DELEYTIME] [DELEYTIME]
DELEY_TIME=5 DELEY_TIME=2
FRAME_RATE=25 FRAME_RATE=25
PRVW_FLAG=0 PRVW_FLAG=1
OUTPUT_PLAY_MODE=0
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment