RAW audio capture from HDMI using DeckLink Mini Recorder 4K

devil coder mdamirraza at gmail.com
Thu Mar 12 13:04:32 UTC 2020


Hi Experts,

I need to capture audio from TI DSP hardware/Laptop. So I opted "DeckLink
Mini Recorder 4K Audio" and it connected to desktop.
By using Decklink API's I am able to capture audio (PCM) with 32-bit depth.
But when I used media express to capture, and extracted audio
using FFmpeg and I am getting audio (PCM) with 24-bit depth.

*
Question
1) Does this device "DeckLink Mini Recorder 4K Audio" converts audio from
32-bit to 24-bit?
2) Is this device "DeckLink Mini Recorder 4K Audio" bit-exact/loss-less?
*
   consider the below test scenario.

I am playing audio(PCM) by MPC-HC/VLC/Groove player in laptop and capture
audio(PCM) using "DeckLink Mini Recorder 4K Audio"
connected to desktop, The capture audio is bit-exact with the streamed
input.?

i.e  ffmpeg.exe -i HDMI_Output1.av1 -vn -c:a copy out.wav

Note:
    I am using Blackmagic_Desktop_Video_Windows_11.5 & 
Blackmagic_DeckLink_SDK_11.5 software's.

I have added the Decklink API code snippet.


/void main()
{
  IDeckLinkIterator* deckLinkIterator = NULL;
  IDeckLinkAttributes* deckLinkAttributes = NULL;
  IDeckLink* deckLink = NULL;
  IDeckLinkInput* deckLinkInput = NULL;
  NotificationCallback* notificationCallback = NULL;
  HRESULT result;
  BOOL supported;
  int returnCode = 1;
#ifdef WRITE_WAV_FILE
  wave_header wh;
  unsigned octet_depth;
#endif
  Initialize();
#ifdef _WIN32
  MutexHandle = CreateMutex(NULL, /* security attributes */
                            FALSE, /* initially not owned */
                            NULL); /* Name */
#endif
  /* Create an IDeckLinkIterator object to enumerate all DeckLink cards in
the system */
  if (GetDeckLinkIterator(&deckLinkIterator) != S_OK)
  {
    fprintf(stderr, "A DeckLink iterator could not be created.  The DeckLink
drivers may not be installed.\n");
    goto bail;
  }
  /* Obtain the first DeckLink device */
  result = deckLinkIterator->Next(&deckLink);
  if (result != S_OK)
  {
    fprintf(stderr, "Could not find DeckLink device - result = %08x\n",
result);
    goto bail;
  }

  /* Obtain the Attributes interface for the DeckLink device */
  result = deckLink->QueryInterface(IID_IDeckLinkAttributes,
(void**)&deckLinkAttributes);
  if (result != S_OK)
  {
    fprintf(stderr, "Could not obtain the IDeckLinkAttributes interface -
result = %08x\n", result);
    goto bail;
  }

  /* Determine whether the DeckLink device supports input format detection
*/
  result =
deckLinkAttributes->GetFlag(BMDDeckLinkSupportsInputFormatDetection,
&supported);
  if ((result != S_OK) || (supported == false))
  {
    fprintf(stderr, "Device does not support automatic mode detection\n");
    goto bail;
  }

  /* Obtain the input interface for the DeckLink device */
  result = deckLink->QueryInterface(IID_IDeckLinkInput,
(void**)&deckLinkInput);
  if (result != S_OK)
  {
    fprintf(stderr, "Could not obtain the IDeckLinkInput interface - result
= %08x\n", result);
    goto bail;
  }

  /* Create an instance of notification callback */
  notificationCallback = new NotificationCallback(deckLinkInput);
  if (notificationCallback == NULL)
  {
    fprintf(stderr, "Could not create notification callback object\n");
    goto bail;
  }

  /* Set the callback object to the DeckLink device's input interface */
  result = deckLinkInput->SetCallback(notificationCallback);
  if (result != S_OK)
  {
    fprintf(stderr, "Could not set callback - result = %08x\n", result);
    goto bail;
  }

  /*  Enable video input with a default video mode and the automatic format
detection feature enabled */
  result = deckLinkInput->EnableVideoInput(bmdModeHD1080p5994,
bmdFormat8BitYUV, bmdVideoInputFlagDefault);
  if (result != S_OK)
  {
    fprintf(stderr, "Could not enable video input - result = %08x\n",
result);
    goto bail;
  }
  nBytesPerSample = (bmdAudioSampleType32bitInteger >> 3);
  nChannels = 2;
  /*  Enable audio input with a default audio mode and the automatic format
detection feature enabled */
  result = deckLinkInput->EnableAudioInput(bmdAudioSampleRate48kHz,
bmdAudioSampleType32bitInteger, nChannels);
  if (result != S_OK)
  {
    fprintf(stderr, "Could not enable audio input - result = %08x\n",
result);
    goto bail;
  }

#ifdef WRITE_WAV_FILE
  /* Populate the wave headers */
  /* RIFF */
  sprintf(&wh.riff.name1[0], "RIFF");
  sprintf(&wh.riff.name2[0], "WAVE");
  /* format */
  octet_depth = (bmdAudioSampleType32bitInteger + 7) / 8;
  sprintf(&wh.fmt.name[0], "fmt ");
  wh.fmt.size = FMT_SIZE;
  wh.fmt.format_type = FMT_TAG_PCM;
  wh.fmt.channel_count = (unsigned short)nChannels;
  wh.fmt.sample_rate = bmdAudioSampleRate48kHz;
  wh.fmt.bits_per_sample = (unsigned short)octet_depth * 8;
  wh.fmt.block_alignment = (unsigned short)(octet_depth*nChannels);
  wh.fmt.bytes_per_second = (unsigned
long)wh.fmt.block_alignment*bmdAudioSampleRate48kHz;
  wh.fmt.extra_bytes = (unsigned short)0;
  /* data */
  sprintf(&wh.data.name[0], "data");
#endif 

  printf("Starting streams\n");

  /* Start capture */
  result = deckLinkInput->StartStreams();
  if (result != S_OK)
  {
    fprintf(stderr, "Could not start capture - result = %08x\n", result);
    goto bail;
  }
#ifdef WRITE_WAV_FILE
  FILE *fp = fopen("HDMI_Output.wav", "wb");
#else
  FILE *fp = fopen("HDMI_Output.bin","wb");
#endif
  char *ptrCopy;
  float *fPtr;
  unsigned int zeroCntr, trailingZerosCnt;
  do
  {
      zeroCntr = 0;
      trailingZerosCnt = 0;
#ifdef _WIN32
      WaitForSingleObject(MutexHandle, /* handle */
                          INFINITE); /* time-out interval */
#endif
      int bytesInQueue = (int)((long long)aBufPtr - (long
long)aBufWritePtr);
      ptrCopy = (char *)aBufPtr;
#ifdef _WIN32
      ReleaseMutex(MutexHandle);
#endif
      if (bytesInQueue > 0)
      {
#ifdef STRIP_ZEROS
          /* Parse data for zeros */
          fPtr = (float *)aBufWritePtr;
          for (int i = 0; i < (bytesInQueue >> 2); i++)
          {
              if (*(fPtr + i) == 0.0)
                  zeroCntr++;
              else
                  break;
          }
          aBufWritePtr += (zeroCntr << 2);
          bytesInQueue -= (zeroCntr << 2);
#endif
          if (bytesInQueue > 0)
          {
              fPtr = (float *)aBufWritePtr;
              for (int i = 0; i < (bytesInQueue >> 2); i++)
              {
                  fwrite(fPtr, 4, 1, fp);
                  fflush(fp);

                  if (*fPtr == 0.0)
                      trailingZerosCnt++;
                  else
                      trailingZerosCnt = 0;

                  if (trailingZerosCnt >= NUM_TRAIL_ZEROS_TRESHOLD)
                      break;

                  fPtr++;
              }
          }
      }
      aBufWritePtr = ptrCopy;
      Sleep(100);
  } while (trailingZerosCnt < NUM_TRAIL_ZEROS_TRESHOLD);

  fclose (fp);
#ifdef STRIP_ZEROS
  /* Remove trailing zeros, write wave header */
#ifdef WRITE_WAV_FILE
  fp = fopen("HDMI_Output.wav", "rb");
#else
  fp = fopen("HDMI_Output.bin", "rb");
#endif
  fseek(fp, 0, SEEK_END);
  int size = ftell(fp);
  size = size - (NUM_TRAIL_ZEROS_TRESHOLD << 2);
  printf(" \n size of hearder = %d", size);
#ifdef WRITE_WAV_FILE
  wh.data.size = size;
  wh.riff.size = wh.data.size + sizeof(wave_format) + sizeof(wave_RIFF);
  printf(" \n size of hearderwh.riff.size = %d", wh.riff.size);
#endif
  char * tmpBuf = (char *)malloc(size);
  fseek(fp, 0, SEEK_SET);
  fread(tmpBuf, 1, size, fp);
  fclose(fp);
#endif
#ifdef WRITE_WAV_FILE
  fp = fopen("HDMI_Output.wav", "wb");
  /* write the wave header */
  fwrite(&wh, 1, sizeof(wave_header), fp);
  /* Write the zero stripped PCM data */
  fwrite(tmpBuf, 1, size, fp);
  free(tmpBuf);
  fflush(fp);
  fclose(fp);
#endif
bail:
  /* Stop capture */
  result = deckLinkInput->StopStreams();

  /* Disable the video input interface */
  result = deckLinkInput->DisableVideoInput();

  /* return success */
  returnCode = 0;

  /* Release resources */

  /* Release the attributes interface */
  if (deckLinkAttributes != NULL)
    deckLinkAttributes->Release();

  /* Release the video input interface */
  if (deckLinkInput != NULL)
    deckLinkInput->Release();

  /* Release the Decklink object */
  if (deckLink != NULL)
    deckLink->Release();

  /* Release the DeckLink iterator */
  if (deckLinkIterator != NULL)
    deckLinkIterator->Release();

  /* Release the notification callback object */
  if (notificationCallback)
    delete notificationCallback;
}
/



-----
adi
--
Sent from: http://gstreamer-devel.966125.n4.nabble.com/


More information about the gstreamer-devel mailing list