Захват аудио RAW с HDMI с помощью мини-рекордера DeckLink 4K - PullRequest
0 голосов
/ 12 марта 2020

Мне нужно захватить звук с аппаратного обеспечения TI DSP / ноутбука. Поэтому я выбрал «DeckLink Mini Recorder 4K Audio», и он подключился к рабочему столу. Используя API Decklink, я могу захватывать аудио (PCM) с 32-битной глубиной. Но когда я использовал медиа express для захвата и извлечения аудио с помощью FFmpeg, и я получаю аудио (PCM) с 24-битной глубиной.

Вопрос 1) Есть ли у этого устройства "DeckLink Mini Recorder 4K Аудио »конвертирует аудио из 32-битного в 24-битное? 2) Является ли это устройство «DeckLink Mini Recorder 4K Audio» точным / без потерь?

, рассмотрите следующий тестовый сценарий.

Я играю аудио (PCM) MP C -HC / VLC / Groove проигрыватель в ноутбуке и захват аудио (PCM) с помощью «DeckLink Mini Recorder 4K Audio», подключенного к рабочему столу. Захват звука является бит-точным с потоковым входом .?

т.е. ffmpeg.exe -i HDMI_Output1.av1 -vn - c: копия out.wav

Примечание. Я использую программное обеспечение Blackmagic_Desktop_Video_Windows_11.5 & Blackmagic_DeckLink_SDK_11.5.

Я добавил Фрагмент кода Decklink API.

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;
}
...