AJA NTV2 SDK  18.1.0.2262
NTV2 SDK 18.1.0.2262
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 (!popt.otherArgs().empty())
58  {cerr << "## WARNING: ignored argument(s): '" << aja::join(popt.otherArgs(), "', '") << "'" << endl; return 2;}
59  if (showVersion)
60  {cout << argv[0] << ", NTV2 SDK " << ::NTV2Version() << endl; return 0;}
61 
62  // Device
63  const string deviceSpec (pDeviceSpec ? pDeviceSpec : "0");
64  BurnConfig config(deviceSpec);
65 
66  // Input source
67  const string inputSourceStr (pInputSrcSpec ? CNTV2DemoCommon::ToLower(string(pInputSrcSpec)) : "");
68  const string legalSources (CNTV2DemoCommon::GetInputSourceStrings(NTV2_IOKINDS_ALL, pDeviceSpec ? deviceSpec : ""));
69  config.fInputSource = CNTV2DemoCommon::GetInputSourceFromString(inputSourceStr, NTV2_IOKINDS_ALL, pDeviceSpec ? deviceSpec : "");
70  if (inputSourceStr == "?" || inputSourceStr == "list")
71  {cout << legalSources << endl; return 0;}
72  if (!inputSourceStr.empty() && !NTV2_IS_VALID_INPUT_SOURCE(config.fInputSource))
73  {cerr << "## ERROR: Input source '" << inputSourceStr << "' not one of:" << endl << legalSources << endl; return 1;}
74 
75  // Pixel Format
76  const string pixelFormatStr (pPixelFormat ? pPixelFormat : "");
77  config.fPixelFormat = pixelFormatStr.empty() ? NTV2_FBF_8BIT_YCBCR : CNTV2DemoCommon::GetPixelFormatFromString(pixelFormatStr);
78  if (pixelFormatStr == "?" || pixelFormatStr == "list")
79  {cout << CNTV2DemoCommon::GetPixelFormatStrings(PIXEL_FORMATS_ALL, pDeviceSpec ? deviceSpec : "") << endl; return 0;}
80  else if (!pixelFormatStr.empty() && !NTV2_IS_VALID_FRAME_BUFFER_FORMAT(config.fPixelFormat))
81  {
82  cerr << "## ERROR: Invalid '--pixelFormat' value '" << pixelFormatStr << "' -- expected values:" << endl
84  return 2;
85  }
86 
87  config.fDoMultiFormat = doMultiFormat ? true : false;
88  config.fSuppressAudio = noAudio ? true : false;
89  config.fIsFieldMode = noFieldMode ? false : true;
91 
92  { // Instantiate and initialize the NTV2FieldBurn object...
93  NTV2FieldBurn burner (config);
94 
95  ::signal (SIGINT, SignalHandler);
96  #if defined (AJAMac)
97  ::signal (SIGHUP, SignalHandler);
98  ::signal (SIGQUIT, SignalHandler);
99  #endif
100  const string hdg1 (" Capture Playout Capture Playout"),
101  hdg2a(" Fields Fields Fields Buffer Buffer"),
102  hdg2b(" Frames Frames Frames Buffer Buffer"),
103  hdg3 ("Processed Dropped Dropped Level Level"),
104  hdg2 (noFieldMode ? hdg2b : hdg2a);
105 
106  // Initialize the NTV2FieldBurn instance...
107  AJAStatus status (burner.Init());
108  if (AJA_FAILURE (status))
109  {cerr << "## ERROR: Initialization failed, status=" << status << endl; return 4;}
110 
111  // Start the burner's capture and playout threads...
112  burner.Run();
113 
114  // Loop until told to stop...
115  cout << hdg1 << endl << hdg2 << endl << hdg3 << endl;
116  do
117  {
118  ULWord totalFrames(0), inputDrops(0), outputDrops(0), inputBufferLevel(0), outputBufferLevel(0);
119  burner.GetStatus (totalFrames, inputDrops, outputDrops, inputBufferLevel, outputBufferLevel);
120  cout << setw(9) << totalFrames << setw(9) << inputDrops << setw(9) << outputDrops
121  << setw(9) << inputBufferLevel << setw(9) << outputBufferLevel << "\r" << flush;
122  AJATime::Sleep(2000);
123  } while (!gGlobalQuit); // loop until signaled
124  cout << endl;
125  } // NTV2FieldBurn scope
126  return 0;
127 
128 } // main
NTV2Channel NTV2InputSourceToChannel(const NTV2InputSource inInputSource)
Converts a given NTV2InputSource to its equivalent NTV2Channel value.
Definition: ntv2utils.cpp:5050
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:1297
Definition: json.hpp:5362
void SignalHandler(int inSignal)
Definition: main.cpp:26
#define false
uint32_t ULWord
Definition: ajatypes.h:236
#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:4965
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:180
virtual const NTV2StringList & otherArgs(void) const
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:1286
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.
NTV2TCIndex fTimecodeSource
Timecode source to use.
std::string join(const std::vector< std::string > &parts, const std::string &delim)
Definition: common.cpp:468
#define NTV2_IS_VALID_FRAME_BUFFER_FORMAT(__s__)
Definition: ntv2enums.h:265
#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:225
NTV2InputSource fInputSource
The device input connector to use.