Видео трансляция с использованием NDI SDK 4.5 в iOS 13 не работает. Приемник в локальной сети не получает видеопакеты - PullRequest
7 голосов
/ 08 мая 2020

Я пытался использовать NDI SDK 4.5 в приложении Objective- C iOS -13 для трансляции захвата камеры с устройства iPhone.

Мой пример кода находится в publi c Репозиторий Github: https://github.com/bharatbiswal/CameraExampleObjectiveC

Ниже показано, как я отправляю CMSampleBufferRef sampleBuffer:

CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);

NDIlib_video_frame_v2_t video_frame;
video_frame.xres = VIDEO_CAPTURE_WIDTH;
video_frame.yres = VIDEO_CAPTURE_HEIGHT;
video_frame.FourCC = NDIlib_FourCC_type_UYVY; // kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
video_frame.line_stride_in_bytes = VIDEO_CAPTURE_WIDTH * VIDEO_CAPTURE_PIXEL_SIZE;
video_frame.p_data = CVPixelBufferGetBaseAddress(pixelBuffer);
NDIlib_send_send_video_v2(self.my_ndi_send, &video_frame);

Я использовал " NewTek NDI Video Монитор"для приема видео из сети. Однако, даже если он отображается как источник, видео не воспроизводится.

Использовал ли кто-нибудь NDI SDK в iOS для создания функций широковещательного отправителя или получателя? Пожалуйста, помогите.

Ответы [ 3 ]

5 голосов
/ 16 мая 2020

Вы должны использовать kCVPixelFormatType_32BGRA в настройках видео. И NDIlib_FourCC_type_BGRA как четыре CC в NDIlib_video_frame_v2_t.

4 голосов
/ 14 мая 2020

Вы уверены в своем VIDEO_CAPTURE_PIXEL_SIZE?

Когда я работал с NDI на macos, у меня была такая же проблема с черным экраном, и это было из-за неправильного шага линии.

Может быть, это может помочь: https://developer.apple.com/documentation/corevideo/1456964-cvpixelbuffergetbytesperrow?language=objc?

Также кажется, что форматы пикселей из основного видео и NDI не совпадают.

На стороне основного видео, которое вы используете Bi-Planar Y'CbCr 8-bit 4: 2: 0, а на стороне NDI вы используете NDIlib_FourCC_type_UYVY, что соответствует Y'CbCr 4: 2: 2.

Я не могу найдите любой Bi-Planar Y'CbCr 8-битный формат пикселей 4: 2: 0 на стороне NDI.

Возможно, вам повезет больше, если вы воспользуетесь следующей комбинацией:

Надеюсь, это поможет!

0 голосов
/ 16 июня 2020

По моему опыту, у вас две ошибки. Чтобы использовать CVPixelBufferGetBaseAddress CVPixelBuffer, сначала необходимо вызвать метод CVPixelBufferLockBaseAddress. В противном случае возвращается нулевой указатель.

https://developer.apple.com/documentation/corevideo/1457128-cvpixelbufferlockbaseaddress?language=objc

Во-вторых, NDI не поддерживает бипланарность YUV420. (Формат по умолчанию для камер iOS.) Точнее, NDI принимает только один указатель данных. Другими словами, вы должны объединить бипланарные области памяти в одну, а затем передать ее в формате NV12. См. Подробности в документе NDI.

Итак, ваш код должен выглядеть следующим образом: И при асинхронной отправке вместо NDIlib_send_send_video_v2 должна сохраняться сильная ссылка на переданную область памяти, пока не будет завершена операция передачи библиотекой NDI .

CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CVPixelBufferLockBaseAddress(pixelBuffer, 0);
int width = (int)CVPixelBufferGetWidth(pixelBuffer);
int height = (int)CVPixelBufferGetHeight(pixelBuffer);
OSType pixelFormat = CVPixelBufferGetPixelFormatType(pixelBuffer);

NDIlib_FourCC_video_type_e ndiVideoFormat;
uint8_t* pixelData;
int stride;

if (pixelFormat == kCVPixelFormatType_32BGRA) {
    ndiVideoFormat = NDIlib_FourCC_type_BGRA;
    pixelData = (uint8_t*)CVPixelBufferGetBaseAddress(pixelBuffer); // Or copy for asynchronous transmit.
    stride = width * 4;        
} else if (pixelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) {
    ndiVideoFormat = NDIlib_FourCC_type_NV12;
    pixelData = (uint8_t*)malloc(width * height * 1.5);
    uint8_t* yPlane = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0);
    int yPlaneBytesPerRow = (int)CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0);
    int ySize = yPlaneBytesPerRow * height;
    uint8_t* uvPlane = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1);
    int uvPlaneBytesPerRow = (int)CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1);
    int uvSize = uvPlaneBytesPerRow * height;
    stride = yPlaneBytesPerRow;

    memcpy(pixelData, yPlane, ySize);
    memcpy(pixelData + ySize, uvPlane, uvSize);
} else {
    return;
}

NDIlib_video_frame_v2_t video_frame;
video_frame.xres = width;
video_frame.yres = height;
video_frame.FourCC = ndiVideoFormat;
video_frame.line_stride_in_bytes = stride;
video_frame.p_data = pixelData;
NDIlib_send_send_video_v2(self.my_ndi_send, &video_frame); // synchronous sending.

CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);

// For synchrnous sending case. Free data or use pre-allocated memory.
if (pixelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) {
    free(pixelData);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...