diff --git a/src/main.c b/src/main.c index adfe6cd..de8b4b9 100644 --- a/src/main.c +++ b/src/main.c @@ -253,6 +253,10 @@ static void pair_check(PSERVER_DATA server) int main(int argc, char *argv[]) { + // force line buffered mode + setvbuf(stdout, NULL, _IOLBF, 0); + setvbuf(stderr, NULL, _IOLBF, 0); + CONFIGURATION config; config_parse(argc, argv, &config); diff --git a/src/video/dji_net.c b/src/video/dji_net.c index c41e862..6c285f5 100644 --- a/src/video/dji_net.c +++ b/src/video/dji_net.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -11,8 +12,13 @@ #include "dji.h" #include "video.h" -int sockfd = -1; -int frame_counter = 0; +#define ACCEPTABLE_FRAME_TIME 50000000 + +static int sockfd = -1; +static struct timespec last_frame_time = {0, 0}; +// static struct timespec last_key_time = {0, 0}; + +static uint8_t buf[1000000]; static int dji_net_setup(int videoFormat, int width, int height, int redrawRate, void *context, int drFlags) @@ -54,26 +60,54 @@ dji_net_setup(int videoFormat, int width, int height, int redrawRate, void *cont send(sockfd, &header, sizeof(header), 0); + clock_gettime(CLOCK_MONOTONIC, &last_frame_time); + // last_key_time = last_frame_time; + return 0; } static int dji_net_submit_decode_unit(PDECODE_UNIT decodeUnit) { - uint8_t *buf = malloc(decodeUnit->fullLength); - PLENTRY entry = decodeUnit->bufferList; uint32_t length = 0; while (entry != NULL) { + if (length + entry->length > sizeof(buf)) + { + printf("dji_net: Frame too large: %d >= 1Mb\n", length + entry->length); + return DR_NEED_IDR; + } + memcpy(buf + length, entry->data, entry->length); length += entry->length; entry = entry->next; } - send(sockfd, &length, sizeof(length), 0); - send(sockfd, buf, length, 0); + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + uint64_t diff = (now.tv_sec - last_frame_time.tv_sec) * 1000000000 + + (now.tv_nsec - last_frame_time.tv_nsec); + last_frame_time = now; + + if (diff >= ACCEPTABLE_FRAME_TIME && decodeUnit->frameType != FRAME_TYPE_IDR) + { + printf("dji_net: Dropping frame: %llums >= 50ms\n", diff / 1000000); + } + else + { + uint8_t frame_type = decodeUnit->frameType; + send(sockfd, &length, sizeof(length), 0); + send(sockfd, &frame_type, sizeof(frame_type), 0); + send(sockfd, buf, length, 0); + } - free(buf); + // diff = (now.tv_sec - last_key_time.tv_sec) * 1000000000 + + // (now.tv_nsec - last_key_time.tv_nsec); + // if (diff >= 1000000000) + // { + // last_key_time = now; + // return DR_NEED_IDR; + // } return DR_OK; } diff --git a/src/video/dji_usb.c b/src/video/dji_usb.c index cbcd42f..051d49c 100644 --- a/src/video/dji_usb.c +++ b/src/video/dji_usb.c @@ -2,11 +2,12 @@ #include #include #include +#include #include #include #include -#include co +#include #include #include "dji.h" @@ -18,7 +19,14 @@ #define USB_INTERFACE 3 #define USB_ENDPOINT_OUT 0x03 -libusb_device_handle *dev = NULL; +#define ACCEPTABLE_FRAME_TIME 50000000 + +static libusb_device_handle *dev = NULL; + +static struct timespec last_frame_time = {0, 0}; +// static struct timespec last_key_time = {0, 0}; + +static uint8_t buf[1000000]; static int dji_usb_setup(int videoFormat, int width, int height, int redrawRate, void *context, int drFlags) @@ -79,6 +87,9 @@ dji_usb_setup(int videoFormat, int width, int height, int redrawRate, void *cont exit(1); } + clock_gettime(CLOCK_MONOTONIC, &last_frame_time); + // last_key_time = last_frame_time; + return 0; } @@ -91,21 +102,38 @@ static void dji_usb_cleanup(void) static int dji_usb_submit_decode_unit(PDECODE_UNIT decodeUnit) { - uint8_t *buf = malloc(decodeUnit->fullLength); - PLENTRY entry = decodeUnit->bufferList; uint32_t length = 0; while (entry != NULL) { + if (length + entry->length > sizeof(buf)) + { + printf("dji_usb: Frame too large: %d >= 1Mb\n", length + entry->length); + return DR_NEED_IDR; + } + memcpy(buf + length, entry->data, entry->length); length += entry->length; entry = entry->next; } - libusb_bulk_transfer(dev, USB_ENDPOINT_OUT, &length, sizeof(length), NULL, 0); - libusb_bulk_transfer(dev, USB_ENDPOINT_OUT, buf, length, NULL, 0); + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + uint64_t diff = (now.tv_sec - last_frame_time.tv_sec) * 1000000000 + + (now.tv_nsec - last_frame_time.tv_nsec); + last_frame_time = now; - free(buf); + if (diff >= ACCEPTABLE_FRAME_TIME && decodeUnit->frameType != FRAME_TYPE_IDR) + { + printf("dji_net: Dropping frame: %lums >= 50ms\n", diff / 1000000); + } + else + { + uint8_t frame_type = decodeUnit->frameType; + libusb_bulk_transfer(dev, USB_ENDPOINT_OUT, &length, sizeof(length), NULL, 0); + libusb_bulk_transfer(dev, USB_ENDPOINT_OUT, &frame_type, sizeof(frame_type), NULL, 0); + libusb_bulk_transfer(dev, USB_ENDPOINT_OUT, buf, length, NULL, 0); + } return DR_OK; }