AJA NTV2 SDK  18.0.0.2122
NTV2 SDK 18.0.0.2122
main.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MIT */
10 // Includes
11 #include "ntv2fieldburn.h"
12 #include <signal.h>
13 #include <iostream>
14 #include <iomanip>
15 
16 using namespace std;
17 
18 
19 // Globals
20 static bool gGlobalQuit (false);
21 
22 
23 static void SignalHandler (int inSignal)
24 {
25  (void) inSignal;
26  gGlobalQuit = true;
27 }
28 
29 
30 int main (int argc, const char ** argv)
31 {
32  char * pDeviceSpec (AJA_NULL); // Which device to use
33  char * pInputSrcSpec (AJA_NULL); // SDI source spec
34  char * pPixelFormat (AJA_NULL); // Pixel format spec
35  int doMultiFormat (0); // MultiFormat mode?
36  int showVersion (0); // Show version?
37  int noAudio (0); // Disable audio?
38  int noFieldMode (0); // Disable AutoCirculate Field Mode?
40 
41  // Command line option descriptions:
42  const struct poptOption optionsTable [] =
43  {
44  {"version", 0, POPT_ARG_NONE, &showVersion, 0, "show version & exit", AJA_NULL },
45  {"device", 'd', POPT_ARG_STRING, &pDeviceSpec, 0, "device to use", "index#, serial#, or model" },
46  {"multiFormat", 'm', POPT_ARG_NONE, &doMultiFormat, 0, "use multi-format/channel", AJA_NULL },
47  {"pixelFormat", 'p', POPT_ARG_STRING, &pPixelFormat, 0, "pixel format to use", "'?' or 'list' to list" },
48  {"input", 'i', POPT_ARG_STRING, &pInputSrcSpec, 0, "SDI input to use", "1-8, ?=list" },
49  {"noaudio", 0, POPT_ARG_NONE, &noAudio, 0, "disable audio?", AJA_NULL },
50  {"nofield", 0, POPT_ARG_NONE, &noFieldMode, 0, "disables field mode", AJA_NULL },
53  };
54  CNTV2DemoCommon::Popt popt(argc, argv, optionsTable);
55  if (!popt)
56  {cerr << "## ERROR: " << popt.errorStr() << endl; return 2;}
57  if (showVersion)
58  {cout << argv[0] << ", NTV2 SDK " << ::NTV2Version() << endl; return 0;}
59 
60  // Device
61  const string deviceSpec (pDeviceSpec ? pDeviceSpec : "0");
62  if (!CNTV2DemoCommon::IsValidDevice(deviceSpec))
63  return 1;
64 
65  BurnConfig config(deviceSpec);
66 
67  // Input source
68  const string inputSourceStr (pInputSrcSpec ? CNTV2DemoCommon::ToLower(string(pInputSrcSpec)) : "");
69  const string legalSources (CNTV2DemoCommon::GetInputSourceStrings(NTV2_IOKINDS_ALL, pDeviceSpec ? deviceSpec : ""));
70  config.fInputSource = CNTV2DemoCommon::GetInputSourceFromString(inputSourceStr, NTV2_IOKINDS_ALL, pDeviceSpec ? deviceSpec : "");
71  if (inputSourceStr == "?" || inputSourceStr == "list")
72  {cout << legalSources << endl; return 0;}
73  if (!inputSourceStr.empty() && !NTV2_IS_VALID_INPUT_SOURCE(config.fInputSource))
74  {cerr << "## ERROR: Input source '" << inputSourceStr << "' not one of:" << endl << legalSources << endl; return 1;}
75 
76  // Pixel Format
77  const string pixelFormatStr (pPixelFormat ? pPixelFormat : "");
78  config.fPixelFormat = pixelFormatStr.empty() ? NTV2_FBF_8BIT_YCBCR : CNTV2DemoCommon::GetPixelFormatFromString(pixelFormatStr);
79  if (pixelFormatStr == "?" || pixelFormatStr == "list")
80  {cout << CNTV2DemoCommon::GetPixelFormatStrings(PIXEL_FORMATS_ALL, pDeviceSpec ? deviceSpec : "") << endl; return 0;}
81  else if (!pixelFormatStr.empty() && !NTV2_IS_VALID_FRAME_BUFFER_FORMAT(config.fPixelFormat))
82  {
83  cerr << "## ERROR: Invalid '--pixelFormat' value '" << pixelFormatStr << "' -- expected values:" << endl
85  return 2;
86  }
87 
88  config.fDoMultiFormat = doMultiFormat ? true : false;
89  config.fSuppressAudio = noAudio ? true : false;
90  config.fIsFieldMode = noFieldMode ? false : true;
92 
93  // Instantiate the NTV2FieldBurn object...
94  NTV2FieldBurn burner (config);
95 
96  ::signal (SIGINT, SignalHandler);
97  #if defined (AJAMac)
98  ::signal (SIGHUP, SignalHandler);
99  ::signal (SIGQUIT, SignalHandler);
100  #endif
101  const string hdg1 (" Capture Playout Capture Playout"),
102  hdg2a(" Fields Fields Fields Buffer Buffer"),
103  hdg2b(" Frames Frames Frames Buffer Buffer"),
104  hdg3 ("Processed Dropped Dropped Level Level"),
105  hdg2 (noFieldMode ? hdg2b : hdg2a);
106 
107  // Initialize the NTV2FieldBurn instance...
108  AJAStatus status (burner.Init());
109  if (AJA_FAILURE (status))
110  {cerr << "## ERROR: Initialization failed, status=" << status << endl; return 4;}
111 
112  // Start the burner's capture and playout threads...
113  burner.Run();
114 
115  // Loop until told to stop...
116  cout << hdg1 << endl << hdg2 << endl << hdg3 << endl;
117  do
118  {
119  ULWord totalFrames(0), inputDrops(0), outputDrops(0), inputBufferLevel(0), outputBufferLevel(0);
120  burner.GetStatus (totalFrames, inputDrops, outputDrops, inputBufferLevel, outputBufferLevel);
121  cout << setw(9) << totalFrames << setw(9) << inputDrops << setw(9) << outputDrops
122  << setw(9) << inputBufferLevel << setw(9) << outputBufferLevel << "\r" << flush;
123  AJATime::Sleep(2000);
124  } while (!gGlobalQuit); // loop until signaled
125 
126  cout << endl;
127  return 0;
128 
129 } // main
NTV2Channel NTV2InputSourceToChannel(const NTV2InputSource inInputSource)
Converts a given NTV2InputSource to its equivalent NTV2Channel value.
Definition: ntv2utils.cpp:5047
Header file for the NTV2FieldBurn demonstration class.
int main(int argc, const char **argv)
Definition: main.cpp:30
AJAStatus
Definition: types.h:380
virtual AJAStatus Run(void)
Runs me.
static AJAStatus Open(bool incrementRefCount=false)
Definition: debug.cpp:44
#define AJA_FAILURE(_status_)
Definition: types.h:373
static bool gGlobalQuit((0))
Set this "true" to exit gracefully.
static std::string GetInputSourceStrings(const NTV2IOKinds inKinds=NTV2_IOKINDS_ALL, const std::string inDevSpec=std::string())
bool fSuppressAudio
If true, suppress audio; otherwise include audio.
static std::string GetPixelFormatStrings(const NTV2PixelFormatKinds inKinds=PIXEL_FORMATS_ALL, const std::string inDevSpec=std::string())
Specifies any/all input/output kinds.
Definition: ntv2enums.h:1295
Definition: json.hpp:5362
void SignalHandler(int inSignal)
Definition: main.cpp:26
#define false
uint32_t ULWord
Definition: ajatypes.h:223
#define POPT_AUTOHELP
Definition: options_popt.h:227
NTV2TCIndex NTV2ChannelToTimecodeIndex(const NTV2Channel inChannel, const bool inEmbeddedLTC=false, const bool inIsF2=false)
Converts the given NTV2Channel value into the equivalent NTV2TCIndex value.
Definition: ntv2utils.cpp:4962
NTV2PixelFormat fPixelFormat
The pixel format to use.
#define true
std::string NTV2Version(const bool inDetailed=false)
Definition: ntv2version.cpp:41
virtual AJAStatus Init(void)
Initializes me and prepares me to Run.
bool fIsFieldMode
True if Field Mode, otherwise Frame Mode.
#define AJA_NULL
Definition: ajatypes.h:167
static void Sleep(const int32_t inMilliseconds)
Suspends execution of the current thread for a given number of milliseconds.
Definition: systemtime.cpp:284
static std::string ToLower(const std::string &inStr)
Returns the given string after converting it to lower case.
virtual const std::string & errorStr(void) const
I capture individual fields from an interlaced video signal provided to an SDI input. Each frame is captured as two fields in separate host buffers. I burn F1 timecode into the top of F1, and F2 timecode into the bottom half of F2. Then I reassemble both fields and play them through an output of the same device, with a 7-frame latency (by default). I make use of the AJACircularBuffer, which simplifies implementing a producer/consumer model, in which a "consumer" thread delivers burned-in frames to the AJA device output, and a "producer" thread captures raw frames from the AJA device input. I also demonstrate how to detect if an SDI input has embedded timecode, and if so, how AutoCirculate makes it available. I also show how to embed timecode into an SDI output signal using AutoCirculate during playout.
Definition: ntv2fieldburn.h:32
Configures an NTV2Burn or NTV2FieldBurn instance.
#define NTV2_IS_VALID_INPUT_SOURCE(_inpSrc_)
Definition: ntv2enums.h:1284
virtual void GetStatus(ULWord &outNumProcessed, ULWord &outCaptureDrops, ULWord &outPlayoutDrops, ULWord &outCaptureLevel, ULWord &outPlayoutLevel)
Provides status information about my input (capture) and output (playout) processes.
bool fDoMultiFormat
If true, enables device-sharing; otherwise takes exclusive control of the device. ...
#define POPT_TABLEEND
Definition: options_popt.h:222
static NTV2InputSource GetInputSourceFromString(const std::string &inStr, const NTV2IOKinds inKinds=NTV2_IOKINDS_ALL, const std::string inDevSpec=std::string())
Returns the NTV2InputSource that matches the given string.
static bool IsValidDevice(const std::string &inDeviceSpec)
NTV2TCIndex fTimecodeSource
Timecode source to use.
#define NTV2_IS_VALID_FRAME_BUFFER_FORMAT(__s__)
Definition: ntv2enums.h:263
#define POPT_ARG_STRING
Definition: options_popt.h:57
#define POPT_ARG_NONE
Definition: options_popt.h:56
static NTV2PixelFormat GetPixelFormatFromString(const std::string &inStr, const NTV2PixelFormatKinds inKinds=PIXEL_FORMATS_ALL, const std::string inDevSpec=std::string())
Returns the NTV2PixelFormat that matches the given string.
See 8-Bit YCbCr Format.
Definition: ntv2enums.h:223
NTV2InputSource fInputSource
The device input connector to use.