decklink-device-instance.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  1. #include "decklink-device-instance.hpp"
  2. #include "audio-repack.hpp"
  3. #include "DecklinkInput.hpp"
  4. #include "DecklinkOutput.hpp"
  5. #include <util/platform.h>
  6. #include <util/threading.h>
  7. #include <util/util_uint64.h>
  8. #include <sstream>
  9. #include <iomanip>
  10. #include <algorithm>
  11. #include "OBSVideoFrame.h"
  12. #include <caption/caption.h>
  13. #include <util/bitstream.h>
  14. static inline enum video_format ConvertPixelFormat(BMDPixelFormat format)
  15. {
  16. switch (format) {
  17. case bmdFormat8BitBGRA:
  18. return VIDEO_FORMAT_BGRX;
  19. case bmdFormat10BitYUV:
  20. return VIDEO_FORMAT_V210;
  21. default:
  22. case bmdFormat8BitYUV:
  23. return VIDEO_FORMAT_UYVY;
  24. }
  25. }
  26. static inline int ConvertChannelFormat(speaker_layout format)
  27. {
  28. switch (format) {
  29. case SPEAKERS_2POINT1:
  30. case SPEAKERS_4POINT0:
  31. case SPEAKERS_4POINT1:
  32. case SPEAKERS_5POINT1:
  33. case SPEAKERS_7POINT1:
  34. return 8;
  35. default:
  36. case SPEAKERS_STEREO:
  37. return 2;
  38. }
  39. }
  40. static inline audio_repack_mode_t ConvertRepackFormat(speaker_layout format,
  41. bool swap)
  42. {
  43. switch (format) {
  44. case SPEAKERS_2POINT1:
  45. return repack_mode_8to3ch;
  46. case SPEAKERS_4POINT0:
  47. return repack_mode_8to4ch;
  48. case SPEAKERS_4POINT1:
  49. return swap ? repack_mode_8to5ch_swap : repack_mode_8to5ch;
  50. case SPEAKERS_5POINT1:
  51. return swap ? repack_mode_8to6ch_swap : repack_mode_8to6ch;
  52. case SPEAKERS_7POINT1:
  53. return swap ? repack_mode_8ch_swap : repack_mode_8ch;
  54. default:
  55. assert(false && "No repack requested");
  56. return (audio_repack_mode_t)-1;
  57. }
  58. }
  59. DeckLinkDeviceInstance::DeckLinkDeviceInstance(DecklinkBase *decklink_,
  60. DeckLinkDevice *device_)
  61. : currentFrame(),
  62. currentPacket(),
  63. currentCaptions(),
  64. decklink(decklink_),
  65. device(device_)
  66. {
  67. currentPacket.samples_per_sec = 48000;
  68. currentPacket.speakers = SPEAKERS_STEREO;
  69. currentPacket.format = AUDIO_FORMAT_16BIT;
  70. }
  71. DeckLinkDeviceInstance::~DeckLinkDeviceInstance()
  72. {
  73. if (convertFrame) {
  74. delete convertFrame;
  75. }
  76. }
  77. void DeckLinkDeviceInstance::HandleAudioPacket(
  78. IDeckLinkAudioInputPacket *audioPacket, const uint64_t timestamp)
  79. {
  80. if (audioPacket == nullptr)
  81. return;
  82. void *bytes;
  83. if (audioPacket->GetBytes(&bytes) != S_OK) {
  84. LOG(LOG_WARNING, "Failed to get audio packet data");
  85. return;
  86. }
  87. const uint32_t frameCount =
  88. (uint32_t)audioPacket->GetSampleFrameCount();
  89. currentPacket.frames = frameCount;
  90. currentPacket.timestamp = timestamp;
  91. if (decklink && !static_cast<DeckLinkInput *>(decklink)->buffering) {
  92. currentPacket.timestamp = os_gettime_ns();
  93. currentPacket.timestamp -=
  94. util_mul_div64(frameCount, 1000000000ULL,
  95. currentPacket.samples_per_sec);
  96. }
  97. int maxdevicechannel = device->GetMaxChannel();
  98. if (channelFormat != SPEAKERS_UNKNOWN &&
  99. channelFormat != SPEAKERS_MONO &&
  100. channelFormat != SPEAKERS_STEREO &&
  101. (channelFormat != SPEAKERS_7POINT1 ||
  102. static_cast<DeckLinkInput *>(decklink)->swap) &&
  103. maxdevicechannel >= 8) {
  104. if (audioRepacker->repack((uint8_t *)bytes, frameCount) < 0) {
  105. LOG(LOG_ERROR, "Failed to convert audio packet data");
  106. return;
  107. }
  108. currentPacket.data[0] = (*audioRepacker)->packet_buffer;
  109. } else {
  110. currentPacket.data[0] = (uint8_t *)bytes;
  111. }
  112. nextAudioTS = timestamp +
  113. util_mul_div64(frameCount, 1000000000ULL, 48000ULL) + 1;
  114. obs_source_output_audio(
  115. static_cast<DeckLinkInput *>(decklink)->GetSource(),
  116. &currentPacket);
  117. }
  118. void DeckLinkDeviceInstance::HandleVideoFrame(
  119. IDeckLinkVideoInputFrame *videoFrame, const uint64_t timestamp)
  120. {
  121. if (videoFrame == nullptr)
  122. return;
  123. ComPtr<IDeckLinkVideoFrameAncillaryPackets> packets;
  124. if (videoFrame->QueryInterface(IID_IDeckLinkVideoFrameAncillaryPackets,
  125. (void **)&packets) == S_OK) {
  126. ComPtr<IDeckLinkAncillaryPacketIterator> iterator;
  127. packets->GetPacketIterator(&iterator);
  128. ComPtr<IDeckLinkAncillaryPacket> packet;
  129. iterator->Next(&packet);
  130. if (packet) {
  131. auto did = packet->GetDID();
  132. auto sdid = packet->GetSDID();
  133. // Caption data
  134. if (did == 0x61 && sdid == 0x01) {
  135. this->HandleCaptionPacket(packet, timestamp);
  136. }
  137. }
  138. }
  139. ComPtr<IDeckLinkVideoFrame> frame;
  140. if (videoFrame->GetPixelFormat() != convertFrame->GetPixelFormat()) {
  141. ComPtr<IDeckLinkVideoConversion> frameConverter;
  142. frameConverter.Set(CreateVideoConversionInstance());
  143. frameConverter->ConvertFrame(videoFrame, convertFrame);
  144. frame = convertFrame;
  145. } else {
  146. frame = videoFrame;
  147. }
  148. void *bytes;
  149. if (frame->GetBytes(&bytes) != S_OK) {
  150. LOG(LOG_WARNING, "Failed to get video frame data");
  151. return;
  152. }
  153. currentFrame.data[0] = (uint8_t *)bytes;
  154. currentFrame.linesize[0] = (uint32_t)frame->GetRowBytes();
  155. currentFrame.width = (uint32_t)frame->GetWidth();
  156. currentFrame.height = (uint32_t)frame->GetHeight();
  157. currentFrame.timestamp = timestamp;
  158. if (currentFrame.width == 0 || currentFrame.height == 0)
  159. return;
  160. enum video_trc trc = VIDEO_TRC_DEFAULT;
  161. if (frame->GetFlags() & bmdFrameContainsHDRMetadata) {
  162. ComPtr<IDeckLinkVideoFrameMetadataExtensions> metadata;
  163. if (SUCCEEDED(videoFrame->QueryInterface(
  164. IID_IDeckLinkVideoFrameMetadataExtensions,
  165. (void **)&metadata))) {
  166. int64_t range;
  167. if (SUCCEEDED(metadata->GetInt(
  168. bmdDeckLinkFrameMetadataHDRElectroOpticalTransferFunc,
  169. &range))) {
  170. switch (range) {
  171. case 2:
  172. trc = VIDEO_TRC_PQ;
  173. break;
  174. case 3:
  175. trc = VIDEO_TRC_HLG;
  176. break;
  177. default:
  178. trc = VIDEO_TRC_DEFAULT;
  179. break;
  180. }
  181. }
  182. }
  183. }
  184. currentFrame.trc = trc;
  185. obs_source_output_video2(
  186. static_cast<DeckLinkInput *>(decklink)->GetSource(),
  187. &currentFrame);
  188. }
  189. void DeckLinkDeviceInstance::HandleCaptionPacket(
  190. IDeckLinkAncillaryPacket *packet, const uint64_t timestamp)
  191. {
  192. const void *data;
  193. uint32_t size;
  194. packet->GetBytes(bmdAncillaryPacketFormatUInt8, &data, &size);
  195. auto anc = (uint8_t *)data;
  196. struct bitstream_reader reader;
  197. bitstream_reader_init(&reader, anc, size);
  198. // header1
  199. bitstream_reader_r8(&reader);
  200. // header2
  201. bitstream_reader_r8(&reader);
  202. // length
  203. bitstream_reader_r8(&reader);
  204. // frameRate
  205. bitstream_reader_read_bits(&reader, 4);
  206. //reserved
  207. bitstream_reader_read_bits(&reader, 4);
  208. auto cdp_timecode_added = bitstream_reader_read_bits(&reader, 1);
  209. // cdp_data_block_added
  210. bitstream_reader_read_bits(&reader, 1);
  211. // cdp_service_info_added
  212. bitstream_reader_read_bits(&reader, 1);
  213. // cdp_service_info_start
  214. bitstream_reader_read_bits(&reader, 1);
  215. // cdp_service_info_changed
  216. bitstream_reader_read_bits(&reader, 1);
  217. // cdp_service_info_end
  218. bitstream_reader_read_bits(&reader, 1);
  219. auto cdp_contains_captions = bitstream_reader_read_bits(&reader, 1);
  220. //reserved
  221. bitstream_reader_read_bits(&reader, 1);
  222. // cdp_counter
  223. bitstream_reader_r8(&reader);
  224. // cdp_counter2
  225. bitstream_reader_r8(&reader);
  226. if (cdp_timecode_added) {
  227. // timecodeSectionID
  228. bitstream_reader_r8(&reader);
  229. //reserved
  230. bitstream_reader_read_bits(&reader, 2);
  231. bitstream_reader_read_bits(&reader, 2);
  232. bitstream_reader_read_bits(&reader, 4);
  233. // reserved
  234. bitstream_reader_read_bits(&reader, 1);
  235. bitstream_reader_read_bits(&reader, 3);
  236. bitstream_reader_read_bits(&reader, 4);
  237. bitstream_reader_read_bits(&reader, 1);
  238. bitstream_reader_read_bits(&reader, 3);
  239. bitstream_reader_read_bits(&reader, 4);
  240. bitstream_reader_read_bits(&reader, 1);
  241. bitstream_reader_read_bits(&reader, 1);
  242. bitstream_reader_read_bits(&reader, 3);
  243. bitstream_reader_read_bits(&reader, 4);
  244. }
  245. if (cdp_contains_captions) {
  246. // cdp_data_section
  247. bitstream_reader_r8(&reader);
  248. //process_em_data_flag
  249. bitstream_reader_read_bits(&reader, 1);
  250. // process_cc_data_flag
  251. bitstream_reader_read_bits(&reader, 1);
  252. //additional_data_flag
  253. bitstream_reader_read_bits(&reader, 1);
  254. auto cc_count = bitstream_reader_read_bits(&reader, 5);
  255. auto *outData =
  256. (uint8_t *)bzalloc(sizeof(uint8_t) * cc_count * 3);
  257. memcpy(outData, anc + reader.pos, cc_count * 3);
  258. currentCaptions.data = outData;
  259. currentCaptions.timestamp = timestamp;
  260. currentCaptions.packets = cc_count;
  261. obs_source_output_cea708(
  262. static_cast<DeckLinkInput *>(decklink)->GetSource(),
  263. &currentCaptions);
  264. bfree(outData);
  265. }
  266. }
  267. void DeckLinkDeviceInstance::FinalizeStream()
  268. {
  269. input->SetCallback(nullptr);
  270. input->DisableVideoInput();
  271. if (channelFormat != SPEAKERS_UNKNOWN)
  272. input->DisableAudioInput();
  273. if (audioRepacker != nullptr) {
  274. delete audioRepacker;
  275. audioRepacker = nullptr;
  276. }
  277. mode = nullptr;
  278. }
  279. //#define LOG_SETUP_VIDEO_FORMAT 1
  280. void DeckLinkDeviceInstance::SetupVideoFormat(DeckLinkDeviceMode *mode_)
  281. {
  282. if (mode_ == nullptr)
  283. return;
  284. const enum video_format format = ConvertPixelFormat(pixelFormat);
  285. currentFrame.format = format;
  286. colorSpace = static_cast<DeckLinkInput *>(decklink)->GetColorSpace();
  287. if (colorSpace == VIDEO_CS_DEFAULT) {
  288. const BMDDisplayModeFlags flags = mode_->GetDisplayModeFlags();
  289. /* 2020 wasn't set when testing but maybe it will be someday */
  290. if (flags & bmdDisplayModeColorspaceRec2020)
  291. activeColorSpace = VIDEO_CS_2100_PQ;
  292. else if (flags & bmdDisplayModeColorspaceRec709)
  293. activeColorSpace = VIDEO_CS_709;
  294. else if (flags & bmdDisplayModeColorspaceRec601)
  295. activeColorSpace = VIDEO_CS_601;
  296. else
  297. activeColorSpace = VIDEO_CS_DEFAULT;
  298. } else {
  299. activeColorSpace = colorSpace;
  300. }
  301. colorRange = static_cast<DeckLinkInput *>(decklink)->GetColorRange();
  302. currentFrame.range = colorRange;
  303. video_format_get_parameters_for_format(
  304. activeColorSpace, colorRange, format, currentFrame.color_matrix,
  305. currentFrame.color_range_min, currentFrame.color_range_max);
  306. delete convertFrame;
  307. BMDPixelFormat convertFormat;
  308. switch (pixelFormat) {
  309. case bmdFormat8BitBGRA:
  310. case bmdFormat10BitYUV:
  311. convertFormat = pixelFormat;
  312. break;
  313. default:
  314. case bmdFormat8BitYUV:;
  315. convertFormat = bmdFormat8BitYUV;
  316. break;
  317. }
  318. convertFrame = new OBSVideoFrame(mode_->GetWidth(), mode_->GetHeight(),
  319. convertFormat);
  320. #ifdef LOG_SETUP_VIDEO_FORMAT
  321. LOG(LOG_INFO, "Setup video format: %s, %s, %s",
  322. pixelFormat == bmdFormat8BitYUV ? "YUV" : "RGB",
  323. activeColorSpace == VIDEO_CS_601 ? "BT.601" : "BT.709",
  324. colorRange == VIDEO_RANGE_FULL ? "full" : "limited");
  325. #endif
  326. }
  327. bool DeckLinkDeviceInstance::StartCapture(DeckLinkDeviceMode *mode_,
  328. bool allow10Bit_,
  329. BMDVideoConnection bmdVideoConnection,
  330. BMDAudioConnection bmdAudioConnection)
  331. {
  332. if (mode != nullptr)
  333. return false;
  334. if (mode_ == nullptr)
  335. return false;
  336. LOG(LOG_INFO, "Starting capture...");
  337. if (!device->GetInput(&input))
  338. return false;
  339. HRESULT result = input->QueryInterface(IID_IDeckLinkConfiguration,
  340. (void **)&deckLinkConfiguration);
  341. if (result != S_OK) {
  342. LOG(LOG_ERROR,
  343. "Could not obtain the IDeckLinkConfiguration interface: %08x\n",
  344. result);
  345. } else {
  346. if (bmdVideoConnection > 0) {
  347. result = deckLinkConfiguration->SetInt(
  348. bmdDeckLinkConfigVideoInputConnection,
  349. bmdVideoConnection);
  350. if (result != S_OK) {
  351. LOG(LOG_ERROR,
  352. "Couldn't set input video port to %d\n\n",
  353. bmdVideoConnection);
  354. }
  355. }
  356. if (bmdAudioConnection > 0) {
  357. result = deckLinkConfiguration->SetInt(
  358. bmdDeckLinkConfigAudioInputConnection,
  359. bmdAudioConnection);
  360. if (result != S_OK) {
  361. LOG(LOG_ERROR,
  362. "Couldn't set input audio port to %d\n\n",
  363. bmdVideoConnection);
  364. }
  365. }
  366. }
  367. videoConnection = bmdVideoConnection;
  368. audioConnection = bmdAudioConnection;
  369. BMDVideoInputFlags flags;
  370. bool isauto = mode_->GetName() == "Auto";
  371. if (isauto) {
  372. displayMode = bmdModeNTSC;
  373. if (allow10Bit_) {
  374. pixelFormat = bmdFormat10BitYUV;
  375. } else {
  376. pixelFormat = bmdFormat8BitYUV;
  377. }
  378. flags = bmdVideoInputEnableFormatDetection;
  379. } else {
  380. displayMode = mode_->GetDisplayMode();
  381. pixelFormat =
  382. static_cast<DeckLinkInput *>(decklink)->GetPixelFormat();
  383. flags = bmdVideoInputFlagDefault;
  384. }
  385. allow10Bit = allow10Bit_;
  386. const HRESULT videoResult =
  387. input->EnableVideoInput(displayMode, pixelFormat, flags);
  388. if (videoResult != S_OK) {
  389. LOG(LOG_ERROR, "Failed to enable video input");
  390. return false;
  391. }
  392. SetupVideoFormat(mode_);
  393. channelFormat =
  394. static_cast<DeckLinkInput *>(decklink)->GetChannelFormat();
  395. currentPacket.speakers = channelFormat;
  396. swap = static_cast<DeckLinkInput *>(decklink)->swap;
  397. int maxdevicechannel = device->GetMaxChannel();
  398. if (channelFormat != SPEAKERS_UNKNOWN) {
  399. const int channel = ConvertChannelFormat(channelFormat);
  400. const HRESULT audioResult = input->EnableAudioInput(
  401. bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger,
  402. channel);
  403. if (audioResult != S_OK)
  404. LOG(LOG_WARNING,
  405. "Failed to enable audio input; continuing...");
  406. if (channelFormat != SPEAKERS_UNKNOWN &&
  407. channelFormat != SPEAKERS_MONO &&
  408. channelFormat != SPEAKERS_STEREO &&
  409. (channelFormat != SPEAKERS_7POINT1 || swap) &&
  410. maxdevicechannel >= 8) {
  411. const audio_repack_mode_t repack_mode =
  412. ConvertRepackFormat(channelFormat, swap);
  413. audioRepacker = new AudioRepacker(repack_mode);
  414. }
  415. }
  416. if (input->SetCallback(this) != S_OK) {
  417. LOG(LOG_ERROR, "Failed to set callback");
  418. FinalizeStream();
  419. return false;
  420. }
  421. if (input->StartStreams() != S_OK) {
  422. LOG(LOG_ERROR, "Failed to start streams");
  423. FinalizeStream();
  424. return false;
  425. }
  426. mode = mode_;
  427. return true;
  428. }
  429. bool DeckLinkDeviceInstance::StopCapture(void)
  430. {
  431. if (mode == nullptr || input == nullptr)
  432. return false;
  433. LOG(LOG_INFO, "Stopping capture of '%s'...",
  434. GetDevice()->GetDisplayName().c_str());
  435. input->StopStreams();
  436. FinalizeStream();
  437. return true;
  438. }
  439. bool DeckLinkDeviceInstance::StartOutput(DeckLinkDeviceMode *mode_)
  440. {
  441. if (mode != nullptr)
  442. return false;
  443. if (mode_ == nullptr)
  444. return false;
  445. LOG(LOG_INFO, "Starting output...");
  446. if (!device->GetOutput(&output))
  447. return false;
  448. const HRESULT videoResult = output->EnableVideoOutput(
  449. mode_->GetDisplayMode(), bmdVideoOutputFlagDefault);
  450. if (videoResult != S_OK) {
  451. LOG(LOG_ERROR, "Failed to enable video output");
  452. return false;
  453. }
  454. const HRESULT audioResult = output->EnableAudioOutput(
  455. bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger, 2,
  456. bmdAudioOutputStreamTimestamped);
  457. if (audioResult != S_OK) {
  458. LOG(LOG_ERROR, "Failed to enable audio output");
  459. return false;
  460. }
  461. mode = mode_;
  462. ComPtr<IDeckLinkKeyer> deckLinkKeyer;
  463. if (device->GetKeyer(&deckLinkKeyer)) {
  464. const int keyerMode = device->GetKeyerMode();
  465. if (keyerMode) {
  466. deckLinkKeyer->Enable(keyerMode == 1);
  467. deckLinkKeyer->SetLevel(255);
  468. } else {
  469. deckLinkKeyer->Disable();
  470. }
  471. }
  472. auto decklinkOutput = dynamic_cast<DeckLinkOutput *>(decklink);
  473. if (decklinkOutput == nullptr)
  474. return false;
  475. HRESULT result;
  476. result = output->CreateVideoFrame(
  477. decklinkOutput->GetWidth(), decklinkOutput->GetHeight(),
  478. decklinkOutput->GetWidth() * 4, bmdFormat8BitBGRA,
  479. bmdFrameFlagDefault, &decklinkOutputFrame);
  480. if (result != S_OK) {
  481. blog(LOG_ERROR, "failed to make frame 0x%X", result);
  482. return false;
  483. }
  484. return true;
  485. }
  486. bool DeckLinkDeviceInstance::StopOutput()
  487. {
  488. if (mode == nullptr || output == nullptr)
  489. return false;
  490. LOG(LOG_INFO, "Stopping output of '%s'...",
  491. GetDevice()->GetDisplayName().c_str());
  492. output->DisableVideoOutput();
  493. output->DisableAudioOutput();
  494. decklinkOutputFrame.Clear();
  495. return true;
  496. }
  497. void DeckLinkDeviceInstance::DisplayVideoFrame(video_data *frame)
  498. {
  499. auto decklinkOutput = dynamic_cast<DeckLinkOutput *>(decklink);
  500. if (decklinkOutput == nullptr)
  501. return;
  502. uint8_t *destData;
  503. decklinkOutputFrame->GetBytes((void **)&destData);
  504. uint8_t *outData = frame->data[0];
  505. std::copy(outData,
  506. outData + (decklinkOutput->GetWidth() *
  507. decklinkOutput->GetHeight() * 4),
  508. destData);
  509. output->DisplayVideoFrameSync(decklinkOutputFrame);
  510. }
  511. void DeckLinkDeviceInstance::WriteAudio(audio_data *frames)
  512. {
  513. uint32_t sampleFramesWritten;
  514. output->WriteAudioSamplesSync(frames->data[0], frames->frames,
  515. &sampleFramesWritten);
  516. }
  517. #define TIME_BASE 1000000000
  518. HRESULT STDMETHODCALLTYPE DeckLinkDeviceInstance::VideoInputFrameArrived(
  519. IDeckLinkVideoInputFrame *videoFrame,
  520. IDeckLinkAudioInputPacket *audioPacket)
  521. {
  522. BMDTimeValue videoTS = 0;
  523. BMDTimeValue videoDur = 0;
  524. BMDTimeValue audioTS = 0;
  525. if (videoFrame) {
  526. videoFrame->GetStreamTime(&videoTS, &videoDur, TIME_BASE);
  527. lastVideoTS = (uint64_t)videoTS;
  528. }
  529. if (audioPacket) {
  530. BMDTimeValue newAudioTS = 0;
  531. int64_t diff;
  532. audioPacket->GetPacketTime(&newAudioTS, TIME_BASE);
  533. audioTS = newAudioTS + audioOffset;
  534. diff = (int64_t)audioTS - (int64_t)nextAudioTS;
  535. if (diff > 10000000LL) {
  536. audioOffset -= diff;
  537. audioTS = newAudioTS + audioOffset;
  538. } else if (diff < -1000000) {
  539. audioOffset = 0;
  540. audioTS = newAudioTS;
  541. }
  542. }
  543. if (videoFrame && videoTS >= 0)
  544. HandleVideoFrame(videoFrame, (uint64_t)videoTS);
  545. if (audioPacket && audioTS >= 0)
  546. HandleAudioPacket(audioPacket, (uint64_t)audioTS);
  547. return S_OK;
  548. }
  549. HRESULT STDMETHODCALLTYPE DeckLinkDeviceInstance::VideoInputFormatChanged(
  550. BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode *newMode,
  551. BMDDetectedVideoInputFormatFlags detectedSignalFlags)
  552. {
  553. if (events & bmdVideoInputColorspaceChanged) {
  554. if (detectedSignalFlags & bmdDetectedVideoInputRGB444) {
  555. pixelFormat = bmdFormat8BitBGRA;
  556. }
  557. if (detectedSignalFlags & bmdDetectedVideoInputYCbCr422) {
  558. if (detectedSignalFlags &
  559. bmdDetectedVideoInput10BitDepth) {
  560. if (allow10Bit) {
  561. pixelFormat = bmdFormat10BitYUV;
  562. } else {
  563. pixelFormat = bmdFormat8BitYUV;
  564. }
  565. }
  566. if (detectedSignalFlags &
  567. bmdDetectedVideoInput8BitDepth) {
  568. pixelFormat = bmdFormat8BitYUV;
  569. }
  570. }
  571. }
  572. if (events & bmdVideoInputDisplayModeChanged) {
  573. input->PauseStreams();
  574. mode->SetMode(newMode);
  575. displayMode = mode->GetDisplayMode();
  576. const HRESULT videoResult = input->EnableVideoInput(
  577. displayMode, pixelFormat,
  578. bmdVideoInputEnableFormatDetection);
  579. if (videoResult != S_OK) {
  580. LOG(LOG_ERROR, "Failed to enable video input");
  581. input->StopStreams();
  582. FinalizeStream();
  583. return E_FAIL;
  584. }
  585. SetupVideoFormat(mode);
  586. input->FlushStreams();
  587. input->StartStreams();
  588. }
  589. return S_OK;
  590. }
  591. ULONG STDMETHODCALLTYPE DeckLinkDeviceInstance::AddRef(void)
  592. {
  593. return os_atomic_inc_long(&refCount);
  594. }
  595. HRESULT STDMETHODCALLTYPE DeckLinkDeviceInstance::QueryInterface(REFIID iid,
  596. LPVOID *ppv)
  597. {
  598. HRESULT result = E_NOINTERFACE;
  599. *ppv = nullptr;
  600. CFUUIDBytes unknown = CFUUIDGetUUIDBytes(IUnknownUUID);
  601. if (memcmp(&iid, &unknown, sizeof(REFIID)) == 0) {
  602. *ppv = this;
  603. AddRef();
  604. result = S_OK;
  605. } else if (memcmp(&iid, &IID_IDeckLinkNotificationCallback,
  606. sizeof(REFIID)) == 0) {
  607. *ppv = (IDeckLinkNotificationCallback *)this;
  608. AddRef();
  609. result = S_OK;
  610. }
  611. return result;
  612. }
  613. ULONG STDMETHODCALLTYPE DeckLinkDeviceInstance::Release(void)
  614. {
  615. const long newRefCount = os_atomic_dec_long(&refCount);
  616. if (newRefCount == 0) {
  617. delete this;
  618. return 0;
  619. }
  620. return newRefCount;
  621. }