From abf1aec152907e9b0175fb4f89d8041a4d921590 Mon Sep 17 00:00:00 2001 From: Daniel C Date: Sun, 17 Nov 2024 22:18:59 -0500 Subject: [PATCH] Revamp liveview, delete useless memcpys and processing --- src/camlib.h | 8 ----- src/canon.c | 21 ++++++++++++ src/cl_lv.h | 0 src/cl_ops.h | 25 ++++++++++++++ src/liveview.c | 92 ++++++-------------------------------------------- src/log.c | 2 ++ src/ml.c | 28 ++++++++++----- 7 files changed, 78 insertions(+), 98 deletions(-) create mode 100644 src/cl_lv.h diff --git a/src/camlib.h b/src/camlib.h index ffee9ea..5cbf54e 100644 --- a/src/camlib.h +++ b/src/camlib.h @@ -65,14 +65,6 @@ enum PtpGeneralError { /// @brief Evaluates PtpGeneralError into string message const char *ptp_perror(int rc); -enum PtpLiveViewType { - PTP_LV_NONE = 0, - PTP_LV_EOS = 1, - PTP_LV_CANON = 2, - PTP_LV_ML = 3, // ptplv v1 - PTP_LV_EOS_ML_BMP = 4, // ptplv v2 -}; - /// @brief Unique camera types - each type should have similar opcodes and behavior enum PtpVendors { PTP_DEV_EMPTY = 0, diff --git a/src/canon.c b/src/canon.c index 0286d95..910496c 100644 --- a/src/canon.c +++ b/src/canon.c @@ -218,3 +218,24 @@ int ptp_eos_update_firmware(struct PtpRuntime *r, FILE *f, char *name) { } } } + +int ptp_eos_get_liveview(struct PtpRuntime *r) { + int rc = ptp_eos_get_viewfinder_data(r); + if (rc == PTP_CHECK_CODE) { + if (ptp_get_return_code(r) == PTP_RC_CANON_NotReady) { + return 0; + } + } else if (rc) return rc; + + uint32_t length, type; + + uint8_t *d = ptp_get_payload(r); + d += ptp_read_u32(d, &length); + d += ptp_read_u32(d, &type); + + if (length == 0) { + return 0; + } + + return length; +} diff --git a/src/cl_lv.h b/src/cl_lv.h new file mode 100644 index 0000000..e69de29 diff --git a/src/cl_ops.h b/src/cl_ops.h index d3d8da1..8da0b3b 100644 --- a/src/cl_ops.h +++ b/src/cl_ops.h @@ -2,6 +2,27 @@ #ifndef OPERATIONS_H #define OPERATIONS_H +enum PtpLiveViewType { + PTP_LV_NONE = 0, + PTP_LV_EOS = 1, + PTP_LV_CANON = 2, + // ptpview v1, Old 360x240 manually computed 7fps liveview + PTP_LV_ML = 3, + // ptpview v2, only has bmp menu graphics + PTP_LV_EOS_ML_BMP = 4, +}; + +enum PtpLiveViewFormat { + PTP_LV_JPEG, +}; + +struct PtpLiveviewParams { + uint32_t payload_offset_to_data; + enum PtpLiveViewFormat format; +}; + +int ptp_liveview_params(struct PtpRuntime *r, struct PtpLiveviewParams *params); + /// @brief Set a generic property - abstraction over SetDeviceProp /// @note May reject writes if an invalid property is found (see event code) /// @memberof PtpRuntime @@ -139,6 +160,7 @@ int ptp_liveview_type(struct PtpRuntime *r); // Get Magic Lantern transparent menus buffer - see https://github.com/petabyt/ptpview int ptp_ml_init_bmp_lv(struct PtpRuntime *r); int ptp_ml_get_bmp_lv(struct PtpRuntime *r, uint32_t **buffer_ptr); +int ptp_ml_get_liveview_v1(struct PtpRuntime *r); int ptp_chdk_get_version(struct PtpRuntime *r); int ptp_chdk_upload_file(struct PtpRuntime *r, char *input, char *dest); @@ -150,4 +172,7 @@ int ptp_eos_evproc_run(struct PtpRuntime *r, char *fmt, ...); int ptp_eos_evproc_return_data(struct PtpRuntime *r); int ptp_eos_fa_get_build_version(struct PtpRuntime *r, char *buffer, int max); +/// @returns enum PtpGeneralError, 0 for 'camera is busy', or the size of the image in the payload +int ptp_eos_get_liveview(struct PtpRuntime *r); + #endif diff --git a/src/liveview.c b/src/liveview.c index c8a434b..bb346e1 100644 --- a/src/liveview.c +++ b/src/liveview.c @@ -7,33 +7,13 @@ #include #include #include - #include #include -#define MAX_EOS_JPEG_SIZE 550000 - -// Transparency pixel used in liveview processor. Will be packed as RGB uint32 -// uncompressed array of pixels in little-endian. This will be used as the first byte. -#ifndef PTP_LV_TRANSPARENCY_PIXEL - #define PTP_LV_TRANSPARENCY_PIXEL 0x0 -#endif - -#define PTP_ML_LvWidth 360 -#define PTP_ML_LvHeight 240 - -int ptp_get_ml_lv1(struct PtpRuntime *r) { - struct PtpCommand cmd; - cmd.code = PTP_OC_ML_Live360x240; - cmd.param_length = 0; - - return ptp_send(r, &cmd); -} - int ptp_liveview_type(struct PtpRuntime *r) { int type = ptp_device_type(r); if (type == PTP_DEV_CANON || type == PTP_DEV_EOS) { - #ifndef NO_ML_LV + // TODO: allow changing of EOS/ML liveview priority if (ptp_check_opcode(r, PTP_OC_ML_Live360x240)) { return PTP_LV_ML; } @@ -41,7 +21,6 @@ int ptp_liveview_type(struct PtpRuntime *r) { if (ptp_check_opcode(r, PTP_OC_ML_LiveBmpRam)) { return PTP_LV_EOS_ML_BMP; } - #endif if (ptp_check_opcode(r, PTP_OC_EOS_GetViewFinderData)) { return PTP_LV_EOS; @@ -55,56 +34,19 @@ int ptp_liveview_type(struct PtpRuntime *r) { return PTP_LV_NONE; } -int ptp_liveview_size(struct PtpRuntime *r) { +int ptp_liveview_params(struct PtpRuntime *r, struct PtpLiveviewParams *params) { switch (ptp_liveview_type(r)) { - case PTP_LV_ML: - return PTP_ML_LvWidth * PTP_ML_LvHeight * 4; case PTP_LV_EOS: - case PTP_LV_EOS_ML_BMP: - return MAX_EOS_JPEG_SIZE; + params->payload_offset_to_data = 8; + params->format = PTP_LV_JPEG; + break; } return 0; } -int ptp_liveview_ml(struct PtpRuntime *r, uint8_t *buffer) { - int a = ptp_get_ml_lv1(r); - if (a < 0) { - return PTP_IO_ERR; - } else if (ptp_get_return_code(r) != PTP_RC_OK) { - return PTP_CHECK_CODE; - } - - uint8_t *data = ptp_get_payload(r); - int length = (PTP_ML_LvWidth * PTP_ML_LvHeight); - - for (int i = 0; i < length; i++) { - buffer[0] = data[0]; - buffer[1] = data[1]; - buffer[2] = data[2]; - buffer[3] = PTP_LV_TRANSPARENCY_PIXEL; - buffer += 4; - data += 3; - } - - return length * 4; -} - -int ptp_liveview_eos(struct PtpRuntime *r, uint8_t *buffer) { - int x = ptp_eos_get_viewfinder_data(r); - if (x < 0) return x; - - if (ptp_get_return_code(r) == PTP_RC_CANON_NotReady) { - return 0; - } - - struct PtpEOSViewFinderData *vfd = (struct PtpEOSViewFinderData *)(ptp_get_payload(r)); - if (MAX_EOS_JPEG_SIZE < vfd->length) { - return 0; - } - - memcpy(buffer, ptp_get_payload(r) + 8, vfd->length); - return vfd->length; +int ptp_liveview_size(struct PtpRuntime *r) { + ptp_panic("deprecated"); } int ptp_liveview_init(struct PtpRuntime *r) { @@ -138,7 +80,8 @@ int ptp_liveview_deinit(struct PtpRuntime *r) { // if (x) return x; x = ptp_eos_set_prop_value(r, PTP_DPC_EOS_CaptureDestination, 2); if (x) return x; - ptp_eos_hdd_capacity_push(r); + x = ptp_eos_hdd_capacity_push(r); + if (x) return x; return 0; } @@ -146,20 +89,5 @@ int ptp_liveview_deinit(struct PtpRuntime *r) { } int ptp_liveview_frame(struct PtpRuntime *r, void *buffer) { - switch (ptp_liveview_type(r)) { - case PTP_LV_ML: - return ptp_liveview_ml(r, (uint8_t *)buffer); - case PTP_LV_EOS_ML_BMP: - case PTP_LV_EOS: { - int rc = ptp_liveview_eos(r, (uint8_t *)buffer); - // Sleep a little to prevent tons of requests while LV is idle - if (rc == PTP_CHECK_CODE) { - CAMLIB_SLEEP(100); - return 0; - } - return rc; - } - } - - return PTP_UNSUPPORTED; + ptp_panic("deprecated"); } diff --git a/src/log.c b/src/log.c index 4937ca6..3884dd5 100644 --- a/src/log.c +++ b/src/log.c @@ -6,6 +6,7 @@ #include int camlib_verbose = 1; +__attribute__((weak)) void ptp_verbose_log(char *fmt, ...) { if (camlib_verbose) { va_list args; @@ -16,6 +17,7 @@ void ptp_verbose_log(char *fmt, ...) { } __attribute__ ((noreturn)) +__attribute__((weak)) void ptp_panic(char *fmt, ...) { printf("PTP abort: "); va_list args; diff --git a/src/ml.c b/src/ml.c index 01ad314..0cd77b9 100644 --- a/src/ml.c +++ b/src/ml.c @@ -8,6 +8,10 @@ #include #include +// ptplv v1 +#define PTP_ML_LvWidth 360 +#define PTP_ML_LvHeight 240 + // Destination buffer size #define SCREEN_WIDTH 720 #define SCREEN_HEIGHT 480 @@ -18,12 +22,12 @@ static struct PtpMlLvInfo lv_info = {0}; -int yuv2rgb_rv[256]; -int yuv2rgb_gu[256]; -int yuv2rgb_gv[256]; -int yuv2rgb_bu[256]; +static int yuv2rgb_rv[256]; +static int yuv2rgb_gu[256]; +static int yuv2rgb_gv[256]; +static int yuv2rgb_bu[256]; -void precompute_yuv2rgb() { +static void precompute_yuv2rgb() { for (int u = 0; u < 256; u++) { int8_t U = u; yuv2rgb_gu[u] = (-352 * U) / 1024; @@ -37,11 +41,11 @@ void precompute_yuv2rgb() { } } -int coerce(int x, int lo, int hi) { +static inline int coerce(int x, int lo, int hi) { return ((x) < (lo)) ? (lo) : (((x) > (hi)) ? (hi) : (x)); } -void yuv2rgb(uint8_t Y, uint8_t U, uint8_t V, uint8_t *R, uint8_t *G, uint8_t *B) { +static void yuv2rgb(uint8_t Y, uint8_t U, uint8_t V, uint8_t *R, uint8_t *G, uint8_t *B) { int v_and_ff = V & 0xFF; int u_and_ff = U & 0xFF; int v = Y + yuv2rgb_rv[v_and_ff]; @@ -73,8 +77,8 @@ int ptp_ml_init_bmp_lv(struct PtpRuntime *r) { int ptp_ml_get_bmp_lv(struct PtpRuntime *r, uint32_t **buffer_ptr) { buffer_ptr[0] = NULL; + // Every 100 calls, get the LUT and bmp spec info static int toggle = 0; - toggle++; if (toggle > 100) { ptp_ml_init_bmp_lv(r); @@ -147,6 +151,14 @@ int ptp_ml_get_bmp_lv(struct PtpRuntime *r, uint32_t **buffer_ptr) { return 0; } +int ptp_ml_get_liveview_v1(struct PtpRuntime *r) { + struct PtpCommand cmd; + cmd.code = PTP_OC_ML_Live360x240; + cmd.param_length = 0; + + return ptp_send(r, &cmd); +} + int ptp_chdk_upload_file(struct PtpRuntime *r, char *input, char *dest) { struct PtpCommand cmd; cmd.code = PTP_OC_CHDK;