diff options
| author | rimio <vasi.vilvoiu@gmail.com> | 2019-02-11 02:18:00 +0200 |
|---|---|---|
| committer | rimio <vasi.vilvoiu@gmail.com> | 2019-02-11 02:18:00 +0200 |
| commit | 00ad11118c8c16c5b5d167bba04fea4d8113dd54 (patch) | |
| tree | 7cc6a8601911f4b6f55013ea660a630ba5047a55 | |
| parent | 84a3971982ddd04f3e8cab8be69ae07ef201010d (diff) | |
Remove size_t; precompute timings in microsamples; support all PD modes
| -rw-r--r-- | src/encoder.c | 186 | ||||
| -rw-r--r-- | src/libsstv.template.h | 32 | ||||
| -rw-r--r-- | src/sstv.c | 30 | ||||
| -rw-r--r-- | src/tools/sstv-encode.cpp | 30 |
4 files changed, 211 insertions, 67 deletions
diff --git a/src/encoder.c b/src/encoder.c index 65edc18..7d5655a 100644 --- a/src/encoder.c +++ b/src/encoder.c @@ -10,11 +10,42 @@ #include "luts.h" /* + * Frequencies (all expressed in Hz) + */ +#define LEADER_FREQ 1900 +#define BREAK_FREQ 1200 + +#define VIS_START_STOP_FREQ 1200 +#define VIS_LOW_FREQ 1300 +#define VIS_HIGH_FREQ 1100 + +#define SYNC_FREQ 1200 +#define PORCH_FREQ 1500 + +#define DATA_BASE_FREQ 1500 +#define DATA_BANDWIDTH 800 + +/* + * Durations (useconds) + */ +#define LEADER_TONE_USEC 300000 +#define BREAK_USEC 10000 +#define VIS_BIT_USEC 30000 + +/* * Computation helpers */ -#define MILLISAMPLES_FROM_MICROSECONDS(time_us, sample_rate) ((uint64_t)(time_us) * (uint64_t)(sample_rate) / 1000) +#define MICROSAMPLES_FROM_MICROSECONDS(time_us, sample_rate) ((uint64_t)(time_us) * (uint64_t)(sample_rate)) #define DPHASE_FROM_FREQ(freq, sample_rate) ((((uint64_t)(freq)) << 32) / (uint64_t)(sample_rate)) +#define BYTE_TO_FREQ(b) (DATA_BASE_FREQ + (b) * DATA_BANDWIDTH / 255) + +#define FSK(ctx, usamples, freq) \ + { \ + (ctx)->fsk.phase_delta = DPHASE_FROM_FREQ((freq), context->sample_rate); \ + (ctx)->fsk.remaining_usamp += usamples; \ + } + /* * Encoder state */ @@ -56,7 +87,7 @@ typedef struct { /* output configuration */ sstv_mode_t mode; - size_t sample_rate; + uint32_t sample_rate; /* current state */ sstv_encoder_state_t state; @@ -65,9 +96,16 @@ typedef struct { struct { uint32_t phase; uint32_t phase_delta; - size_t remaining_samples; + uint64_t remaining_usamp; } fsk; + /* mode timings */ + struct { + uint32_t sync_usamp; + uint32_t porch_usamp; + uint32_t pixel_usamp; + } timings; + /* state extra info */ union { struct { @@ -76,8 +114,8 @@ typedef struct { } vis; struct { - size_t curr_line; - size_t curr_col; + uint32_t curr_line; + uint32_t curr_col; } scan; } extra; } sstv_encoder_context_t; @@ -90,7 +128,7 @@ static uint64_t default_encoder_context_usage = 0x0; sstv_error_t -sstv_create_encoder(void **out_ctx, sstv_image_t image, sstv_mode_t mode, size_t sample_rate) +sstv_create_encoder(void **out_ctx, sstv_image_t image, sstv_mode_t mode, uint32_t sample_rate) { sstv_encoder_context_t *ctx = NULL; @@ -101,7 +139,7 @@ sstv_create_encoder(void **out_ctx, sstv_image_t image, sstv_mode_t mode, size_t /* check image properties */ { - size_t w, h; + uint32_t w, h; sstv_image_format_t fmt; sstv_error_t rc; @@ -125,7 +163,7 @@ sstv_create_encoder(void **out_ctx, sstv_image_t image, sstv_mode_t mode, size_t return SSTV_ALLOC_FAIL; } } else { - size_t i; + uint32_t i; /* use default contexts */ for (i = 0; i < SSTV_DEFAULT_ENCODER_CONTEXT_COUNT; i++) { if ((default_encoder_context_usage & (0x1 << i)) == 0) { @@ -145,7 +183,64 @@ sstv_create_encoder(void **out_ctx, sstv_image_t image, sstv_mode_t mode, size_t ctx->sample_rate = sample_rate; ctx->state = SSTV_ENCODER_STATE_START; ctx->fsk.phase = 0; /* start nicely from zero */ - ctx->fsk.remaining_samples = 0; /* so we get initial state change */ + ctx->fsk.remaining_usamp = 0; /* so we get initial state change */ + + /* initialize mode timings */ + switch (mode) { + /* + * PD modes + */ + case SSTV_MODE_PD50: + ctx->timings.sync_usamp = MICROSAMPLES_FROM_MICROSECONDS(20000, sample_rate); + ctx->timings.porch_usamp = MICROSAMPLES_FROM_MICROSECONDS(2080, sample_rate); + ctx->timings.pixel_usamp = MICROSAMPLES_FROM_MICROSECONDS(286, sample_rate); + break; + + case SSTV_MODE_PD90: + ctx->timings.sync_usamp = MICROSAMPLES_FROM_MICROSECONDS(20000, sample_rate); + ctx->timings.porch_usamp = MICROSAMPLES_FROM_MICROSECONDS(2080, sample_rate); + ctx->timings.pixel_usamp = MICROSAMPLES_FROM_MICROSECONDS(532, sample_rate); + break; + + case SSTV_MODE_PD120: + ctx->timings.sync_usamp = MICROSAMPLES_FROM_MICROSECONDS(20000, sample_rate); + ctx->timings.porch_usamp = MICROSAMPLES_FROM_MICROSECONDS(2080, sample_rate); + ctx->timings.pixel_usamp = MICROSAMPLES_FROM_MICROSECONDS(190, sample_rate); + break; + + case SSTV_MODE_PD160: + ctx->timings.sync_usamp = MICROSAMPLES_FROM_MICROSECONDS(20000, sample_rate); + ctx->timings.porch_usamp = MICROSAMPLES_FROM_MICROSECONDS(2080, sample_rate); + ctx->timings.pixel_usamp = MICROSAMPLES_FROM_MICROSECONDS(382, sample_rate); + break; + + case SSTV_MODE_PD180: + ctx->timings.sync_usamp = MICROSAMPLES_FROM_MICROSECONDS(20000, sample_rate); + ctx->timings.porch_usamp = MICROSAMPLES_FROM_MICROSECONDS(2080, sample_rate); + ctx->timings.pixel_usamp = MICROSAMPLES_FROM_MICROSECONDS(286, sample_rate); + break; + + case SSTV_MODE_PD240: + ctx->timings.sync_usamp = MICROSAMPLES_FROM_MICROSECONDS(20000, sample_rate); + ctx->timings.porch_usamp = MICROSAMPLES_FROM_MICROSECONDS(2080, sample_rate); + ctx->timings.pixel_usamp = MICROSAMPLES_FROM_MICROSECONDS(382, sample_rate); + break; + + case SSTV_MODE_PD290: + ctx->timings.sync_usamp = MICROSAMPLES_FROM_MICROSECONDS(20000, sample_rate); + ctx->timings.porch_usamp = MICROSAMPLES_FROM_MICROSECONDS(2080, sample_rate); + ctx->timings.pixel_usamp = MICROSAMPLES_FROM_MICROSECONDS(286, sample_rate); + break; + + /* + * Invalid mode + */ + default: + if (sstv_free_user) { + sstv_free_user(ctx); + } + return SSTV_BAD_MODE; + } /* set output */ *out_ctx = ctx; @@ -157,7 +252,7 @@ sstv_create_encoder(void **out_ctx, sstv_image_t image, sstv_mode_t mode, size_t sstv_error_t sstv_delete_encoder(void *ctx) { - size_t i; + uint32_t i; if (!ctx) { return SSTV_BAD_PARAMETER; @@ -190,9 +285,8 @@ sstv_encode_pd_state_change(sstv_encoder_context_t *context) /* start communication */ if (context->state == SSTV_ENCODER_STATE_VIS_STOP_BIT) { context->state = SSTV_ENCODER_STATE_SYNC; - context->fsk.phase_delta = DPHASE_FROM_FREQ(1200, context->sample_rate); - context->fsk.remaining_samples += MILLISAMPLES_FROM_MICROSECONDS(20000, context->sample_rate); context->extra.scan.curr_line = 0; + FSK(context, context->timings.sync_usamp, SYNC_FREQ); return SSTV_OK; } @@ -202,17 +296,15 @@ sstv_encode_pd_state_change(sstv_encoder_context_t *context) && (context->extra.scan.curr_line < context->image.height-1)) { context->state = SSTV_ENCODER_STATE_SYNC; - context->fsk.phase_delta = DPHASE_FROM_FREQ(1200, context->sample_rate); - context->fsk.remaining_samples += MILLISAMPLES_FROM_MICROSECONDS(20000, context->sample_rate); context->extra.scan.curr_line += 2; + FSK(context, context->timings.sync_usamp, SYNC_FREQ); return SSTV_OK; } /* sync->porch */ if (context->state == SSTV_ENCODER_STATE_SYNC) { context->state = SSTV_ENCODER_STATE_PORCH; - context->fsk.phase_delta = DPHASE_FROM_FREQ(1500, context->sample_rate); - context->fsk.remaining_samples += MILLISAMPLES_FROM_MICROSECONDS(2080, context->sample_rate); + FSK(context, context->timings.porch_usamp, PORCH_FREQ); return SSTV_OK; } @@ -227,10 +319,9 @@ sstv_encode_pd_state_change(sstv_encoder_context_t *context) context->state = SSTV_ENCODER_STATE_Y_EVEN_SCAN; - size_t pix_offset = context->image.width * context->extra.scan.curr_line + context->extra.scan.curr_col; + uint32_t pix_offset = context->image.width * context->extra.scan.curr_line + context->extra.scan.curr_col; uint8_t y = context->image.buffer[pix_offset * 3]; - context->fsk.phase_delta = DPHASE_FROM_FREQ(1500 + y * 800 / 255, context->sample_rate); - context->fsk.remaining_samples += MILLISAMPLES_FROM_MICROSECONDS(190, context->sample_rate); + FSK(context, context->timings.pixel_usamp, BYTE_TO_FREQ(y)); context->extra.scan.curr_col ++; return SSTV_OK; @@ -247,13 +338,12 @@ sstv_encode_pd_state_change(sstv_encoder_context_t *context) context->state = SSTV_ENCODER_STATE_RY_SCAN; - size_t pix_offset_l0 = context->image.width * context->extra.scan.curr_line + context->extra.scan.curr_col; - size_t pix_offset_l1 = context->image.width * (context->extra.scan.curr_line + 1) + context->extra.scan.curr_col; + uint32_t pix_offset_l0 = context->image.width * context->extra.scan.curr_line + context->extra.scan.curr_col; + uint32_t pix_offset_l1 = context->image.width * (context->extra.scan.curr_line + 1) + context->extra.scan.curr_col; uint8_t r1 = context->image.buffer[pix_offset_l0 * 3 + 2]; uint8_t r2 = context->image.buffer[pix_offset_l1 * 3 + 2]; uint8_t r = (r1 + r2) / 2; - context->fsk.phase_delta = DPHASE_FROM_FREQ(1500 + r * 800 / 255, context->sample_rate); - context->fsk.remaining_samples += MILLISAMPLES_FROM_MICROSECONDS(190, context->sample_rate); + FSK(context, context->timings.pixel_usamp, BYTE_TO_FREQ(r)); context->extra.scan.curr_col ++; return SSTV_OK; @@ -270,13 +360,12 @@ sstv_encode_pd_state_change(sstv_encoder_context_t *context) context->state = SSTV_ENCODER_STATE_BY_SCAN; - size_t pix_offset_l0 = context->image.width * context->extra.scan.curr_line + context->extra.scan.curr_col; - size_t pix_offset_l1 = context->image.width * (context->extra.scan.curr_line + 1) + context->extra.scan.curr_col; + uint32_t pix_offset_l0 = context->image.width * context->extra.scan.curr_line + context->extra.scan.curr_col; + uint32_t pix_offset_l1 = context->image.width * (context->extra.scan.curr_line + 1) + context->extra.scan.curr_col; uint8_t b1 = context->image.buffer[pix_offset_l0 * 3 + 1]; uint8_t b2 = context->image.buffer[pix_offset_l1 * 3 + 1]; uint8_t b = (b1 + b2) / 2; - context->fsk.phase_delta = DPHASE_FROM_FREQ(1500 + b * 800 / 255, context->sample_rate); - context->fsk.remaining_samples += MILLISAMPLES_FROM_MICROSECONDS(190, context->sample_rate); + FSK(context, context->timings.pixel_usamp, BYTE_TO_FREQ(b)); context->extra.scan.curr_col ++; return SSTV_OK; @@ -293,10 +382,9 @@ sstv_encode_pd_state_change(sstv_encoder_context_t *context) context->state = SSTV_ENCODER_STATE_Y_ODD_SCAN; - size_t pix_offset = context->image.width * (context->extra.scan.curr_line + 1) + context->extra.scan.curr_col; + uint32_t pix_offset = context->image.width * (context->extra.scan.curr_line + 1) + context->extra.scan.curr_col; uint8_t y = context->image.buffer[pix_offset * 3]; - context->fsk.phase_delta = DPHASE_FROM_FREQ(1500 + y * 800 / 255, context->sample_rate); - context->fsk.remaining_samples += MILLISAMPLES_FROM_MICROSECONDS(190, context->sample_rate); + FSK(context, context->timings.pixel_usamp, BYTE_TO_FREQ(y)); context->extra.scan.curr_col ++; return SSTV_OK; @@ -313,32 +401,36 @@ sstv_encode_state_change(sstv_encoder_context_t *context) /* leader tone #1 */ if (context->state == SSTV_ENCODER_STATE_START) { context->state = SSTV_ENCODER_STATE_LEADER_TONE_1; - context->fsk.phase_delta = DPHASE_FROM_FREQ(1900, context->sample_rate); - context->fsk.remaining_samples += MILLISAMPLES_FROM_MICROSECONDS(300000, context->sample_rate); + FSK(context, + MICROSAMPLES_FROM_MICROSECONDS(LEADER_TONE_USEC, context->sample_rate), + LEADER_FREQ); return SSTV_OK; } /* break */ if (context->state == SSTV_ENCODER_STATE_LEADER_TONE_1) { context->state = SSTV_ENCODER_STATE_BREAK; - context->fsk.phase_delta = DPHASE_FROM_FREQ(1200, context->sample_rate); - context->fsk.remaining_samples += MILLISAMPLES_FROM_MICROSECONDS(10000, context->sample_rate); + FSK(context, + MICROSAMPLES_FROM_MICROSECONDS(BREAK_USEC, context->sample_rate), + BREAK_FREQ); return SSTV_OK; } /* leader tone #2 */ if (context->state == SSTV_ENCODER_STATE_BREAK) { context->state = SSTV_ENCODER_STATE_LEADER_TONE_2; - context->fsk.phase_delta = DPHASE_FROM_FREQ(1900, context->sample_rate); - context->fsk.remaining_samples += MILLISAMPLES_FROM_MICROSECONDS(300000, context->sample_rate); + FSK(context, + MICROSAMPLES_FROM_MICROSECONDS(LEADER_TONE_USEC, context->sample_rate), + LEADER_FREQ); return SSTV_OK; } /* VIS start bit */ if (context->state == SSTV_ENCODER_STATE_LEADER_TONE_2) { context->state = SSTV_ENCODER_STATE_VIS_START_BIT; - context->fsk.phase_delta = DPHASE_FROM_FREQ(1200, context->sample_rate); - context->fsk.remaining_samples += MILLISAMPLES_FROM_MICROSECONDS(30000, context->sample_rate); + FSK(context, + MICROSAMPLES_FROM_MICROSECONDS(VIS_BIT_USEC, context->sample_rate), + VIS_START_STOP_FREQ); context->extra.vis.visp = sstv_get_visp_code(context->mode); context->extra.vis.curr_bit = 0; return SSTV_OK; @@ -351,27 +443,31 @@ sstv_encode_state_change(sstv_encoder_context_t *context) uint8_t bit = (context->extra.vis.visp >> context->extra.vis.curr_bit) & 0x1; context->state = SSTV_ENCODER_STATE_VIS_BIT; context->extra.vis.curr_bit ++; - context->fsk.phase_delta = DPHASE_FROM_FREQ((bit ? 1100 : 1300), context->sample_rate); - context->fsk.remaining_samples += MILLISAMPLES_FROM_MICROSECONDS(30000, context->sample_rate); + FSK(context, + MICROSAMPLES_FROM_MICROSECONDS(VIS_BIT_USEC, context->sample_rate), + (bit ? VIS_HIGH_FREQ : VIS_LOW_FREQ)); return SSTV_OK; } /* VIS stop bit */ if (context->state == SSTV_ENCODER_STATE_VIS_BIT) { context->state = SSTV_ENCODER_STATE_VIS_STOP_BIT; - context->fsk.phase_delta = DPHASE_FROM_FREQ(1200, context->sample_rate); - context->fsk.remaining_samples += MILLISAMPLES_FROM_MICROSECONDS(30000, context->sample_rate); + FSK(context, + MICROSAMPLES_FROM_MICROSECONDS(VIS_BIT_USEC, context->sample_rate), + VIS_START_STOP_FREQ); return SSTV_OK; } /* call state change routine for specific mode */ switch (context->mode) { /* PD modes */ + case SSTV_MODE_PD50: case SSTV_MODE_PD90: case SSTV_MODE_PD120: case SSTV_MODE_PD160: case SSTV_MODE_PD180: case SSTV_MODE_PD240: + case SSTV_MODE_PD290: return sstv_encode_pd_state_change(context); default: @@ -395,7 +491,7 @@ sstv_encode(void *ctx, sstv_signal_t *signal) /* main encoding loop */ while (1) { /* state change? */ - if (context->fsk.remaining_samples < 1000) { + if (context->fsk.remaining_usamp < 1000000) { rc = sstv_encode_state_change(context); if (rc != SSTV_OK) { return rc; @@ -407,7 +503,7 @@ sstv_encode(void *ctx, sstv_signal_t *signal) } /* make sure we don't skip a state */ - if (context->fsk.remaining_samples < 1000) { + if (context->fsk.remaining_usamp < 1000000) { /* this should not happen for a proper sample rate */ return SSTV_INTERNAL_ERROR; } @@ -421,7 +517,7 @@ sstv_encode(void *ctx, sstv_signal_t *signal) } /* encode sample and continue */ - context->fsk.remaining_samples -= 1000; + context->fsk.remaining_usamp -= 1000000; context->fsk.phase += context->fsk.phase_delta; switch(signal->type) { case SSTV_SAMPLE_INT8: diff --git a/src/libsstv.template.h b/src/libsstv.template.h index ce4cf26..7338da9 100644 --- a/src/libsstv.template.h +++ b/src/libsstv.template.h @@ -8,6 +8,10 @@ #ifndef _LIBSSTV_H_ #define _LIBSSTV_H_ +#ifdef __cplusplus +extern "C" { +#endif + #include <stdint.h> #include <stddef.h> @@ -59,11 +63,13 @@ typedef enum { */ typedef enum { /* PD modes */ + SSTV_MODE_PD50, SSTV_MODE_PD90, SSTV_MODE_PD120, SSTV_MODE_PD160, SSTV_MODE_PD180, - SSTV_MODE_PD240 + SSTV_MODE_PD240, + SSTV_MODE_PD290 } sstv_mode_t; /* @@ -91,8 +97,8 @@ typedef enum { */ typedef struct { /* image properties */ - size_t width; - size_t height; + uint32_t width; + uint32_t height; sstv_image_format_t format; /* image buffer */ @@ -116,16 +122,16 @@ typedef struct { void *buffer; /* size in bytes */ - size_t size; + uint32_t size; /* sample type */ sstv_sample_type_t type; /* number of total samples */ - size_t capacity; + uint32_t capacity; /* number of used samples */ - size_t count; + uint32_t count; } sstv_signal_t; @@ -148,7 +154,7 @@ extern sstv_error_t sstv_init(sstv_malloc_t alloc_func, sstv_free_t dealloc_func * format(out): pixel format * returns: error code */ -extern sstv_error_t sstv_get_mode_image_props(sstv_mode_t mode, size_t *width, size_t *height, sstv_image_format_t *format); +extern sstv_error_t sstv_get_mode_image_props(sstv_mode_t mode, uint32_t *width, uint32_t *height, sstv_image_format_t *format); /* * Create an image given an SSTV mode. @@ -176,7 +182,7 @@ extern sstv_error_t sstv_create_image_from_mode(sstv_image_t *out_img, sstv_mode * NOTE: The resulting image must be deleted using sstv_delete_image() once it * goes out of scope (i.e. after the encoder is deleted). */ -extern sstv_error_t sstv_create_image_from_props(sstv_image_t *out_img, size_t w, size_t h, sstv_image_format_t format); +extern sstv_error_t sstv_create_image_from_props(sstv_image_t *out_img, uint32_t w, uint32_t h, sstv_image_format_t format); /* * Deletes an image. @@ -212,7 +218,7 @@ extern sstv_error_t sstv_convert_image(sstv_image_t *img, sstv_image_format_t fo * NOTE: Pixel buffer is managed by user. Do NOT call sstv_delete_image() on * resulting image. */ -extern sstv_error_t sstv_pack_image(sstv_image_t *out_img, size_t width, size_t height, sstv_image_format_t format, uint8_t *buffer); +extern sstv_error_t sstv_pack_image(sstv_image_t *out_img, uint32_t width, uint32_t height, sstv_image_format_t format, uint8_t *buffer); /* * Pack a signal buffer into a signal structure. @@ -224,7 +230,7 @@ extern sstv_error_t sstv_pack_image(sstv_image_t *out_img, size_t width, size_t * * NOTE: Buffer is managed by user. */ -extern sstv_error_t sstv_pack_signal(sstv_signal_t *sig, sstv_sample_type_t type, size_t capacity, void *buffer); +extern sstv_error_t sstv_pack_signal(sstv_signal_t *sig, sstv_sample_type_t type, uint32_t capacity, void *buffer); /* * Create an SSTV encoder. @@ -241,7 +247,7 @@ extern sstv_error_t sstv_pack_signal(sstv_signal_t *sig, sstv_sample_type_t type * SSTV_DEFAULT_ENCODER_CONTEXT_COUNT default structures, and once these are * used up, a SSTV_NO_DEFAULT_ENCODERS error is returned. */ -extern sstv_error_t sstv_create_encoder(void **out_ctx, sstv_image_t image, sstv_mode_t mode, size_t sample_rate); +extern sstv_error_t sstv_create_encoder(void **out_ctx, sstv_image_t image, sstv_mode_t mode, uint32_t sample_rate); /* * Deletes an SSTV encoder. @@ -263,4 +269,8 @@ extern sstv_error_t sstv_delete_encoder(void *ctx); */ extern sstv_error_t sstv_encode(void *ctx, sstv_signal_t *signal); +#ifdef __cplusplus +} +#endif + #endif
\ No newline at end of file @@ -151,10 +151,16 @@ sstv_convert_image(sstv_image_t *img, sstv_image_format_t format) } sstv_error_t -sstv_get_mode_image_props(sstv_mode_t mode, size_t *width, size_t *height, sstv_image_format_t *format) +sstv_get_mode_image_props(sstv_mode_t mode, uint32_t *width, uint32_t *height, sstv_image_format_t *format) { switch (mode) { /* PD modes */ + case SSTV_MODE_PD50: + if (width) *width = 320; + if (height) *height = 256; + if (format) *format = SSTV_FORMAT_YCBCR; + break; + case SSTV_MODE_PD90: if (width) *width = 320; if (height) *height = 256; @@ -185,6 +191,12 @@ sstv_get_mode_image_props(sstv_mode_t mode, size_t *width, size_t *height, sstv_ if (format) *format = SSTV_FORMAT_YCBCR; break; + case SSTV_MODE_PD290: + if (width) *width = 800; + if (height) *height = 616; + if (format) *format = SSTV_FORMAT_YCBCR; + break; + default: return SSTV_BAD_MODE; } @@ -195,7 +207,7 @@ sstv_get_mode_image_props(sstv_mode_t mode, size_t *width, size_t *height, sstv_ sstv_error_t sstv_create_image_from_mode(sstv_image_t *out_img, sstv_mode_t mode) { - size_t w, h; + uint32_t w, h; sstv_image_format_t fmt; sstv_error_t rc; @@ -208,9 +220,9 @@ sstv_create_image_from_mode(sstv_image_t *out_img, sstv_mode_t mode) } sstv_error_t -sstv_create_image_from_props(sstv_image_t *out_img, size_t w, size_t h, sstv_image_format_t format) +sstv_create_image_from_props(sstv_image_t *out_img, uint32_t w, uint32_t h, sstv_image_format_t format) { - size_t bsize; + uint32_t bsize; if (!out_img) { return SSTV_BAD_PARAMETER; @@ -255,7 +267,7 @@ sstv_create_image_from_props(sstv_image_t *out_img, size_t w, size_t h, sstv_ima } sstv_error_t -sstv_pack_image(sstv_image_t *out_img, size_t width, size_t height, sstv_image_format_t format, uint8_t *buffer) +sstv_pack_image(sstv_image_t *out_img, uint32_t width, uint32_t height, sstv_image_format_t format, uint8_t *buffer) { if (!out_img || !buffer) { return SSTV_BAD_PARAMETER; @@ -294,7 +306,7 @@ sstv_delete_image(sstv_image_t *img) } sstv_error_t -sstv_pack_signal(sstv_signal_t *sig, sstv_sample_type_t type, size_t capacity, void *buffer) +sstv_pack_signal(sstv_signal_t *sig, sstv_sample_type_t type, uint32_t capacity, void *buffer) { if (!sig) { return SSTV_BAD_PARAMETER; @@ -327,6 +339,9 @@ uint8_t sstv_get_visp_code(sstv_mode_t mode) { switch (mode) { + case SSTV_MODE_PD50: + return 221; + case SSTV_MODE_PD90: return 99; @@ -342,6 +357,9 @@ sstv_get_visp_code(sstv_mode_t mode) case SSTV_MODE_PD240: return 225; + case SSTV_MODE_PD290: + return 222; + default: return 0; } diff --git a/src/tools/sstv-encode.cpp b/src/tools/sstv-encode.cpp index 48c6623..fa673b6 100644 --- a/src/tools/sstv-encode.cpp +++ b/src/tools/sstv-encode.cpp @@ -13,20 +13,40 @@ #include <Magick++.h> #include <sndfile.h> -extern "C" { #include <libsstv.h> -} /* * Command line flags */ - DEFINE_bool(logtostderr, false, "Only log to stderr"); DEFINE_string(mode, "", "SSTV mode for encoder"); DEFINE_string(input, "", "input image"); DEFINE_string(output, "", "output WAV file"); DEFINE_uint64(sample_rate, 48000, "output audio sample rate"); +sstv_mode_t mode_from_string(std::string mode) +{ + std::transform(mode.begin(), mode.end(), mode.begin(), ::toupper); + + if (mode == "PD50") { + return SSTV_MODE_PD50; + } else if (mode == "PD90") { + return SSTV_MODE_PD90; + } else if (mode == "PD120") { + return SSTV_MODE_PD120; + } else if (mode == "PD160") { + return SSTV_MODE_PD160; + } else if (mode == "PD180") { + return SSTV_MODE_PD180; + } else if (mode == "PD240") { + return SSTV_MODE_PD240; + } else if (mode == "PD290") { + return SSTV_MODE_PD290; + } else { + LOG(FATAL) << "Unknown mode '" << mode << "'"; + } +} + int main(int argc, char **argv) { /* Parse command line flags */ @@ -48,10 +68,10 @@ int main(int argc, char **argv) } /* TODO: parse SSTV mode */ - sstv_mode_t mode = SSTV_MODE_PD120; + sstv_mode_t mode = mode_from_string(FLAGS_mode); /* get image properties for chosen mode */ - size_t width, height; + uint32_t width, height; sstv_image_format_t format; if (sstv_get_mode_image_props(mode, &width, &height, &format) != SSTV_OK) { LOG(FATAL) << "sstv_get_mode_image_props() failed"; |
