AJA NTV2 SDK  17.1.1.1245
NTV2 SDK 17.1.1.1245
ntv2encodehevcfile.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MIT */
8 #include <stdio.h>
9 
10 #include "ntv2encodehevcfile.h"
11 #include "ntv2utils.h"
12 #include "ntv2devicefeatures.h"
13 #include "ajabase/system/process.h"
15 
16 using namespace std;
17 
18 
19 NTV2EncodeHEVCFile::NTV2EncodeHEVCFile (const string inDeviceSpecifier,
20  const NTV2Channel inChannel,
21  const string fileName,
22  const uint32_t frameWidth,
23  const uint32_t frameHeight,
24  const M31VideoPreset inPreset)
25 
26 : mFileInputThread (AJAThread()),
27  mVideoProcessThread (AJAThread()),
28  mCodecRawThread (AJAThread()),
29  mCodecHevcThread (AJAThread()),
30  mVideoFileThread (AJAThread()),
31  mM31 (AJA_NULL),
32  mHevcCommon (AJA_NULL),
33  mDeviceID (DEVICE_ID_NOTFOUND),
34  mDeviceSpecifier (inDeviceSpecifier),
35  mFileName (fileName),
36  mFrameWidth (frameWidth),
37  mFrameHeight (frameHeight),
38  mInputChannel (inChannel),
39  mEncodeChannel (M31_CH0),
40  mPreset (inPreset),
41  mVideoFormat (NTV2_MAX_NUM_VIDEO_FORMATS),
42  mPixelFormat (NTV2_FBF_8BIT_YCBCR_420PL2),
43  mQuad (false),
44  mInterlaced (false),
45  mMultiStream (false),
46  mSavedTaskMode (NTV2_STANDARD_TASKS),
47  mLastFrame (false),
48  mLastFrameInput (false),
49  mLastFrameRaw (false),
50  mLastFrameHevc (false),
51  mLastFrameVideo (false),
52  mGlobalQuit (false),
53  mVideoInputFrameCount (0),
54  mVideoProcessFrameCount (0),
55  mCodecRawFrameCount (0),
56  mCodecHevcFrameCount (0),
57  mVideoFileFrameCount (0)
58 {
59  ::memset (mFileInputBuffer, 0x0, sizeof (mFileInputBuffer));
60  ::memset (mVideoRawBuffer, 0x0, sizeof (mVideoRawBuffer));
61  ::memset (mVideoHevcBuffer, 0x0, sizeof (mVideoHevcBuffer));
62 
63 } // constructor
64 
65 
67 {
68  // Stop my capture and consumer threads, then destroy them...
69  Quit ();
70 
71  if (mM31 != AJA_NULL)
72  {
73  delete mM31;
74  mM31 = AJA_NULL;
75  }
76 
77  if (mHevcCommon != AJA_NULL)
78  {
79  delete mHevcCommon;
80  mHevcCommon = AJA_NULL;
81  }
82 
83  // free all my buffers...
84  for (unsigned bufferNdx = 0; bufferNdx < VIDEO_RING_SIZE; bufferNdx++)
85  {
86  if (mFileInputBuffer[bufferNdx].pVideoBuffer)
87  {
88  delete [] mFileInputBuffer[bufferNdx].pVideoBuffer;
89  mFileInputBuffer[bufferNdx].pVideoBuffer = AJA_NULL;
90  }
91  if (mFileInputBuffer[bufferNdx].pInfoBuffer)
92  {
93  delete [] mFileInputBuffer[bufferNdx].pInfoBuffer;
94  mFileInputBuffer[bufferNdx].pInfoBuffer = AJA_NULL;
95  }
96 
97  if (mVideoRawBuffer[bufferNdx].pVideoBuffer)
98  {
99  delete [] mVideoRawBuffer[bufferNdx].pVideoBuffer;
100  mVideoRawBuffer[bufferNdx].pVideoBuffer = AJA_NULL;
101  }
102  if (mVideoRawBuffer[bufferNdx].pInfoBuffer)
103  {
104  delete [] mVideoRawBuffer[bufferNdx].pInfoBuffer;
105  mVideoRawBuffer[bufferNdx].pInfoBuffer = AJA_NULL;
106  }
107 
108  if (mVideoHevcBuffer[bufferNdx].pVideoBuffer)
109  {
110  delete [] mVideoHevcBuffer[bufferNdx].pVideoBuffer;
111  mVideoHevcBuffer[bufferNdx].pVideoBuffer = AJA_NULL;
112  }
113  if (mVideoHevcBuffer[bufferNdx].pInfoBuffer)
114  {
115  delete [] mVideoHevcBuffer[bufferNdx].pInfoBuffer;
116  mVideoHevcBuffer[bufferNdx].pInfoBuffer = AJA_NULL;
117  }
118  }
119 
120 } // destructor
121 
122 
124 {
125  if (mM31 && !mLastFrame && !mGlobalQuit)
126  {
127  // Set the last frame flag to start the quit process
128  mLastFrame = true;
129 
130  // Wait for the last frame to be written to disk
131  int i;
132  int timeout = 300;
133  for (i = 0; i < timeout; i++)
134  {
135  if (mLastFrameVideo) break;
136  AJATime::Sleep (10);
137  }
138  if (i == timeout)
139  { cerr << "## ERROR: Wait for last frame timeout" << endl; }
140 
141  // Stop the encoder stream
142  if (!mM31->ChangeEHState(Hevc_EhState_ReadyToStop, mEncodeChannel))
143  { cerr << "## ERROR: ChangeEHState ready to stop failed" << endl; }
144 
145  if (!mM31->ChangeEHState(Hevc_EhState_Stop, mEncodeChannel))
146  { cerr << "## ERROR: ChangeEHState stop failed" << endl; }
147 
148  // stop the video input stream
149  if (!mM31->ChangeVInState(Hevc_VinState_Stop, mEncodeChannel))
150  { cerr << "## ERROR: ChangeVInState stop failed" << endl; }
151 
152  if(!mMultiStream)
153  {
154  // Now go to the init state
155  if (!mM31->ChangeMainState(Hevc_MainState_Init, Hevc_EncodeMode_Single))
156  { cerr << "## ERROR: ChangeMainState to init failed" << endl; }
157  }
158  }
159 
160  // Stop the worker threads
161  mGlobalQuit = true;
162 
163  while (mFileInputThread.Active())
164  AJATime::Sleep(10);
165 
166  while (mVideoProcessThread.Active())
167  AJATime::Sleep(10);
168 
169  while (mCodecRawThread.Active())
170  AJATime::Sleep(10);
171 
172  while (mCodecHevcThread.Active())
173  AJATime::Sleep(10);
174 
175  while (mVideoFileThread.Active())
176  AJATime::Sleep(10);
177 
178  // Release board
179  if (!mMultiStream)
180  {
181  mDevice.ReleaseStreamForApplication (kDemoAppSignature, static_cast<int32_t>(AJAProcess::GetPid()));
182  mDevice.SetEveryFrameServices (mSavedTaskMode); // Restore prior task mode
183  }
184 
185  // Close output file
186  mHevcCommon->CloseHevcFile();
187 
188  // Close YUV input file
189  mHevcCommon->CloseYuv420File();
190 
191 } // Quit
192 
193 
195 {
196  AJAStatus status (AJA_STATUS_SUCCESS);
197 
198  // Open the device...
199  if (!CNTV2DeviceScanner::GetFirstDeviceFromArgument (mDeviceSpecifier, mDevice))
200  { cerr << "## ERROR: Device '" << mDeviceSpecifier << "' not found" << endl; return AJA_STATUS_OPEN; }
201 
202  // Grab board in a shared environment
203  if (!mMultiStream)
204  {
205  if (!mDevice.AcquireStreamForApplication (kDemoAppSignature, static_cast<int32_t>(AJAProcess::GetPid())))
206  return AJA_STATUS_BUSY; // Another app is using the device
207  mDevice.GetEveryFrameServices (mSavedTaskMode); // Save the current state before we change it
208  }
209  mDevice.SetEveryFrameServices (NTV2_OEM_TASKS); // Since this is an OEM demo, use the OEM service level
210 
211  mDeviceID = mDevice.GetDeviceID (); // Keep the device ID handy, as it's used frequently
212 
213  // Make sure this device has an M31
214  if (!mDevice.features().HasHEVCM31())
215  {
216  cerr << "## ERROR: M31 not found" << endl;
217  return AJA_STATUS_FAIL;
218  }
219 
220  // Allocate our M31 helper class and our HEVC common class
221  mM31 = new CNTV2m31 (&mDevice);
222  mHevcCommon = new CNTV2DemoHevcCommon ();
223 
224  if ((mM31 == AJA_NULL) || (mHevcCommon == AJA_NULL))
225  return AJA_STATUS_FAIL;
226 
227  // Sanity check
228  if (mPreset >= M31_NUMVIDEOPRESETS)
229  return AJA_STATUS_FAIL;
230 
231  // This class only handles file based presets so make sure they didn't pass in a vif one
232  if (CNTV2m31::IsPresetVIF(mPreset))
233  return AJA_STATUS_FAIL;
234 
235  // Get NTV2 formats to match codec preset
236  mVideoFormat = CNTV2m31::GetPresetVideoFormat(mPreset);
237  mPixelFormat = CNTV2m31::GetPresetFrameBufferFormat(mPreset);
238  mQuad = CNTV2m31::IsPresetUHD(mPreset);
239  mInterlaced = CNTV2m31::IsPresetInterlaced(mPreset);
240 
241  // Quad mode must be channel 1
242  if (mQuad)
243  {
244  mInputChannel = NTV2_CHANNEL1;
245  mEncodeChannel = M31_CH0;
246  }
247  else
248  {
249  // When input channel specified we are multistream
250  switch (mInputChannel)
251  {
252  case NTV2_CHANNEL1: { mEncodeChannel = M31_CH0; mMultiStream = true; break; }
253  case NTV2_CHANNEL2: { mEncodeChannel = M31_CH1; mMultiStream = true; break; }
254  case NTV2_CHANNEL3: { mEncodeChannel = M31_CH2; mMultiStream = true; break; }
255  case NTV2_CHANNEL4: { mEncodeChannel = M31_CH3; mMultiStream = true; break; }
256  default: { mInputChannel = NTV2_CHANNEL1; mEncodeChannel = M31_CH0; }
257  }
258  }
259 
260  // Setup codec
261  status = mHevcCommon->SetupHEVC (mM31, mPreset, mEncodeChannel, mMultiStream, false);
262  if (AJA_FAILURE (status))
263  return status;
264 
265  // Setup the circular buffers
266  SetupHostBuffers ();
267 
268  // Open the YUV input file
269  status = mHevcCommon->OpenYuv420File (mFileName, RAWFILEWIDTH, RAWFILEHEIGHT);
270  if (AJA_FAILURE (status))
271  {
272  cerr << "OpenYuv420File " << mFileName << " failed " << status << endl;
273  return status;
274  }
275 
276  {
277  // Create encoded video output file
278  ostringstream fileName;
279  if (mMultiStream)
280  fileName << "raw_" << (mInputChannel+1) << ".hevc";
281  else
282  fileName << "raw.hevc";
283  status = mHevcCommon->CreateHevcFile (fileName.str(), mHevcCommon->YuvNumFrames());
284  if (AJA_FAILURE (status))
285  return status;
286  }
287  return AJA_STATUS_SUCCESS;
288 
289 } // Init
290 
291 
293 {
294  return mPreset;
295 }
296 
297 
299 {
300  mVideoBufferSize = GetVideoActiveSize (mVideoFormat, mPixelFormat, NTV2_VANCMODE_OFF);
301  mPicInfoBufferSize = sizeof(HevcPictureInfo)*2;
302  mEncInfoBufferSize = sizeof(HevcEncodedInfo)*2;
303 
304  // video input ring
305  mFileInputCircularBuffer.SetAbortFlag (&mGlobalQuit);
306  for (unsigned bufferNdx = 0; bufferNdx < VIDEO_RING_SIZE; bufferNdx++ )
307  {
308  memset (&mFileInputBuffer[bufferNdx], 0, sizeof(AVHevcDataBuffer));
309  mFileInputBuffer[bufferNdx].pVideoBuffer = new uint32_t [mVideoBufferSize/4];
310  mFileInputBuffer[bufferNdx].videoBufferSize = mVideoBufferSize;
311  mFileInputBuffer[bufferNdx].videoDataSize = 0;
312  mFileInputBuffer[bufferNdx].videoDataSize2 = 0;
313  mFileInputBuffer[bufferNdx].pInfoBuffer = new uint32_t [mPicInfoBufferSize/4];
314  mFileInputBuffer[bufferNdx].infoBufferSize = mPicInfoBufferSize;
315  mFileInputBuffer[bufferNdx].infoDataSize = 0;
316  mFileInputBuffer[bufferNdx].infoDataSize2 = 0;
317  mFileInputCircularBuffer.Add (& mFileInputBuffer[bufferNdx]);
318  }
319 
320  // video raw ring
321  mVideoRawCircularBuffer.SetAbortFlag (&mGlobalQuit);
322  for (unsigned bufferNdx = 0; bufferNdx < VIDEO_RING_SIZE; bufferNdx++ )
323  {
324  memset (&mVideoRawBuffer[bufferNdx], 0, sizeof(AVHevcDataBuffer));
325  mVideoRawBuffer[bufferNdx].pVideoBuffer = new uint32_t [mVideoBufferSize/4];
326  mVideoRawBuffer[bufferNdx].videoBufferSize = mVideoBufferSize;
327  mVideoRawBuffer[bufferNdx].videoDataSize = 0;
328  mVideoRawBuffer[bufferNdx].videoDataSize2 = 0;
329  mVideoRawBuffer[bufferNdx].pInfoBuffer = new uint32_t [mPicInfoBufferSize/4];
330  mVideoRawBuffer[bufferNdx].infoBufferSize = mPicInfoBufferSize;
331  mVideoRawBuffer[bufferNdx].infoDataSize = 0;
332  mVideoRawBuffer[bufferNdx].infoDataSize2 = 0;
333  mVideoRawCircularBuffer.Add (& mVideoRawBuffer[bufferNdx]);
334  }
335 
336  // video hevc ring
337  mVideoHevcCircularBuffer.SetAbortFlag (&mGlobalQuit);
338  for (unsigned bufferNdx = 0; bufferNdx < VIDEO_RING_SIZE; bufferNdx++ )
339  {
340  memset (&mVideoHevcBuffer[bufferNdx], 0, sizeof(AVHevcDataBuffer));
341  mVideoHevcBuffer[bufferNdx].pVideoBuffer = new uint32_t [mVideoBufferSize/4];
342  mVideoHevcBuffer[bufferNdx].videoBufferSize = mVideoBufferSize;
343  mVideoHevcBuffer[bufferNdx].videoDataSize = 0;
344  mVideoHevcBuffer[bufferNdx].videoDataSize2 = 0;
345  mVideoHevcBuffer[bufferNdx].pInfoBuffer = new uint32_t [mEncInfoBufferSize/4];
346  mVideoHevcBuffer[bufferNdx].infoBufferSize = mEncInfoBufferSize;
347  mVideoHevcBuffer[bufferNdx].infoDataSize = 0;
348  mVideoHevcBuffer[bufferNdx].infoDataSize2 = 0;
349  mVideoHevcCircularBuffer.Add (& mVideoHevcBuffer[bufferNdx]);
350  }
351 
352 } // SetupHostBuffers
353 
354 
356 {
357  // Start the playout and capture threads...
363 
364  return AJA_STATUS_SUCCESS;
365 
366 } // Run
367 
368 
369 // This is where we will start the video input thread
371 {
372  mFileInputThread.Attach(VideoInputThreadStatic, this);
373  mFileInputThread.SetPriority(AJA_ThreadPriority_High);
374  mFileInputThread.Start();
375 
376 } // StartVideoInputThread
377 
378 
379 // The video input thread static callback
380 void NTV2EncodeHEVCFile::VideoInputThreadStatic (AJAThread * pThread, void * pContext)
381 {
382  (void) pThread;
383 
384  NTV2EncodeHEVCFile * pApp (reinterpret_cast <NTV2EncodeHEVCFile *> (pContext));
385  pApp->VideoInputWorker ();
386 
387 } // VideoInputThreadStatic
388 
389 
391 {
392  AJAStatus status;
393 
394  while (!mGlobalQuit)
395  {
396  // Have we read all the frames of the file in
397  if (mVideoInputFrameCount < mHevcCommon->YuvNumFrames())
398  {
399  // No so lets read another frame
400  // First grab a local buffer so we can read a frame of data into it
401  AVHevcDataBuffer * pVideoData (mFileInputCircularBuffer.StartProduceNextBuffer ());
402  if (pVideoData)
403  {
404  status = mHevcCommon->ReadYuv420Frame(pVideoData->pVideoBuffer, mVideoInputFrameCount);
405  if (status != AJA_STATUS_SUCCESS)
406  {
407  printf("Error reading frame %d\n", mVideoInputFrameCount);
408  }
409 
410  pVideoData->videoDataSize = pVideoData->videoBufferSize;
411  pVideoData->videoDataSize2 = 0;
412 
413  // if we are done mark the last frame for the other threads
414  if (mVideoInputFrameCount == mHevcCommon->YuvNumFrames())
415  {
416  pVideoData->lastFrame = true;
417  }
418 
419  if(pVideoData->lastFrame && !mLastFrameInput)
420  {
421  printf ( "Read last frame number %d\n", mVideoInputFrameCount );
422  mLastFrameInput = true;
423  }
424  mVideoInputFrameCount++;
425 
426  // signal that we're done "producing" the frame, making it available for future "consumption"...
427  mFileInputCircularBuffer.EndProduceNextBuffer ();
428  }
429  }
430  // Looks like we are done
431  else
432  {
433  mGlobalQuit = true;
434  }
435  }
436 } // VideoInputWorker
437 
438 
439 // This is where we start the video process thread
441 {
442  mVideoProcessThread.Attach(VideoProcessThreadStatic, this);
443  mVideoProcessThread.SetPriority(AJA_ThreadPriority_High);
444  mVideoProcessThread.Start();
445 
446 } // StartVideoProcessThread
447 
448 
449 // The video process static callback
451 {
452  (void) pThread;
453 
454  NTV2EncodeHEVCFile * pApp (reinterpret_cast <NTV2EncodeHEVCFile *> (pContext));
455  pApp->VideoProcessWorker ();
456 
457 } // VideoProcessThreadStatic
458 
459 
461 {
462  while (!mGlobalQuit)
463  {
464  // wait for the next video input buffer
465  AVHevcDataBuffer * pSrcFrameData (mFileInputCircularBuffer.StartConsumeNextBuffer ());
466  if (pSrcFrameData)
467  {
468  // wait for the next video raw buffer
469  AVHevcDataBuffer * pDstFrameData (mVideoRawCircularBuffer.StartProduceNextBuffer ());
470  if (pDstFrameData)
471  {
472  // do something useful with the frame data...
473  ProcessVideoFrame(pSrcFrameData, pDstFrameData);
474 
475  mVideoProcessFrameCount++;
476 
477  // release the video raw buffer
478  mVideoRawCircularBuffer.EndProduceNextBuffer ();
479  }
480 
481  // release the video input buffer
482  mFileInputCircularBuffer.EndConsumeNextBuffer ();
483 
484  }
485  } // loop til quit signaled
486 
487 } // VideoProcessWorker
488 
489 
490 // This is where we start the codec raw thread
492 {
493  mCodecRawThread.Attach(CodecRawThreadStatic, this);
494  mCodecRawThread.SetPriority(AJA_ThreadPriority_High);
495  mCodecRawThread.Start();
496 
497 } // StartCodecRawThread
498 
499 
500 // The codec raw static callback
501 void NTV2EncodeHEVCFile::CodecRawThreadStatic (AJAThread * pThread, void * pContext)
502 {
503  (void) pThread;
504 
505  NTV2EncodeHEVCFile * pApp (reinterpret_cast <NTV2EncodeHEVCFile *> (pContext));
506  pApp->CodecRawWorker ();
507 
508 } // CodecRawThreadStatic
509 
510 
512 {
513  CNTV2Card ntv2Device;
514  CNTV2m31 * m31;
515 
516  // Open the device...
517  if (!CNTV2DeviceScanner::GetFirstDeviceFromArgument (mDeviceSpecifier, ntv2Device))
518  { cerr << "## ERROR: Device '" << mDeviceSpecifier << "' not found" << endl; return; }
519 
520  // Allocate our M31 helper class and our HEVC common class
521  m31 = new CNTV2m31 (&ntv2Device);
522 
523  while (!mGlobalQuit)
524  {
525  // wait for the next raw video frame
526  AVHevcDataBuffer * pFrameData (mVideoRawCircularBuffer.StartConsumeNextBuffer ());
527  if (pFrameData)
528  {
529  if (!mLastFrameRaw)
530  {
531  // transfer the raw video frame to the codec
532  if (mInterlaced)
533  {
534  m31->RawTransfer(mPreset, mEncodeChannel,
535  (uint8_t*)pFrameData->pVideoBuffer,
536  pFrameData->videoDataSize,
537  false, false);
538 
539  m31->RawTransfer(mPreset, mEncodeChannel,
540  (uint8_t*)pFrameData->pVideoBuffer,
541  pFrameData->videoDataSize,
542  true, pFrameData->lastFrame);
543  }
544  else
545  {
546  m31->RawTransfer(mEncodeChannel,
547  (uint8_t*)pFrameData->pVideoBuffer,
548  pFrameData->videoDataSize,
549  pFrameData->lastFrame);
550  }
551  if (pFrameData->lastFrame)
552  {
553  mLastFrameRaw = true;
554  }
555 
556  mCodecRawFrameCount++;
557  }
558 
559  // release the raw video frame
560  mVideoRawCircularBuffer.EndConsumeNextBuffer ();
561  }
562  } // loop til quit signaled
563 
564  delete m31;
565 
566 } // CodecRawWorker
567 
568 
569 // This is where we will start the codec hevc thread
571 {
572  mCodecHevcThread.Attach(CodecHevcThreadStatic, this);
573  mCodecHevcThread.SetPriority(AJA_ThreadPriority_High);
574  mCodecHevcThread.Start();
575 
576 } // StartCodecHevcThread
577 
578 
579 // The codec hevc static callback
580 void NTV2EncodeHEVCFile::CodecHevcThreadStatic (AJAThread * pThread, void * pContext)
581 {
582  (void) pThread;
583 
584  NTV2EncodeHEVCFile * pApp (reinterpret_cast <NTV2EncodeHEVCFile *> (pContext));
585  pApp->CodecHevcWorker ();
586 
587 } // CodecHevcThreadStatic
588 
589 
591 {
592  CNTV2Card ntv2Device;
593  CNTV2m31 * m31;
594 
595  // Open the device...
596  if (!CNTV2DeviceScanner::GetFirstDeviceFromArgument (mDeviceSpecifier, ntv2Device))
597  { cerr << "## ERROR: Device '" << mDeviceSpecifier << "' not found" << endl; return; }
598 
599  // Allocate our M31 helper class and our HEVC common class
600  m31 = new CNTV2m31 (&ntv2Device);
601 
602  while (!mGlobalQuit)
603  {
604  // wait for the next hevc frame
605  AVHevcDataBuffer * pFrameData (mVideoHevcCircularBuffer.StartProduceNextBuffer ());
606  if (pFrameData)
607  {
608  if (!mLastFrameHevc)
609  {
610  if (mInterlaced)
611  {
612  // get field 1 video and info buffer and size
613  uint8_t* pVideoBuffer = (uint8_t*)pFrameData->pVideoBuffer;
614  uint8_t* pInfoBuffer = (uint8_t*)pFrameData->pInfoBuffer;
615  uint32_t videoBufferSize = pFrameData->videoBufferSize;
616  uint32_t infoBufferSize = sizeof(HevcEncodedInfo);
617 
618  // transfer an hevc field 1 from the codec including encoded information
619  m31->EncTransfer(mEncodeChannel,
620  pVideoBuffer,
621  videoBufferSize,
622  pInfoBuffer,
623  infoBufferSize,
624  pFrameData->videoDataSize,
625  pFrameData->infoDataSize,
626  pFrameData->lastFrame);
627 
628  // round the video size up
629  pFrameData->videoDataSize = mHevcCommon->AlignDataBuffer(pVideoBuffer,
630  videoBufferSize,
631  pFrameData->videoDataSize,
632  8, 0xff);
633  // round the info size up
634  pFrameData->infoDataSize = mHevcCommon->AlignDataBuffer(pInfoBuffer,
635  infoBufferSize,
636  pFrameData->infoDataSize,
637  8, 0);
638 
639  // get field 2 video and info buffer and size
640  pVideoBuffer = ((uint8_t*)pFrameData->pVideoBuffer) + pFrameData->videoDataSize;
641  pInfoBuffer = ((uint8_t*)pFrameData->pInfoBuffer) + sizeof(HevcEncodedInfo);
642  videoBufferSize = pFrameData->videoBufferSize - pFrameData->videoDataSize;
643  infoBufferSize = sizeof(HevcEncodedInfo);
644 
645  // transfer an hevc field 2 from the codec including encoded information
646  m31->EncTransfer(mEncodeChannel,
647  pVideoBuffer,
648  videoBufferSize,
649  pInfoBuffer,
650  infoBufferSize,
651  pFrameData->videoDataSize2,
652  pFrameData->infoDataSize2,
653  pFrameData->lastFrame);
654 
655  // round the video size up
656  pFrameData->videoDataSize2 = mHevcCommon->AlignDataBuffer(pVideoBuffer,
657  videoBufferSize,
658  pFrameData->videoDataSize2,
659  8, 0xff);
660  // round the info size up
661  pFrameData->infoDataSize2 = mHevcCommon->AlignDataBuffer(pInfoBuffer,
662  infoBufferSize,
663  pFrameData->infoDataSize2,
664  8, 0);
665  }
666  else
667  {
668  // transfer an hevc frame from the codec including encoded information
669  m31->EncTransfer(mEncodeChannel,
670  (uint8_t*)pFrameData->pVideoBuffer,
671  pFrameData->videoBufferSize,
672  (uint8_t*)pFrameData->pInfoBuffer,
673  pFrameData->infoBufferSize,
674  pFrameData->videoDataSize,
675  pFrameData->infoDataSize,
676  pFrameData->lastFrame);
677 
678  // round the video size up
679  pFrameData->videoDataSize = mHevcCommon->AlignDataBuffer(pFrameData->pVideoBuffer,
680  pFrameData->videoBufferSize,
681  pFrameData->videoDataSize,
682  8, 0xff);
683  // round the info size up
684  pFrameData->infoDataSize = mHevcCommon->AlignDataBuffer(pFrameData->pInfoBuffer,
685  pFrameData->infoBufferSize,
686  pFrameData->infoDataSize,
687  8, 0);
688  }
689 
690  if (pFrameData->lastFrame)
691  {
692  mLastFrameHevc = true;
693  }
694 
695  mCodecHevcFrameCount++;
696  }
697 
698  // release and recycle the buffer...
699  mVideoHevcCircularBuffer.EndProduceNextBuffer ();
700  }
701  } // loop til quit signaled
702 
703  delete m31;
704 } // EncTransferFrames
705 
706 
707 // This is where we start the video file writer thread
709 {
710  mVideoFileThread.Attach(VideoFileThreadStatic, this);
711  mVideoFileThread.SetPriority(AJA_ThreadPriority_High);
712  mVideoFileThread.Start();
713 
714 } // StartVideoFileThread
715 
716 
717 // The file writer static callback
718 void NTV2EncodeHEVCFile::VideoFileThreadStatic (AJAThread * pThread, void * pContext)
719 {
720  (void) pThread;
721 
722  NTV2EncodeHEVCFile * pApp (reinterpret_cast <NTV2EncodeHEVCFile *> (pContext));
723  pApp->VideoFileWorker ();
724 
725 } // VideoFileStatic
726 
727 
729 {
730  while (!mGlobalQuit)
731  {
732  // wait for the next codec hevc frame
733  AVHevcDataBuffer * pFrameData (mVideoHevcCircularBuffer.StartConsumeNextBuffer ());
734  if (pFrameData)
735  {
736  if (!mLastFrameVideo)
737  {
738  // write the frame / fields hevc to the output file
739  mHevcCommon->WriteHevcData(pFrameData->pVideoBuffer, pFrameData->videoDataSize + pFrameData->videoDataSize2);
740 
741  if (pFrameData->lastFrame)
742  {
743  printf ( "Video file last frame number %d\n", mVideoFileFrameCount );
744  mLastFrameVideo = true;
745  }
746 
747  mVideoFileFrameCount++;
748  }
749 
750  // release the hevc buffer
751  mVideoHevcCircularBuffer.EndConsumeNextBuffer ();
752  }
753  } // loop til quit signaled
754 
755 } // VideoFileWorker
756 
757 
759 
760 
762 {
763  // Just report frames processed for file demo, as there's never a dropped frame,
764  // since there's no requirement to run in realtime, though this typically runs
765  // faster than real time. Also the buffer level is not important.
766  outStatus.framesProcessed = mVideoFileFrameCount;
767  outStatus.framesDropped = outStatus.bufferLevel = 0;
768 } // GetStatus
769 
770 
772 {
773  // Convert the RAW YUV tri-planar frame in to an NV12 bi-planar fame
774  AJAStatus status = mHevcCommon->ConvertYuv420FrameToNV12(pSrcFrame->pVideoBuffer, pDstFrame->pVideoBuffer, pSrcFrame->videoDataSize);
775 
776  pDstFrame->videoDataSize = pSrcFrame->videoDataSize;
777  pDstFrame->lastFrame = pSrcFrame->lastFrame;
778 
779  return status;
780 
781 } // ProcessVideoFrame
NTV2EncodeHEVCFile::StartVideoFileThread
virtual void StartVideoFileThread(void)
Start the video file writer thread.
Definition: ntv2encodehevcfile.cpp:708
RAWFILEHEIGHT
#define RAWFILEHEIGHT
Definition: ntv2encodehevcfile.h:32
ntv2encodehevcfile.h
Declares the NTV2EncodeHEVCFile class.
Hevc_EncodeMode_Single
@ Hevc_EncodeMode_Single
Definition: ntv2publicinterface.h:9378
NTV2_CHANNEL2
@ NTV2_CHANNEL2
Specifies channel or Frame Store 2 (or the 2nd item).
Definition: ntv2enums.h:1308
AJA_ThreadPriority_High
@ AJA_ThreadPriority_High
Definition: thread.h:44
NTV2EncodeHEVCFile::VideoFileThreadStatic
static void VideoFileThreadStatic(AJAThread *pThread, void *pContext)
This is the video file writer thread's static callback function that gets called when the thread star...
Definition: ntv2encodehevcfile.cpp:718
ntv2devicefeatures.h
Declares device capability functions.
AVHevcDataBuffer::videoDataSize2
uint32_t videoDataSize2
Size of field 2 video data (bytes)
Definition: ntv2demohevccommon.h:32
NTV2Channel
NTV2Channel
These enum values are mostly used to identify a specific widget_framestore. They're also commonly use...
Definition: ntv2enums.h:1305
AJA_STATUS_SUCCESS
@ AJA_STATUS_SUCCESS
Definition: types.h:381
CNTV2DemoHevcCommon::WriteHevcData
void WriteHevcData(void *pBuffer, uint32_t bufferSize)
Definition: ntv2demohevccommon.cpp:134
NTV2EncodeHEVCFile::VideoInputThreadStatic
static void VideoInputThreadStatic(AJAThread *pThread, void *pContext)
This is the video input thread's static callback function that gets called when the thread starts....
Definition: ntv2encodehevcfile.cpp:380
M31_CH2
@ M31_CH2
Definition: ntv2m31enums.h:229
NTV2EncodeHEVCFile::ProcessVideoFrame
virtual AJAStatus ProcessVideoFrame(AVHevcDataBuffer *pSrcFrame, AVHevcDataBuffer *pDstFrame)
Default do-nothing function for processing the captured frames.
Definition: ntv2encodehevcfile.cpp:771
AJAThread::Attach
virtual AJAStatus Attach(AJAThreadFunction *pThreadFunction, void *pUserContext)
Definition: thread.cpp:169
NTV2EncodeHEVCFile::CodecRawWorker
virtual void CodecRawWorker(void)
Repeatedly removes video frames from the raw video ring and transfers them to the codec.
Definition: ntv2encodehevcfile.cpp:511
AVHevcDataBuffer::lastFrame
bool lastFrame
Indicates last captured frame.
Definition: ntv2demohevccommon.h:44
NTV2EncodeHEVCFile::~NTV2EncodeHEVCFile
virtual ~NTV2EncodeHEVCFile()
Definition: ntv2encodehevcfile.cpp:66
NTV2EncodeHEVCFile::GetStatus
virtual void GetStatus(AVHevcStatus &outStatus)
Provides status information about my input (capture) process.
Definition: ntv2encodehevcfile.cpp:761
systemtime.h
Declares the AJATime class.
NTV2EncodeHEVCFile::Run
virtual AJAStatus Run(void)
Runs me.
Definition: ntv2encodehevcfile.cpp:355
AJA_STATUS_BUSY
@ AJA_STATUS_BUSY
Definition: types.h:391
CNTV2DeviceScanner::GetFirstDeviceFromArgument
static bool GetFirstDeviceFromArgument(const std::string &inArgument, CNTV2Card &outDevice)
Rescans the host, and returns an open CNTV2Card instance for the AJA device that matches a command li...
Definition: ntv2devicescanner.cpp:366
CNTV2DemoHevcCommon
Definition: ntv2demohevccommon.h:56
CNTV2DemoHevcCommon::ConvertYuv420FrameToNV12
AJAStatus ConvertYuv420FrameToNV12(void *pSrcBuffer, void *pDstBuffer, uint32_t bufferSize)
Definition: ntv2demohevccommon.cpp:467
AJACircularBuffer::StartConsumeNextBuffer
FrameDataPtr StartConsumeNextBuffer(void)
The thread that's responsible for processing incoming frames – the consumer – calls this function to ...
Definition: circularbuffer.h:153
NTV2EncodeHEVCFile::StartCodecRawThread
virtual void StartCodecRawThread(void)
Start the codec raw thread.
Definition: ntv2encodehevcfile.cpp:491
AVHevcDataBuffer::pVideoBuffer
uint32_t * pVideoBuffer
Pointer to host video buffer.
Definition: ntv2demohevccommon.h:29
CNTV2DemoHevcCommon::CloseHevcFile
void CloseHevcFile(void)
Definition: ntv2demohevccommon.cpp:123
NTV2EncodeHEVCFile::VideoProcessThreadStatic
static void VideoProcessThreadStatic(AJAThread *pThread, void *pContext)
This is the video process thread's static callback function that gets called when the thread starts....
Definition: ntv2encodehevcfile.cpp:450
CNTV2MacDriverInterface::ReleaseStreamForApplication
virtual bool ReleaseStreamForApplication(ULWord inApplicationType, int32_t inProcessID)
Releases exclusive use of the AJA device for the given process, permitting other processes to acquire...
Definition: ntv2macdriverinterface.cpp:516
AJACircularBuffer::EndProduceNextBuffer
void EndProduceNextBuffer(void)
The producer thread calls this function to signal that it has finished populating the frame it obtain...
Definition: circularbuffer.h:259
VIDEO_RING_SIZE
#define VIDEO_RING_SIZE
Definition: ntv2encodehevc.h:28
NTV2EncodeHEVCFile::VideoFileWorker
virtual void VideoFileWorker(void)
Repeatedly removes hevc frame from the hevc ring and writes them to the hevc output file.
Definition: ntv2encodehevcfile.cpp:728
NTV2EncodeHEVCFile::CodecHevcWorker
virtual void CodecHevcWorker(void)
Repeatedly transfers hevc frames from the codec and adds them to the hevc ring.
Definition: ntv2encodehevcfile.cpp:590
AVHevcDataBuffer::infoDataSize
uint32_t infoDataSize
Size of the information data (bytes)
Definition: ntv2demohevccommon.h:35
NTV2_CHANNEL1
@ NTV2_CHANNEL1
Specifies channel or Frame Store 1 (or the first item).
Definition: ntv2enums.h:1307
NTV2EncodeHEVCFile
Instances of me capture frames in real time from a video signal provided to an input of an AJA device...
Definition: ntv2encodehevcfile.h:40
AVHevcStatus::framesDropped
ULWord framesDropped
Definition: ntv2demohevccommon.h:51
nlohmann::json_abiNLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON_v3_11_NLOHMANN_JSON_VERSION_PATCH::detail::void
j template void())
Definition: json.hpp:4893
AVHevcDataBuffer::pInfoBuffer
uint32_t * pInfoBuffer
Picture information (raw) or encode information (hevc)
Definition: ntv2demohevccommon.h:33
AVHevcDataBuffer::infoDataSize2
uint32_t infoDataSize2
Size of the field 2 information data (bytes)
Definition: ntv2demohevccommon.h:36
NTV2_CHANNEL4
@ NTV2_CHANNEL4
Specifies channel or Frame Store 4 (or the 4th item).
Definition: ntv2enums.h:1310
M31_CH1
@ M31_CH1
Definition: ntv2m31enums.h:228
Hevc_MainState_Init
@ Hevc_MainState_Init
Definition: ntv2publicinterface.h:9368
CNTV2Card::features
virtual class DeviceCapabilities & features(void)
Definition: ntv2card.h:141
M31_NUMVIDEOPRESETS
@ M31_NUMVIDEOPRESETS
Definition: ntv2m31enums.h:178
AJAThread
Definition: thread.h:69
NTV2_FBF_8BIT_YCBCR_420PL2
@ NTV2_FBF_8BIT_YCBCR_420PL2
8-Bit 4:2:0 2-Plane YCbCr
Definition: ntv2enums.h:241
M31_CH0
@ M31_CH0
Definition: ntv2m31enums.h:227
AJAThread::Active
virtual bool Active()
Definition: thread.cpp:116
M31_CH3
@ M31_CH3
Definition: ntv2m31enums.h:230
AVHevcDataBuffer::videoDataSize
uint32_t videoDataSize
Size of video data (bytes)
Definition: ntv2demohevccommon.h:31
AJAStatus
AJAStatus
Definition: types.h:378
process.h
Declares the AJAProcess class.
AJATime::Sleep
static void Sleep(const int32_t inMilliseconds)
Suspends execution of the current thread for a given number of milliseconds.
Definition: systemtime.cpp:284
AJACircularBuffer::Add
AJAStatus Add(FrameDataPtr pInFrameData)
Appends a new frame buffer to me, increasing my frame storage capacity by one frame.
Definition: circularbuffer.h:92
Hevc_VinState_Stop
@ Hevc_VinState_Stop
Definition: ntv2publicinterface.h:9405
NTV2_VANCMODE_OFF
@ NTV2_VANCMODE_OFF
This identifies the mode in which there are no VANC lines in the frame buffer.
Definition: ntv2enums.h:3718
AJA_STATUS_FAIL
@ AJA_STATUS_FAIL
Definition: types.h:382
CNTV2DemoHevcCommon::CloseYuv420File
void CloseYuv420File(void)
Definition: ntv2demohevccommon.cpp:431
NTV2_MAX_NUM_VIDEO_FORMATS
@ NTV2_MAX_NUM_VIDEO_FORMATS
Definition: ntv2enums.h:685
AJAProcess::GetPid
static uint64_t GetPid()
Definition: process.cpp:35
AVHevcStatus::bufferLevel
ULWord bufferLevel
Definition: ntv2demohevccommon.h:52
NTV2_CHANNEL3
@ NTV2_CHANNEL3
Specifies channel or Frame Store 3 (or the 3rd item).
Definition: ntv2enums.h:1309
AJACircularBuffer::StartProduceNextBuffer
FrameDataPtr StartProduceNextBuffer(void)
The thread that's responsible for providing frames – the producer – calls this function to populate t...
Definition: circularbuffer.h:109
ntv2utils.h
Declares numerous NTV2 utility functions.
CNTV2Card
I interrogate and control an AJA video/audio capture/playout device.
Definition: ntv2card.h:28
NTV2EncodeHEVCFile::CodecRawThreadStatic
static void CodecRawThreadStatic(AJAThread *pThread, void *pContext)
This is the codec raw thread's static callback function that gets called when the thread starts....
Definition: ntv2encodehevcfile.cpp:501
HevcPictureInfo
struct HevcPictureInfo HevcPictureInfo
GetVideoActiveSize
ULWord GetVideoActiveSize(const NTV2VideoFormat inVideoFormat, const NTV2FrameBufferFormat inFBFormat, const NTV2VANCMode inVancMode=NTV2_VANCMODE_OFF)
Definition: ntv2utils.cpp:2758
M31VideoPreset
M31VideoPreset
Definition: ntv2m31enums.h:12
kDemoAppSignature
static const ULWord kDemoAppSignature((((uint32_t)( 'D'))<< 24)|(((uint32_t)( 'E'))<< 16)|(((uint32_t)( 'M'))<< 8)|(((uint32_t)( 'O'))<< 0))
NTV2EncodeHEVCFile::GetCodecPreset
virtual M31VideoPreset GetCodecPreset(void)
Get the codec preset.
Definition: ntv2encodehevcfile.cpp:292
AJACircularBuffer::EndConsumeNextBuffer
void EndConsumeNextBuffer(void)
The consumer thread calls this function to signal that it has finished processing the frame it obtain...
Definition: circularbuffer.h:266
HevcEncodedInfo
struct HevcEncodedInfo HevcEncodedInfo
NTV2_STANDARD_TASKS
@ NTV2_STANDARD_TASKS
1: Standard/Retail: Device is completely controlled by AJA ControlPanel, service/daemon,...
Definition: ntv2publicinterface.h:4291
CNTV2Card::SetEveryFrameServices
virtual bool SetEveryFrameServices(const NTV2EveryFrameTaskMode inMode)
Sets the device's task mode.
Definition: ntv2register.cpp:179
AJA_NULL
#define AJA_NULL
Definition: ajatypes.h:197
NTV2EncodeHEVCFile::StartVideoProcessThread
virtual void StartVideoProcessThread(void)
Start the video process thread.
Definition: ntv2encodehevcfile.cpp:440
NTV2EncodeHEVCFile::VideoProcessWorker
virtual void VideoProcessWorker(void)
Repeatedly removes video frames from the video input ring, calls a custom video process method and ad...
Definition: ntv2encodehevcfile.cpp:460
RAWFILEWIDTH
#define RAWFILEWIDTH
Definition: ntv2encodehevcfile.h:31
false
#define false
Definition: ntv2devicefeatures.h:25
std
Definition: json.hpp:5362
NTV2EncodeHEVCFile::Init
virtual AJAStatus Init(void)
Initializes me and prepares me to Run.
Definition: ntv2encodehevcfile.cpp:194
AVHevcStatus
Definition: ntv2demohevccommon.h:48
NTV2EncodeHEVCFile::NTV2EncodeHEVCFile
NTV2EncodeHEVCFile(const std::string inDeviceSpecifier="0", const NTV2Channel inChannel=NTV2_CHANNEL1, const std::string inFilePath="", const uint32_t inFrameWidth=0, const uint32_t inFrameHeight=0, const M31VideoPreset inM31Preset=M31_FILE_1920X1080_420_8_24p)
Constructs me using the given settings.
Definition: ntv2encodehevcfile.cpp:19
CNTV2MacDriverInterface::AcquireStreamForApplication
virtual bool AcquireStreamForApplication(ULWord inApplicationType, int32_t inProcessID)
Reserves exclusive use of the AJA device for a given process, preventing other processes on the host ...
Definition: ntv2macdriverinterface.cpp:481
Hevc_EhState_ReadyToStop
@ Hevc_EhState_ReadyToStop
Definition: ntv2publicinterface.h:9416
CNTV2DriverInterface::GetDeviceID
virtual NTV2DeviceID GetDeviceID(void)
Definition: ntv2driverinterface.cpp:381
Hevc_EhState_Stop
@ Hevc_EhState_Stop
Definition: ntv2publicinterface.h:9414
CNTV2Card::GetEveryFrameServices
virtual bool GetEveryFrameServices(NTV2EveryFrameTaskMode &outMode)
Retrieves the device's current "retail service" task mode.
Definition: ntv2register.cpp:184
NTV2EncodeHEVCFile::SetupHostBuffers
virtual void SetupHostBuffers(void)
Sets up my circular buffers.
Definition: ntv2encodehevcfile.cpp:298
CNTV2DemoHevcCommon::CreateHevcFile
AJAStatus CreateHevcFile(const std::string &inFileName, uint32_t maxFrames)
Definition: ntv2demohevccommon.cpp:103
AJACircularBuffer::SetAbortFlag
void SetAbortFlag(const bool *pAbortFlag)
Tells me the boolean variable I should monitor such that when it gets set to "true" will cause any th...
Definition: circularbuffer.h:51
AVHevcDataBuffer::videoBufferSize
uint32_t videoBufferSize
Size of host video buffer (bytes)
Definition: ntv2demohevccommon.h:30
NTV2EncodeHEVCFile::StartVideoInputThread
virtual void StartVideoInputThread(void)
Start the video input thread.
Definition: ntv2encodehevcfile.cpp:370
AJAThread::SetPriority
virtual AJAStatus SetPriority(AJAThreadPriority priority)
Definition: thread.cpp:133
AVHevcDataBuffer::infoBufferSize
uint32_t infoBufferSize
Size of the host information buffer (bytes)
Definition: ntv2demohevccommon.h:34
NTV2EncodeHEVCFile::CodecHevcThreadStatic
static void CodecHevcThreadStatic(AJAThread *pThread, void *pContext)
This is the codec hevc thread's static callback function that gets called when the thread starts....
Definition: ntv2encodehevcfile.cpp:580
NTV2EncodeHEVCFile::Quit
virtual void Quit(void)
Gracefully stops me from running.
Definition: ntv2encodehevcfile.cpp:123
AJA_STATUS_OPEN
@ AJA_STATUS_OPEN
Definition: types.h:388
CNTV2DemoHevcCommon::AlignDataBuffer
uint32_t AlignDataBuffer(void *pBuffer, uint32_t bufferSize, uint32_t dataSize, uint32_t alignBytes, uint8_t fill)
Definition: ntv2demohevccommon.cpp:544
AJAThread::Start
virtual AJAStatus Start()
Definition: thread.cpp:91
NTV2EncodeHEVCFile::VideoInputWorker
virtual void VideoInputWorker(void)
Repeatedly captures video frames using AutoCirculate and add them to the video input ring.
Definition: ntv2encodehevcfile.cpp:390
AVHevcDataBuffer
This structure encapsulates the video and audio buffers used by the HEVC demo applications....
Definition: ntv2demohevccommon.h:27
AJA_FAILURE
#define AJA_FAILURE(_status_)
Definition: types.h:371
CNTV2DemoHevcCommon::ReadYuv420Frame
AJAStatus ReadYuv420Frame(void *pBuffer, uint32_t numFrame)
Definition: ntv2demohevccommon.cpp:446
AVHevcStatus::framesProcessed
ULWord framesProcessed
Definition: ntv2demohevccommon.h:50
CNTV2DemoHevcCommon::YuvNumFrames
uint32_t YuvNumFrames()
Definition: ntv2demohevccommon.h:88
DEVICE_ID_NOTFOUND
@ DEVICE_ID_NOTFOUND
Invalid or "not found".
Definition: ntv2enums.h:90
CNTV2DemoHevcCommon::OpenYuv420File
AJAStatus OpenYuv420File(const std::string &inFileName, const uint32_t width, const uint32_t height)
Definition: ntv2demohevccommon.cpp:400
NTV2_OEM_TASKS
@ NTV2_OEM_TASKS
2: OEM: Device is configured by controlling application(s), with minimal driver involvement.
Definition: ntv2publicinterface.h:4292
NTV2EncodeHEVCFile::StartCodecHevcThread
virtual void StartCodecHevcThread(void)
Start the codec hevc thread.
Definition: ntv2encodehevcfile.cpp:570
CNTV2DemoHevcCommon::SetupHEVC
AJAStatus SetupHEVC(CNTV2m31 *pM31, M31VideoPreset preset, M31Channel encodeChannel, bool multiStream, bool withInfo)
Definition: ntv2demohevccommon.cpp:618