Skip to content

Commit

Permalink
Revamp liveview, delete useless memcpys and processing
Browse files Browse the repository at this point in the history
  • Loading branch information
petabyt committed Nov 18, 2024
1 parent 36cbd4b commit abf1aec
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 98 deletions.
8 changes: 0 additions & 8 deletions src/camlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
21 changes: 21 additions & 0 deletions src/canon.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Empty file added src/cl_lv.h
Empty file.
25 changes: 25 additions & 0 deletions src/cl_ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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
92 changes: 10 additions & 82 deletions src/liveview.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,20 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <camlib.h>
#include <ptp.h>

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

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;
Expand All @@ -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) {
Expand Down Expand Up @@ -138,28 +80,14 @@ 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;
}

return PTP_RUNTIME_ERR;
}

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");
}
2 changes: 2 additions & 0 deletions src/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <camlib.h>

int camlib_verbose = 1;
__attribute__((weak))
void ptp_verbose_log(char *fmt, ...) {
if (camlib_verbose) {
va_list args;
Expand All @@ -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;
Expand Down
28 changes: 20 additions & 8 deletions src/ml.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
#include <camlib.h>
#include <ptp.h>

// ptplv v1
#define PTP_ML_LvWidth 360
#define PTP_ML_LvHeight 240

// Destination buffer size
#define SCREEN_WIDTH 720
#define SCREEN_HEIGHT 480
Expand All @@ -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;
Expand All @@ -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];
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit abf1aec

Please sign in to comment.