From df553c5d0dfe33d1d852969c72891e18e0fa0fe3 Mon Sep 17 00:00:00 2001 From: Bubbadime <146256626+Bubbadime@users.noreply.github.com> Date: Tue, 1 Jul 2025 18:12:01 +0100 Subject: [PATCH 01/14] Add basic library usage and testing --- .gitignore | 3 + Makefile | 14 ++- ssdv.c | 10 ++ ssdvutils.c | 353 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ssdvutils.h | 46 +++++++ test.c | 60 +++++++++ 6 files changed, 484 insertions(+), 2 deletions(-) mode change 100644 => 100755 .gitignore mode change 100644 => 100755 Makefile mode change 100644 => 100755 ssdv.c create mode 100755 ssdvutils.c create mode 100755 ssdvutils.h create mode 100755 test.c diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 index 57592d9..a088a38 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ ssdv +test *.o +*.lo +*.so *.jpeg *.bin* diff --git a/Makefile b/Makefile old mode 100644 new mode 100755 index 02a03cf..ed8a797 --- a/Makefile +++ b/Makefile @@ -3,18 +3,28 @@ CC=gcc CFLAGS=-g -O3 -Wall LDFLAGS=-g -all: ssdv +all: ssdv libssdv.so test ssdv: main.o ssdv.o rs8.o ssdv.h rs8.h $(CC) $(LDFLAGS) main.o ssdv.o rs8.o -o ssdv +libssdv.so: ssdvutils.lo ssdv.lo rs8.lo ssdv.h rs8.h + $(CC) -shared $(LDFLAGS) ssdvutils.lo ssdv.lo rs8.lo -o libssdv.so + +test: test.c libssdv.so + $(CC) $(LDFLAGS) test.c -l:libssdv.so -o test + .c.o: $(CC) $(CFLAGS) -c $< -o $@ +%.lo : %.c + $(CC) $(CFLAGS) -fPIC -c $< -o $@ + install: all mkdir -p ${DESTDIR}/usr/bin install -m 755 ssdv ${DESTDIR}/usr/bin + install -m 755 libssdv.so ${DESTDIR}/usr/lib clean: - rm -f *.o ssdv + rm -f *.o *.lo ssdv libssdv.so test diff --git a/ssdv.c b/ssdv.c old mode 100644 new mode 100755 index 92c537e..4d76c94 --- a/ssdv.c +++ b/ssdv.c @@ -675,6 +675,7 @@ static char ssdv_have_marker(ssdv_t *s) /* Copy the data before processing */ if(s->marker_len > TBL_LEN + HBUFF_LEN - s->stbl_len) { + printf("SSDV out of memory - marker len = %hu\n", s->marker_len); /* Not enough memory ... shouldn't happen! */ return(SSDV_ERROR); } @@ -979,6 +980,8 @@ char ssdv_enc_get_packet(ssdv_t *s) /* If the output buffer is empty, re-initialise */ if(s->out_len == 0) ssdv_enc_set_buffer(s, s->out); + printf("Get packet:\n"); + printf("stbl_len: %hu\n", s->stbl_len); while(s->in_len) { b = *(s->inp++); @@ -987,9 +990,11 @@ char ssdv_enc_get_packet(ssdv_t *s) /* Skip bytes if necessary */ if(s->in_skip) { s->in_skip--; continue; } + printf("Marker 0x%hx, length %hu: ", s->marker, s->marker_len); switch(s->state) { case S_MARKER: + printf("S_MARKER\n"); s->marker = (s->marker << 8) | b; if(s->marker == J_TEM || @@ -1010,6 +1015,7 @@ char ssdv_enc_get_packet(ssdv_t *s) break; case S_MARKER_LEN: + printf("S_MARKER_LEN\n"); s->marker_len = (s->marker_len << 8) | b; if((s->needbits -= 8) == 0) { @@ -1020,6 +1026,7 @@ char ssdv_enc_get_packet(ssdv_t *s) break; case S_MARKER_DATA: + printf("S_MARKER_DATA\n"); s->marker_data[s->marker_data_len++] = b; if(s->marker_data_len == s->marker_len) { @@ -1029,7 +1036,9 @@ char ssdv_enc_get_packet(ssdv_t *s) break; case S_HUFF: + printf("S_HUFF\n"); case S_INT: + printf("S_INT\n"); /* Is the next byte a stuffing byte? Skip it */ /* TODO: Test the next byte is actually 0x00 */ if(b == 0xFF) s->in_skip++; @@ -1116,6 +1125,7 @@ char ssdv_enc_get_packet(ssdv_t *s) break; case S_EOI: + printf("S_EOI\n"); /* Shouldn't reach this point */ break; } diff --git a/ssdvutils.c b/ssdvutils.c new file mode 100755 index 0000000..66edf00 --- /dev/null +++ b/ssdvutils.c @@ -0,0 +1,353 @@ + +/* SSDV - Slow Scan Digital Video */ +/*=======================================================================*/ +/* Copyright 2011-2016 Philip Heron */ +/* */ +/* This program is free software: you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, either version 3 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program. If not, see . */ + +/* + * ssdvutils.h added by GLRobotics 2025 + */ + +#include +#include +#include +#include +#include +#include "ssdv.h" +#include "ssdvutils.h" + +ssdv_mem_arena_t ssdv_read_file(FILE* f) { + ssdv_mem_arena_t result = {0}; + size_t fcur = ftell(f); + fseek(f, 0, SEEK_END); + size_t fsize = ftell(f); + result.buf = malloc(fsize); + result.length = fsize; + fseek(f, 0, SEEK_SET); + fread(result.buf, result.length, 1, f); + result.used = fsize; + fseek(f, fcur, SEEK_SET); + return result; +} + +size_t ssdv_memcpy_packet(ssdv_mem_arena_t *src, ssdv_mem_arena_t *dest, size_t read_offset, size_t pkt_length) { + size_t src_avail = src->length - read_offset; + size_t dest_avail = dest->length - dest->used; + size_t copy_length = (src_avail < dest_avail)? src_avail : dest_avail; + copy_length = (copy_length < pkt_length)? copy_length : pkt_length; + memcpy(dest->buf + dest->used, src->buf + read_offset, copy_length); + dest->used += copy_length; + return copy_length; + +} + +ssdv_mem_arena_t ssdv_dec_buf(ssdv_mem_arena_t *src, ssdv_t *ssdv) { + + ssdv_mem_arena_t result = {0}; + int src_good = src->buf != 0 && src->length > 0; + + int i, c; + int droptest = 0; + int verbose = 1; + int errors; + int pkt_length = SSDV_PKT_SIZE; + int skipped; + + uint8_t pkt[SSDV_PKT_SIZE], *jpeg; + size_t jpeg_length; + + ssdv_mem_arena_t pkt_arena = {0}; + pkt_arena.buf = pkt; + pkt_arena.length = SSDV_PKT_SIZE; + + if (!src_good) { + fprintf(stderr, "Buffer error. Src: %p %u\n", src->buf, src->length); + return result; + } + + jpeg_length = 1024 * 1024 * 4; + jpeg = malloc(jpeg_length); + ssdv_dec_set_buffer(ssdv, jpeg, jpeg_length); + result.length = jpeg_length; + + i = 0; + + size_t read_offset = 0; + size_t bytes_read = 0; + while((bytes_read = ssdv_memcpy_packet(src, &pkt_arena, read_offset, pkt_length)) > 0) + { + read_offset += bytes_read; + /* Drop % of packets */ + if(droptest && (rand() / (RAND_MAX / 100) < droptest)) continue; + + /* Test the packet is valid */ + skipped = 0; + while((c = ssdv_dec_is_packet(pkt, pkt_length, &errors)) != 0) + { + /* Read 1 byte at a time until a new packet is found */ + memmove(&pkt[0], &pkt[1], pkt_length - 1); + pkt_arena.used -= 1; + if ((bytes_read = ssdv_memcpy_packet(src, &pkt_arena, read_offset, 1)) <= 0) + { + break; + } + read_offset += 1; + + skipped++; + } + + /* No valid packet was found before EOF */ + if(c != 0) break; + + if(verbose) + { + ssdv_packet_info_t p; + + if(skipped > 0) + { + fprintf(stderr, "Skipped %d bytes.\n", skipped); + } + + ssdv_dec_header(&p, pkt); + fprintf(stderr, "Decoded image packet. Callsign: \"%s\", Image ID: %d, Resolution: %dx%d, Packet ID: %d (%d errors corrected)\n" + ">> Type: %d, Quality: %d, EOI: %d, MCU Mode: %d, MCU Offset: %d, MCU ID: %d/%d\n", + p.callsign_s, + p.image_id, + p.width, + p.height, + p.packet_id, + errors, + p.type, + p.quality, + p.eoi, + p.mcu_mode, + p.mcu_offset, + p.mcu_id, + p.mcu_count + ); + pkt_arena.used = 0; + } + + /* Feed it to the decoder */ + ssdv_dec_feed(ssdv, pkt); + i++; + } + + ssdv_dec_get_jpeg(ssdv, &jpeg, &jpeg_length); + result.buf = jpeg; + result.used = jpeg_length; + fprintf(stderr, "Read %i packets\n", i); + return result; +} + +ssdv_mem_arena_t ssdv_enc_buf(ssdv_mem_arena_t *src, ssdv_t *ssdv) { + + ssdv_mem_arena_t result = {0}; + ssdv_mem_arena_t pkt_arena = {0}; + ssdv_mem_arena_t b_arena = {0}; + + ssdv_mem_arena_t tmp = {0}; + + size_t page_count = 1; + size_t page_size = getpagesize(); + + tmp.buf = malloc(page_size); + tmp.length = page_size; + + int i, c; + int pkt_length = SSDV_PKT_SIZE; + uint8_t pkt[SSDV_PKT_SIZE], b[128]; + pkt_arena.buf = pkt; + pkt_arena.length = pkt_length; + b_arena.buf = b; + b_arena.length = 128; + + + ssdv_enc_set_buffer(ssdv, pkt); + + i = 0; + size_t read_offset = 0; + + while(1) + { + while((c = ssdv_enc_get_packet(ssdv)) == SSDV_FEED_ME) + { + b_arena.used = 0; + //size_t r = fread(b, 1, 128, fin); + size_t r = ssdv_memcpy_packet(src, &b_arena, read_offset, 128);; + read_offset += r; + + if(r <= 0) + { + fprintf(stderr, "Premature end of buffer: %u\n", read_offset); + break; + } + ssdv_enc_feed(ssdv, b, r); + } + + if(c == SSDV_EOI) + { + fprintf(stderr, "ssdv_enc_get_packet said EOI\n"); + break; + } + else if(c != SSDV_OK) + { + fprintf(stderr, "ssdv_enc_get_packet failed: %i\n", c); + fprintf(stderr, "Total read: %u\n", read_offset); + return result; + } + // Extend the buffer if we run out of room + if (tmp.length - tmp.used < pkt_length) { + page_count *= 2; + tmp.buf = realloc(tmp.buf, page_count * page_size); + tmp.length = page_count * page_size; + printf("Had to realloc: %u pages used\n", page_count); + } + + //fwrite(pkt, 1, pkt_length, fout); + ssdv_memcpy_packet(&pkt_arena, &tmp, 0, pkt_length); + i++; + } + + fprintf(stderr, "Wrote %i packets\n", i); + result = tmp; + return result; +} + +int ssdv_dec_file(FILE *fin, FILE *fout, ssdv_t *ssdv) { + + int i, c; + int droptest = 0; + int verbose = 1; + int errors; + int pkt_length = SSDV_PKT_SIZE; + int skipped; + + uint8_t pkt[SSDV_PKT_SIZE], *jpeg; + size_t jpeg_length; + + jpeg_length = 1024 * 1024 * 4; + jpeg = malloc(jpeg_length); + ssdv_dec_set_buffer(ssdv, jpeg, jpeg_length); + + i = 0; + while(fread(pkt, pkt_length, 1, fin) > 0) + { + /* Drop % of packets */ + if(droptest && (rand() / (RAND_MAX / 100) < droptest)) continue; + + /* Test the packet is valid */ + skipped = 0; + while((c = ssdv_dec_is_packet(pkt, pkt_length, &errors)) != 0) + { + /* Read 1 byte at a time until a new packet is found */ + memmove(&pkt[0], &pkt[1], pkt_length - 1); + + if(fread(&pkt[pkt_length - 1], 1, 1, fin) <= 0) + { + break; + } + + skipped++; + } + + /* No valid packet was found before EOF */ + if(c != 0) break; + + if(verbose) + { + ssdv_packet_info_t p; + + if(skipped > 0) + { + fprintf(stderr, "Skipped %d bytes.\n", skipped); + } + + ssdv_dec_header(&p, pkt); + fprintf(stderr, "Decoded image packet. Callsign: \"%s\", Image ID: %d, Resolution: %dx%d, Packet ID: %d (%d errors corrected)\n" + ">> Type: %d, Quality: %d, EOI: %d, MCU Mode: %d, MCU Offset: %d, MCU ID: %d/%d\n", + p.callsign_s, + p.image_id, + p.width, + p.height, + p.packet_id, + errors, + p.type, + p.quality, + p.eoi, + p.mcu_mode, + p.mcu_offset, + p.mcu_id, + p.mcu_count + ); + } + + /* Feed it to the decoder */ + ssdv_dec_feed(ssdv, pkt); + i++; + } + + ssdv_dec_get_jpeg(ssdv, &jpeg, &jpeg_length); + fwrite(jpeg, 1, jpeg_length, fout); + free(jpeg); + + fprintf(stderr, "Read %i packets\n", i); + return 0; +} + +int ssdv_enc_file(FILE *fin, FILE *fout, ssdv_t *ssdv) { + + int i, c; + int pkt_length = SSDV_PKT_SIZE; + uint8_t pkt[SSDV_PKT_SIZE], b[128]; + + ssdv_enc_set_buffer(ssdv, pkt); + + i = 0; + + while(1) + { + while((c = ssdv_enc_get_packet(ssdv)) == SSDV_FEED_ME) + { + size_t r = fread(b, 1, 128, fin); + + if(r <= 0) + { + fprintf(stderr, "Premature end of file\n"); + break; + } + ssdv_enc_feed(ssdv, b, r); + } + + if(c == SSDV_EOI) + { + fprintf(stderr, "ssdv_enc_get_packet said EOI\n"); + break; + } + else if(c != SSDV_OK) + { + fprintf(stderr, "ssdv_enc_get_packet failed: %i\n", c); + return(-1); + } + + fwrite(pkt, 1, pkt_length, fout); + i++; + } + + fprintf(stderr, "Wrote %i packets\n", i); + return 0; + +} + diff --git a/ssdvutils.h b/ssdvutils.h new file mode 100755 index 0000000..7876e8d --- /dev/null +++ b/ssdvutils.h @@ -0,0 +1,46 @@ + +/* SSDV - Slow Scan Digital Video */ +/*=======================================================================*/ +/* Copyright 2011-2016 Philip Heron */ +/* */ +/* This program is free software: you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, either version 3 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program. If not, see . */ + +/* + * ssdvutils.h added by GLRobotics 2025 + */ + +#include +#include +#include +#include +#include +#include "ssdv.h" + +typedef struct ssdv_mem_arena_t ssdv_mem_arena_t; +struct ssdv_mem_arena_t { + uint8_t *buf; + size_t length; + size_t used; +}; + +ssdv_mem_arena_t ssdv_read_file(FILE* f); + +size_t ssdv_memcpy_packet(ssdv_mem_arena_t *src, ssdv_mem_arena_t *dest, size_t read_offset, size_t pkt_length); + +ssdv_mem_arena_t ssdv_dec_buf(ssdv_mem_arena_t *src, ssdv_t *ssdv); +ssdv_mem_arena_t ssdv_enc_buf(ssdv_mem_arena_t *src, ssdv_t *ssdv); + +int ssdv_dec_file(FILE *fin, FILE *fout, ssdv_t *ssdv); +int ssdv_enc_file(FILE *fin, FILE *fout, ssdv_t *ssdv); + diff --git a/test.c b/test.c new file mode 100755 index 0000000..00a124c --- /dev/null +++ b/test.c @@ -0,0 +1,60 @@ +#include +#include +#include "ssdv.h" +#include "ssdvutils.h" + +int main(int argc, char* argv[]) { + FILE *fin = stdin; + FILE *fout = stdout; + char type = SSDV_TYPE_NORMAL; + int verbose = 1; + char callsign[7]; + uint8_t image_id = 0; + int8_t quality = 4; + int pkt_length = SSDV_PKT_SIZE; + ssdv_t ssdv; + FILE *ssdvFile, *jpegFile; + + + char rb[] = "rb"; + char wb[] = "wb"; + char encode = argc > 1; + + jpegFile = fopen("rpicam.jpg", encode? rb : wb); + ssdvFile = fopen("rpicam.ssdv", encode? wb : rb); + fin = encode? jpegFile : ssdvFile; + fout = (!encode)? jpegFile : ssdvFile; + + ssdv_mem_arena_t data = {0}; + + switch(encode) + { + case 0: /* Decode */ + + if(ssdv_dec_init(&ssdv, pkt_length) != SSDV_OK) + { + return(-1); + } + ssdv_mem_arena_t decoded; + data = ssdv_read_file(fin); + decoded = ssdv_dec_buf(&data, &ssdv); + fwrite(decoded.buf, decoded.used, 1, fout); + //ssdv_dec_file(fin, fout, &ssdv); + break; + + case 1: /* Encode */ + + if(ssdv_enc_init(&ssdv, type, callsign, image_id, quality, pkt_length) != SSDV_OK) + { + return(-1); + } + ssdv_mem_arena_t encoded; + data = ssdv_read_file(fin); + encoded = ssdv_enc_buf(&data, &ssdv); + fwrite(encoded.buf, encoded.used, 1, fout); + //ssdv_enc_file(fin, fout, &ssdv); + break; + } + return 0; +} + From 011f83f1ac5d1f020962d51be44eacba304e023a Mon Sep 17 00:00:00 2001 From: Bubbadime <146256626+Bubbadime@users.noreply.github.com> Date: Mon, 14 Jul 2025 20:47:15 +0100 Subject: [PATCH 02/14] Add install procedure for .so --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index ed8a797..48a3dd1 100755 --- a/Makefile +++ b/Makefile @@ -22,8 +22,12 @@ test: test.c libssdv.so install: all mkdir -p ${DESTDIR}/usr/bin + mkdir -p ${DESTDIR}/usr/include/ssdv install -m 755 ssdv ${DESTDIR}/usr/bin install -m 755 libssdv.so ${DESTDIR}/usr/lib + install -m 644 ssdv.h ${DESTDIR}/usr/include/ssdv + install -m 644 ssdvutils.h ${DESTDIR}/usr/include/ssdv + install -m 644 rs8.h ${DESTDIR}/usr/include/ssdv clean: rm -f *.o *.lo ssdv libssdv.so test From ae5ce7fd638dec3a38dd532d87514f48301b6612 Mon Sep 17 00:00:00 2001 From: Bubbadime <146256626+Bubbadime@users.noreply.github.com> Date: Mon, 14 Jul 2025 20:49:12 +0100 Subject: [PATCH 03/14] Remove unnecessary prints --- ssdv.c | 11 +---- ssdvutils.c | 2 +- ssdvutils.h | 0 test.c | 137 +++++++++++++++++++++++++++++----------------------- 4 files changed, 79 insertions(+), 71 deletions(-) mode change 100755 => 100644 ssdvutils.h diff --git a/ssdv.c b/ssdv.c index 4d76c94..3fe0dbc 100755 --- a/ssdv.c +++ b/ssdv.c @@ -675,7 +675,7 @@ static char ssdv_have_marker(ssdv_t *s) /* Copy the data before processing */ if(s->marker_len > TBL_LEN + HBUFF_LEN - s->stbl_len) { - printf("SSDV out of memory - marker len = %hu\n", s->marker_len); + fprintf(stderr, "SSDV out of memory - marker len = %hu\n", s->marker_len); /* Not enough memory ... shouldn't happen! */ return(SSDV_ERROR); } @@ -980,8 +980,6 @@ char ssdv_enc_get_packet(ssdv_t *s) /* If the output buffer is empty, re-initialise */ if(s->out_len == 0) ssdv_enc_set_buffer(s, s->out); - printf("Get packet:\n"); - printf("stbl_len: %hu\n", s->stbl_len); while(s->in_len) { b = *(s->inp++); @@ -990,11 +988,9 @@ char ssdv_enc_get_packet(ssdv_t *s) /* Skip bytes if necessary */ if(s->in_skip) { s->in_skip--; continue; } - printf("Marker 0x%hx, length %hu: ", s->marker, s->marker_len); switch(s->state) { case S_MARKER: - printf("S_MARKER\n"); s->marker = (s->marker << 8) | b; if(s->marker == J_TEM || @@ -1015,7 +1011,6 @@ char ssdv_enc_get_packet(ssdv_t *s) break; case S_MARKER_LEN: - printf("S_MARKER_LEN\n"); s->marker_len = (s->marker_len << 8) | b; if((s->needbits -= 8) == 0) { @@ -1026,7 +1021,6 @@ char ssdv_enc_get_packet(ssdv_t *s) break; case S_MARKER_DATA: - printf("S_MARKER_DATA\n"); s->marker_data[s->marker_data_len++] = b; if(s->marker_data_len == s->marker_len) { @@ -1036,9 +1030,7 @@ char ssdv_enc_get_packet(ssdv_t *s) break; case S_HUFF: - printf("S_HUFF\n"); case S_INT: - printf("S_INT\n"); /* Is the next byte a stuffing byte? Skip it */ /* TODO: Test the next byte is actually 0x00 */ if(b == 0xFF) s->in_skip++; @@ -1125,7 +1117,6 @@ char ssdv_enc_get_packet(ssdv_t *s) break; case S_EOI: - printf("S_EOI\n"); /* Shouldn't reach this point */ break; } diff --git a/ssdvutils.c b/ssdvutils.c index 66edf00..f12ed09 100755 --- a/ssdvutils.c +++ b/ssdvutils.c @@ -213,7 +213,7 @@ ssdv_mem_arena_t ssdv_enc_buf(ssdv_mem_arena_t *src, ssdv_t *ssdv) { page_count *= 2; tmp.buf = realloc(tmp.buf, page_count * page_size); tmp.length = page_count * page_size; - printf("Had to realloc: %u pages used\n", page_count); + fprintf(stderr, "Had to realloc: %u pages used\n", page_count); } //fwrite(pkt, 1, pkt_length, fout); diff --git a/ssdvutils.h b/ssdvutils.h old mode 100755 new mode 100644 diff --git a/test.c b/test.c index 00a124c..72cae85 100755 --- a/test.c +++ b/test.c @@ -1,60 +1,77 @@ -#include -#include -#include "ssdv.h" -#include "ssdvutils.h" - -int main(int argc, char* argv[]) { - FILE *fin = stdin; - FILE *fout = stdout; - char type = SSDV_TYPE_NORMAL; - int verbose = 1; - char callsign[7]; - uint8_t image_id = 0; - int8_t quality = 4; - int pkt_length = SSDV_PKT_SIZE; - ssdv_t ssdv; - FILE *ssdvFile, *jpegFile; - - - char rb[] = "rb"; - char wb[] = "wb"; - char encode = argc > 1; - - jpegFile = fopen("rpicam.jpg", encode? rb : wb); - ssdvFile = fopen("rpicam.ssdv", encode? wb : rb); - fin = encode? jpegFile : ssdvFile; - fout = (!encode)? jpegFile : ssdvFile; - - ssdv_mem_arena_t data = {0}; - - switch(encode) - { - case 0: /* Decode */ - - if(ssdv_dec_init(&ssdv, pkt_length) != SSDV_OK) - { - return(-1); - } - ssdv_mem_arena_t decoded; - data = ssdv_read_file(fin); - decoded = ssdv_dec_buf(&data, &ssdv); - fwrite(decoded.buf, decoded.used, 1, fout); - //ssdv_dec_file(fin, fout, &ssdv); - break; - - case 1: /* Encode */ - - if(ssdv_enc_init(&ssdv, type, callsign, image_id, quality, pkt_length) != SSDV_OK) - { - return(-1); - } - ssdv_mem_arena_t encoded; - data = ssdv_read_file(fin); - encoded = ssdv_enc_buf(&data, &ssdv); - fwrite(encoded.buf, encoded.used, 1, fout); - //ssdv_enc_file(fin, fout, &ssdv); - break; - } - return 0; -} - +#include +#include +#include "ssdv.h" +#include "ssdvutils.h" + +int main(int argc, char* argv[]) { + FILE *fin = stdin; + FILE *fout = stdout; + char type = SSDV_TYPE_NORMAL; + int verbose = 1; + char callsign[7]; + uint8_t image_id = 0; + int8_t quality = 4; + int pkt_length = SSDV_PKT_SIZE; + ssdv_t ssdv; + FILE *ssdvFile, *jpegFile; + + + char rb[] = "rb"; + char wb[] = "wb"; + char encode = argc > 1; + + jpegFile = fopen("rpicam.jpg", encode? rb : wb); + ssdvFile = fopen("rpicam.ssdv", encode? wb : rb); + fin = encode? jpegFile : ssdvFile; + fout = (!encode)? jpegFile : ssdvFile; + + ssdv_mem_arena_t data = {0}; + + while(1) { + ssdv_dec_init(&ssdv, pkt_length); + + } + switch(encode) + { + case 0: /* Decode */ + + if(ssdv_dec_init(&ssdv, pkt_length) != SSDV_OK) + { + return(-1); + } + ssdv_mem_arena_t decoded; + data = ssdv_read_file(fin); + decoded = ssdv_dec_buf(&data, &ssdv); + fwrite(decoded.buf, decoded.used, 1, fout); + //ssdv_dec_file(fin, fout, &ssdv); + break; + + case 1: /* Encode */ + + if(ssdv_enc_init(&ssdv, type, callsign, image_id, quality, pkt_length) != SSDV_OK) + { + return(-1); + } + ssdv_mem_arena_t encoded; + ssdv_mem_arena_t data2 = {0}; + data = ssdv_read_file(fin); + data2.buf = malloc(data.length); + data2.length = data.length; + ssdv_memcpy_packet(&data, &data2, 0, data.used); + encoded = ssdv_enc_buf(&data, &ssdv); + + for (size_t i = 0; i < data.used; i++) { + printf("%hhu, %hhu\n", data.buf[i], data2.buf[i]); + if (data.buf[i] != data2.buf[i]) { + printf("NOT EQUAL!\n"); + break; + } + } + printf("Pointers :%p, %p\n", data.buf, data2.buf); + fwrite(encoded.buf, encoded.used, 1, fout); + //ssdv_enc_file(fin, fout, &ssdv); + break; + } + return 0; +} + From 433784abf0af85339f8ed0dd0458461cb165d528 Mon Sep 17 00:00:00 2001 From: Bubbadime <146256626+Bubbadime@users.noreply.github.com> Date: Tue, 15 Jul 2025 20:53:08 +0100 Subject: [PATCH 04/14] Do not force to user to use internal memory structure --- ssdvutils.c | 155 ++++++++++++++++++++++++++++++---------------------- ssdvutils.h | 18 +++--- test.c | 54 +++++++++--------- 3 files changed, 123 insertions(+), 104 deletions(-) mode change 100644 => 100755 ssdvutils.h diff --git a/ssdvutils.c b/ssdvutils.c index f12ed09..145db4c 100755 --- a/ssdvutils.c +++ b/ssdvutils.c @@ -28,21 +28,14 @@ #include "ssdv.h" #include "ssdvutils.h" -ssdv_mem_arena_t ssdv_read_file(FILE* f) { - ssdv_mem_arena_t result = {0}; - size_t fcur = ftell(f); - fseek(f, 0, SEEK_END); - size_t fsize = ftell(f); - result.buf = malloc(fsize); - result.length = fsize; - fseek(f, 0, SEEK_SET); - fread(result.buf, result.length, 1, f); - result.used = fsize; - fseek(f, fcur, SEEK_SET); - return result; -} - -size_t ssdv_memcpy_packet(ssdv_mem_arena_t *src, ssdv_mem_arena_t *dest, size_t read_offset, size_t pkt_length) { +typedef struct ssdv_mem_arena_t ssdv_mem_arena_t; +struct ssdv_mem_arena_t { + uint8_t *buf; + size_t length; + size_t used; +}; + +static size_t ssdv_memcpy_packet(ssdv_mem_arena_t *src, ssdv_mem_arena_t *dest, size_t read_offset, size_t pkt_length) { size_t src_avail = src->length - read_offset; size_t dest_avail = dest->length - dest->used; size_t copy_length = (src_avail < dest_avail)? src_avail : dest_avail; @@ -50,13 +43,71 @@ size_t ssdv_memcpy_packet(ssdv_mem_arena_t *src, ssdv_mem_arena_t *dest, size_t memcpy(dest->buf + dest->used, src->buf + read_offset, copy_length); dest->used += copy_length; return copy_length; +} + +char ssdv_enc_init_default(ssdv_t *ssdv) { + char result = ssdv_enc_init(ssdv, SSDV_TYPE_NORMAL, "", 0, 4, 256); + return result; +} +char ssdv_dec_init_default(ssdv_t *ssdv) { + char result = ssdv_dec_init(ssdv, 256); + return result; +} +void ssdv_print_header(uint8_t *pkt, int fd) { + + ssdv_packet_info_t p; + ssdv_dec_header(&p, pkt); + fprintf(fd, "decoded image packet. callsign: \"%s\", image id: %d, resolution: %dx%d, packet id: %d \n" + ">> type: %d, quality: %d, eoi: %d, mcu mode: %d, mcu offset: %d, mcu id: %d/%d\n", + p.callsign_s, + p.image_id, + p.width, + p.height, + p.packet_id, + p.type, + p.quality, + p.eoi, + p.mcu_mode, + p.mcu_offset, + p.mcu_id, + p.mcu_count + ); +} +void ssdv_print_header_stdout(uint8_t *pkt) { + ssdv_print_header(pkt, stdout); + return; } -ssdv_mem_arena_t ssdv_dec_buf(ssdv_mem_arena_t *src, ssdv_t *ssdv) { +void ssdv_print_header_stderr(uint8_t *pkt) { + ssdv_print_header(pkt, stderr); + return; +} + +uint8_t* ssdv_read_file(FILE* f, size_t *len_out) { + printf("Read file\n"); + uint8_t* result = 0; + size_t fcur = ftell(f); + fseek(f, 0, SEEK_END); + size_t fsize = ftell(f); + result = malloc(fsize); + printf("Read file malloc'd\n"); + *len_out = fsize; + fseek(f, 0, SEEK_SET); + fread(result, *len_out, 1, f); + fseek(f, fcur, SEEK_SET); + return result; +} + +uint8_t* ssdv_dec_buf(uint8_t *src, size_t len_in, ssdv_t *ssdv, size_t *len_out) { ssdv_mem_arena_t result = {0}; - int src_good = src->buf != 0 && src->length > 0; + ssdv_mem_arena_t src_arena = {0}; + src_arena.buf = src; + src_arena.length = len_in; + src_arena.used = len_in; + + int src_good = src != 0 && len_in > 0; int i, c; int droptest = 0; @@ -73,8 +124,8 @@ ssdv_mem_arena_t ssdv_dec_buf(ssdv_mem_arena_t *src, ssdv_t *ssdv) { pkt_arena.length = SSDV_PKT_SIZE; if (!src_good) { - fprintf(stderr, "Buffer error. Src: %p %u\n", src->buf, src->length); - return result; + fprintf(stderr, "Buffer error. Src: %p %u\n", src_arena.buf, src_arena.length); + return 0; } jpeg_length = 1024 * 1024 * 4; @@ -86,7 +137,7 @@ ssdv_mem_arena_t ssdv_dec_buf(ssdv_mem_arena_t *src, ssdv_t *ssdv) { size_t read_offset = 0; size_t bytes_read = 0; - while((bytes_read = ssdv_memcpy_packet(src, &pkt_arena, read_offset, pkt_length)) > 0) + while((bytes_read = ssdv_memcpy_packet(&src_arena, &pkt_arena, read_offset, pkt_length)) > 0) { read_offset += bytes_read; /* Drop % of packets */ @@ -99,7 +150,7 @@ ssdv_mem_arena_t ssdv_dec_buf(ssdv_mem_arena_t *src, ssdv_t *ssdv) { /* Read 1 byte at a time until a new packet is found */ memmove(&pkt[0], &pkt[1], pkt_length - 1); pkt_arena.used -= 1; - if ((bytes_read = ssdv_memcpy_packet(src, &pkt_arena, read_offset, 1)) <= 0) + if ((bytes_read = ssdv_memcpy_packet(&src_arena, &pkt_arena, read_offset, 1)) <= 0) { break; } @@ -113,30 +164,12 @@ ssdv_mem_arena_t ssdv_dec_buf(ssdv_mem_arena_t *src, ssdv_t *ssdv) { if(verbose) { - ssdv_packet_info_t p; if(skipped > 0) { fprintf(stderr, "Skipped %d bytes.\n", skipped); } - - ssdv_dec_header(&p, pkt); - fprintf(stderr, "Decoded image packet. Callsign: \"%s\", Image ID: %d, Resolution: %dx%d, Packet ID: %d (%d errors corrected)\n" - ">> Type: %d, Quality: %d, EOI: %d, MCU Mode: %d, MCU Offset: %d, MCU ID: %d/%d\n", - p.callsign_s, - p.image_id, - p.width, - p.height, - p.packet_id, - errors, - p.type, - p.quality, - p.eoi, - p.mcu_mode, - p.mcu_offset, - p.mcu_id, - p.mcu_count - ); + ssdv_print_header_stderr(pkt); pkt_arena.used = 0; } @@ -149,15 +182,21 @@ ssdv_mem_arena_t ssdv_dec_buf(ssdv_mem_arena_t *src, ssdv_t *ssdv) { result.buf = jpeg; result.used = jpeg_length; fprintf(stderr, "Read %i packets\n", i); - return result; + *len_out = result.used; + return result.buf; } -ssdv_mem_arena_t ssdv_enc_buf(ssdv_mem_arena_t *src, ssdv_t *ssdv) { +uint8_t* ssdv_enc_buf(uint8_t *src, size_t len_in, ssdv_t *ssdv, size_t *len_out) { ssdv_mem_arena_t result = {0}; ssdv_mem_arena_t pkt_arena = {0}; ssdv_mem_arena_t b_arena = {0}; + ssdv_mem_arena_t src_arena = {0}; + src_arena.buf = src; + src_arena.length = len_in; + src_arena.used = len_in; + ssdv_mem_arena_t tmp = {0}; size_t page_count = 1; @@ -186,7 +225,7 @@ ssdv_mem_arena_t ssdv_enc_buf(ssdv_mem_arena_t *src, ssdv_t *ssdv) { { b_arena.used = 0; //size_t r = fread(b, 1, 128, fin); - size_t r = ssdv_memcpy_packet(src, &b_arena, read_offset, 128);; + size_t r = ssdv_memcpy_packet(&src_arena, &b_arena, read_offset, 128);; read_offset += r; if(r <= 0) @@ -206,7 +245,7 @@ ssdv_mem_arena_t ssdv_enc_buf(ssdv_mem_arena_t *src, ssdv_t *ssdv) { { fprintf(stderr, "ssdv_enc_get_packet failed: %i\n", c); fprintf(stderr, "Total read: %u\n", read_offset); - return result; + return 0; } // Extend the buffer if we run out of room if (tmp.length - tmp.used < pkt_length) { @@ -216,14 +255,18 @@ ssdv_mem_arena_t ssdv_enc_buf(ssdv_mem_arena_t *src, ssdv_t *ssdv) { fprintf(stderr, "Had to realloc: %u pages used\n", page_count); } - //fwrite(pkt, 1, pkt_length, fout); ssdv_memcpy_packet(&pkt_arena, &tmp, 0, pkt_length); i++; } + if (tmp.length != tmp.used) { + tmp.buf = realloc(tmp.buf, tmp.used); + tmp.length = tmp.used; + } fprintf(stderr, "Wrote %i packets\n", i); result = tmp; - return result; + *len_out = result.used; + return result.buf; } int ssdv_dec_file(FILE *fin, FILE *fout, ssdv_t *ssdv) { @@ -268,30 +311,12 @@ int ssdv_dec_file(FILE *fin, FILE *fout, ssdv_t *ssdv) { if(verbose) { - ssdv_packet_info_t p; - if(skipped > 0) { fprintf(stderr, "Skipped %d bytes.\n", skipped); } - ssdv_dec_header(&p, pkt); - fprintf(stderr, "Decoded image packet. Callsign: \"%s\", Image ID: %d, Resolution: %dx%d, Packet ID: %d (%d errors corrected)\n" - ">> Type: %d, Quality: %d, EOI: %d, MCU Mode: %d, MCU Offset: %d, MCU ID: %d/%d\n", - p.callsign_s, - p.image_id, - p.width, - p.height, - p.packet_id, - errors, - p.type, - p.quality, - p.eoi, - p.mcu_mode, - p.mcu_offset, - p.mcu_id, - p.mcu_count - ); + ssdv_print_header_stderr(pkt); } /* Feed it to the decoder */ diff --git a/ssdvutils.h b/ssdvutils.h old mode 100644 new mode 100755 index 7876e8d..062966f --- a/ssdvutils.h +++ b/ssdvutils.h @@ -27,19 +27,17 @@ #include #include "ssdv.h" -typedef struct ssdv_mem_arena_t ssdv_mem_arena_t; -struct ssdv_mem_arena_t { - uint8_t *buf; - size_t length; - size_t used; -}; +char ssdv_enc_init_default(ssdv_t *ssdv); +char ssdv_dec_init_default(ssdv_t *ssdv); -ssdv_mem_arena_t ssdv_read_file(FILE* f); +void ssdv_print_header(uint8_t *pkt, int fd); +void ssdv_print_header_stdout(uint8_t *pkt); +void ssdv_print_header_stderr(uint8_t *pkt); -size_t ssdv_memcpy_packet(ssdv_mem_arena_t *src, ssdv_mem_arena_t *dest, size_t read_offset, size_t pkt_length); +uint8_t* ssdv_read_file(FILE* f, size_t* lenOut); -ssdv_mem_arena_t ssdv_dec_buf(ssdv_mem_arena_t *src, ssdv_t *ssdv); -ssdv_mem_arena_t ssdv_enc_buf(ssdv_mem_arena_t *src, ssdv_t *ssdv); +uint8_t* ssdv_dec_buf(uint8_t *src, size_t lenIn, ssdv_t *ssdv, size_t *lenOut); +uint8_t* ssdv_enc_buf(uint8_t *src, size_t lenIn, ssdv_t *ssdv, size_t *lenOut); int ssdv_dec_file(FILE *fin, FILE *fout, ssdv_t *ssdv); int ssdv_enc_file(FILE *fin, FILE *fout, ssdv_t *ssdv); diff --git a/test.c b/test.c index 72cae85..884fd29 100755 --- a/test.c +++ b/test.c @@ -20,17 +20,16 @@ int main(int argc, char* argv[]) { char wb[] = "wb"; char encode = argc > 1; + fprintf(fout, "Pre-open Fin: %p, Fout: %p\n", fin, fout); jpegFile = fopen("rpicam.jpg", encode? rb : wb); ssdvFile = fopen("rpicam.ssdv", encode? wb : rb); fin = encode? jpegFile : ssdvFile; fout = (!encode)? jpegFile : ssdvFile; + printf("Fin: %p, Fout: %p\n", fin, fout); - ssdv_mem_arena_t data = {0}; + uint8_t *data = 0; + size_t dataLen; - while(1) { - ssdv_dec_init(&ssdv, pkt_length); - - } switch(encode) { case 0: /* Decode */ @@ -39,37 +38,34 @@ int main(int argc, char* argv[]) { { return(-1); } - ssdv_mem_arena_t decoded; - data = ssdv_read_file(fin); - decoded = ssdv_dec_buf(&data, &ssdv); - fwrite(decoded.buf, decoded.used, 1, fout); - //ssdv_dec_file(fin, fout, &ssdv); + +#define MODE_BUF 1 +#if MODE_BUF + uint8_t *decoded; + size_t decodedLen; + printf("Read file next\n"); + data = ssdv_read_file(fin, &dataLen); + decoded = ssdv_dec_buf(data, dataLen, &ssdv, &decodedLen); + fwrite(decoded, decodedLen, 1, fout); +#else + ssdv_dec_file(fin, fout, &ssdv); +#endif break; - case 1: /* Encode */ if(ssdv_enc_init(&ssdv, type, callsign, image_id, quality, pkt_length) != SSDV_OK) { return(-1); } - ssdv_mem_arena_t encoded; - ssdv_mem_arena_t data2 = {0}; - data = ssdv_read_file(fin); - data2.buf = malloc(data.length); - data2.length = data.length; - ssdv_memcpy_packet(&data, &data2, 0, data.used); - encoded = ssdv_enc_buf(&data, &ssdv); - - for (size_t i = 0; i < data.used; i++) { - printf("%hhu, %hhu\n", data.buf[i], data2.buf[i]); - if (data.buf[i] != data2.buf[i]) { - printf("NOT EQUAL!\n"); - break; - } - } - printf("Pointers :%p, %p\n", data.buf, data2.buf); - fwrite(encoded.buf, encoded.used, 1, fout); - //ssdv_enc_file(fin, fout, &ssdv); +#if MODE_BUF + uint8_t *encoded; + size_t encodedLen; + data = ssdv_read_file(fin, &dataLen); + encoded = ssdv_enc_buf(data, dataLen, &ssdv, &encodedLen); + fwrite(encoded, encodedLen, 1, fout); +#else + ssdv_enc_file(fin, fout, &ssdv); +#endif break; } return 0; From 3334349cd9dd6347c48648320ad0304712e6d961 Mon Sep 17 00:00:00 2001 From: Bubbadime <146256626+Bubbadime@users.noreply.github.com> Date: Tue, 15 Jul 2025 21:40:10 +0100 Subject: [PATCH 05/14] Add comments, default behavior, and cleanup --- ssdvutils.c | 86 +++++++++++++++++++++++++++++++++-------------------- ssdvutils.h | 25 ++++++++-------- test.c | 24 +++++++++++---- 3 files changed, 84 insertions(+), 51 deletions(-) diff --git a/ssdvutils.c b/ssdvutils.c index 145db4c..30a1761 100755 --- a/ssdvutils.c +++ b/ssdvutils.c @@ -23,11 +23,11 @@ #include #include #include -#include #include #include "ssdv.h" #include "ssdvutils.h" +// Memory struct for internal use typedef struct ssdv_mem_arena_t ssdv_mem_arena_t; struct ssdv_mem_arena_t { uint8_t *buf; @@ -35,6 +35,7 @@ struct ssdv_mem_arena_t { size_t used; }; +// Mimics the behavior of fread for code consistency between file and buffer API static size_t ssdv_memcpy_packet(ssdv_mem_arena_t *src, ssdv_mem_arena_t *dest, size_t read_offset, size_t pkt_length) { size_t src_avail = src->length - read_offset; size_t dest_avail = dest->length - dest->used; @@ -45,16 +46,20 @@ static size_t ssdv_memcpy_packet(ssdv_mem_arena_t *src, ssdv_mem_arena_t *dest, return copy_length; } +// Init the ssdv struct for encoding with default parameters char ssdv_enc_init_default(ssdv_t *ssdv) { char result = ssdv_enc_init(ssdv, SSDV_TYPE_NORMAL, "", 0, 4, 256); return result; } + +// Init the ssdv struct for decoding with default parameters char ssdv_dec_init_default(ssdv_t *ssdv) { char result = ssdv_dec_init(ssdv, 256); return result; } -void ssdv_print_header(uint8_t *pkt, int fd) { +// Print the header decoded from pkt into fd +void ssdv_print_header(uint8_t *pkt, FILE* fd) { ssdv_packet_info_t p; ssdv_dec_header(&p, pkt); @@ -74,32 +79,24 @@ void ssdv_print_header(uint8_t *pkt, int fd) { p.mcu_count ); } + +// Print the header decoded from pkt to stdout void ssdv_print_header_stdout(uint8_t *pkt) { ssdv_print_header(pkt, stdout); return; } +// Print the header decoded from pkt to stderr void ssdv_print_header_stderr(uint8_t *pkt) { ssdv_print_header(pkt, stderr); return; } -uint8_t* ssdv_read_file(FILE* f, size_t *len_out) { - printf("Read file\n"); - uint8_t* result = 0; - size_t fcur = ftell(f); - fseek(f, 0, SEEK_END); - size_t fsize = ftell(f); - result = malloc(fsize); - printf("Read file malloc'd\n"); - *len_out = fsize; - fseek(f, 0, SEEK_SET); - fread(result, *len_out, 1, f); - fseek(f, fcur, SEEK_SET); - return result; -} - -uint8_t* ssdv_dec_buf(uint8_t *src, size_t len_in, ssdv_t *ssdv, size_t *len_out) { +/* Decode a buffer of ssdv packets + * Fills a buffer with the resulting jpeg binary data, + * and puts the length of the buffer in len_out + */ +uint8_t* ssdv_dec_buf_opts(ssdv_t *ssdv, uint8_t *src, size_t len_in, int verbose, int droptest, size_t *len_out) { ssdv_mem_arena_t result = {0}; ssdv_mem_arena_t src_arena = {0}; @@ -110,8 +107,6 @@ uint8_t* ssdv_dec_buf(uint8_t *src, size_t len_in, ssdv_t *ssdv, size_t *len_out int src_good = src != 0 && len_in > 0; int i, c; - int droptest = 0; - int verbose = 1; int errors; int pkt_length = SSDV_PKT_SIZE; int skipped; @@ -186,7 +181,20 @@ uint8_t* ssdv_dec_buf(uint8_t *src, size_t len_in, ssdv_t *ssdv, size_t *len_out return result.buf; } -uint8_t* ssdv_enc_buf(uint8_t *src, size_t len_in, ssdv_t *ssdv, size_t *len_out) { +// calls ssdv_dec_buf_opts with default parameters +uint8_t* ssdv_dec_buf(ssdv_t *ssdv, uint8_t *src, size_t len_in, size_t *len_out) { + uint8_t* result; + int droptest = 0; + int verbose = 0; + result = ssdv_dec_buf_opts(ssdv, src, len_in, verbose, droptest, len_out); + return result; +} + +/* Encode a buffer of jpeg data + * Fills a buffer with the resulting ssdv packets, + * and puts the length of the buffer in len_out + */ +uint8_t* ssdv_enc_buf(ssdv_t *ssdv, uint8_t *src, size_t len_in, size_t *len_out) { ssdv_mem_arena_t result = {0}; ssdv_mem_arena_t pkt_arena = {0}; @@ -199,11 +207,11 @@ uint8_t* ssdv_enc_buf(uint8_t *src, size_t len_in, ssdv_t *ssdv, size_t *len_out ssdv_mem_arena_t tmp = {0}; - size_t page_count = 1; - size_t page_size = getpagesize(); + size_t alloc_count = 1; + size_t alloc_size = 4096; - tmp.buf = malloc(page_size); - tmp.length = page_size; + tmp.buf = malloc(alloc_size); + tmp.length = alloc_size; int i, c; int pkt_length = SSDV_PKT_SIZE; @@ -249,10 +257,10 @@ uint8_t* ssdv_enc_buf(uint8_t *src, size_t len_in, ssdv_t *ssdv, size_t *len_out } // Extend the buffer if we run out of room if (tmp.length - tmp.used < pkt_length) { - page_count *= 2; - tmp.buf = realloc(tmp.buf, page_count * page_size); - tmp.length = page_count * page_size; - fprintf(stderr, "Had to realloc: %u pages used\n", page_count); + alloc_count *= 2; + tmp.buf = realloc(tmp.buf, alloc_count * alloc_size); + tmp.length = alloc_count * alloc_size; + fprintf(stderr, "Had to realloc: %zu bytes used\n", alloc_count * alloc_size); } ssdv_memcpy_packet(&pkt_arena, &tmp, 0, pkt_length); @@ -269,11 +277,12 @@ uint8_t* ssdv_enc_buf(uint8_t *src, size_t len_in, ssdv_t *ssdv, size_t *len_out return result.buf; } -int ssdv_dec_file(FILE *fin, FILE *fout, ssdv_t *ssdv) { +/* Decode a file of ssdv packets + * Reads data from fin, and write to fout + */ +int ssdv_dec_file_opts(ssdv_t *ssdv, FILE *fin, FILE *fout, int droptest, int verbose) { int i, c; - int droptest = 0; - int verbose = 1; int errors; int pkt_length = SSDV_PKT_SIZE; int skipped; @@ -332,7 +341,18 @@ int ssdv_dec_file(FILE *fin, FILE *fout, ssdv_t *ssdv) { return 0; } -int ssdv_enc_file(FILE *fin, FILE *fout, ssdv_t *ssdv) { +// calls ssdv_dec_file_opts with default parameters +int ssdv_dec_file(ssdv_t *ssdv, FILE *fin, FILE *fout) { + int droptest = 0; + int verbose = 0; + int result = ssdv_dec_file_opts(ssdv, fin, fout, droptest, verbose); + return result; +} + +/* Encode a jpeg file to ssdv packets + * Reads data from fin, and write to fout + */ +int ssdv_enc_file(ssdv_t *ssdv, FILE *fin, FILE *fout) { int i, c; int pkt_length = SSDV_PKT_SIZE; diff --git a/ssdvutils.h b/ssdvutils.h index 062966f..de61809 100755 --- a/ssdvutils.h +++ b/ssdvutils.h @@ -22,23 +22,22 @@ #include #include -#include -#include -#include #include "ssdv.h" -char ssdv_enc_init_default(ssdv_t *ssdv); -char ssdv_dec_init_default(ssdv_t *ssdv); - -void ssdv_print_header(uint8_t *pkt, int fd); +// Printing +void ssdv_print_header(uint8_t *pkt, FILE* fd); void ssdv_print_header_stdout(uint8_t *pkt); void ssdv_print_header_stderr(uint8_t *pkt); -uint8_t* ssdv_read_file(FILE* f, size_t* lenOut); - -uint8_t* ssdv_dec_buf(uint8_t *src, size_t lenIn, ssdv_t *ssdv, size_t *lenOut); -uint8_t* ssdv_enc_buf(uint8_t *src, size_t lenIn, ssdv_t *ssdv, size_t *lenOut); +// Decoding +char ssdv_dec_init_default(ssdv_t *ssdv); +uint8_t* ssdv_dec_buf_opts(ssdv_t *ssdv, uint8_t *src, size_t len_in, int verbose, int droptest, size_t *len_out); +uint8_t* ssdv_dec_buf(ssdv_t *ssdv, uint8_t *src, size_t len_in, size_t *len_out); +int ssdv_dec_file_opts(ssdv_t *ssdv, FILE *fin, FILE *fout, int droptest, int verbose); +int ssdv_dec_file(ssdv_t *ssdv, FILE *fin, FILE *fout); -int ssdv_dec_file(FILE *fin, FILE *fout, ssdv_t *ssdv); -int ssdv_enc_file(FILE *fin, FILE *fout, ssdv_t *ssdv); +// Encoding +char ssdv_enc_init_default(ssdv_t *ssdv); +uint8_t* ssdv_enc_buf(ssdv_t *ssdv, uint8_t *src, size_t len_in, size_t *len_out); +int ssdv_enc_file(ssdv_t *ssdv, FILE *fin, FILE *fout); diff --git a/test.c b/test.c index 884fd29..917d5a0 100755 --- a/test.c +++ b/test.c @@ -1,8 +1,22 @@ #include #include +#include #include "ssdv.h" #include "ssdvutils.h" +uint8_t* ssdv_read_file(FILE* f, size_t *len_out) { + uint8_t* result = 0; + size_t fcur = ftell(f); + fseek(f, 0, SEEK_END); + size_t fsize = ftell(f); + result = malloc(fsize); + *len_out = fsize; + fseek(f, 0, SEEK_SET); + fread(result, *len_out, 1, f); + fseek(f, fcur, SEEK_SET); + return result; +} + int main(int argc, char* argv[]) { FILE *fin = stdin; FILE *fout = stdout; @@ -45,15 +59,15 @@ int main(int argc, char* argv[]) { size_t decodedLen; printf("Read file next\n"); data = ssdv_read_file(fin, &dataLen); - decoded = ssdv_dec_buf(data, dataLen, &ssdv, &decodedLen); + decoded = ssdv_dec_buf(&ssdv, data, dataLen, &decodedLen); fwrite(decoded, decodedLen, 1, fout); #else - ssdv_dec_file(fin, fout, &ssdv); + ssdv_dec_file(&ssdv, fin, fout); #endif break; case 1: /* Encode */ - if(ssdv_enc_init(&ssdv, type, callsign, image_id, quality, pkt_length) != SSDV_OK) + if(ssdv_enc_init_default(&ssdv) != SSDV_OK) { return(-1); } @@ -61,10 +75,10 @@ int main(int argc, char* argv[]) { uint8_t *encoded; size_t encodedLen; data = ssdv_read_file(fin, &dataLen); - encoded = ssdv_enc_buf(data, dataLen, &ssdv, &encodedLen); + encoded = ssdv_enc_buf(&ssdv, data, dataLen, &encodedLen); fwrite(encoded, encodedLen, 1, fout); #else - ssdv_enc_file(fin, fout, &ssdv); + ssdv_enc_file(&ssdv, fin, fout); #endif break; } From cdf63a99fa9f312a5ede8ccf5fd7dbbca3754316 Mon Sep 17 00:00:00 2001 From: Bubbadime <146256626+Bubbadime@users.noreply.github.com> Date: Tue, 15 Jul 2025 21:55:19 +0100 Subject: [PATCH 06/14] Polishing up and remove // style comments --- ssdvutils.c | 31 +++++++++++++------------------ ssdvutils.h | 10 ++++------ test.c | 28 ++++++++++++++++++++++++---- 3 files changed, 41 insertions(+), 28 deletions(-) diff --git a/ssdvutils.c b/ssdvutils.c index 30a1761..3735265 100755 --- a/ssdvutils.c +++ b/ssdvutils.c @@ -16,9 +16,7 @@ /* You should have received a copy of the GNU General Public License */ /* along with this program. If not, see . */ -/* - * ssdvutils.h added by GLRobotics 2025 - */ +/* ssdvutils.h added by GLRobotics 2025 */ #include #include @@ -27,7 +25,7 @@ #include "ssdv.h" #include "ssdvutils.h" -// Memory struct for internal use +/* Memory struct for internal use */ typedef struct ssdv_mem_arena_t ssdv_mem_arena_t; struct ssdv_mem_arena_t { uint8_t *buf; @@ -35,7 +33,7 @@ struct ssdv_mem_arena_t { size_t used; }; -// Mimics the behavior of fread for code consistency between file and buffer API +/* Mimics the behavior of fread for code consistency between file and buffer API */ static size_t ssdv_memcpy_packet(ssdv_mem_arena_t *src, ssdv_mem_arena_t *dest, size_t read_offset, size_t pkt_length) { size_t src_avail = src->length - read_offset; size_t dest_avail = dest->length - dest->used; @@ -46,21 +44,20 @@ static size_t ssdv_memcpy_packet(ssdv_mem_arena_t *src, ssdv_mem_arena_t *dest, return copy_length; } -// Init the ssdv struct for encoding with default parameters +/* Init the ssdv struct for encoding with default parameters */ char ssdv_enc_init_default(ssdv_t *ssdv) { char result = ssdv_enc_init(ssdv, SSDV_TYPE_NORMAL, "", 0, 4, 256); return result; } -// Init the ssdv struct for decoding with default parameters +/* Init the ssdv struct for decoding with default parameters */ char ssdv_dec_init_default(ssdv_t *ssdv) { char result = ssdv_dec_init(ssdv, 256); return result; } -// Print the header decoded from pkt into fd +/* Print the header decoded from pkt into fd */ void ssdv_print_header(uint8_t *pkt, FILE* fd) { - ssdv_packet_info_t p; ssdv_dec_header(&p, pkt); fprintf(fd, "decoded image packet. callsign: \"%s\", image id: %d, resolution: %dx%d, packet id: %d \n" @@ -80,13 +77,13 @@ void ssdv_print_header(uint8_t *pkt, FILE* fd) { ); } -// Print the header decoded from pkt to stdout +/* Print the header decoded from pkt to stdout */ void ssdv_print_header_stdout(uint8_t *pkt) { ssdv_print_header(pkt, stdout); return; } -// Print the header decoded from pkt to stderr +/* Print the header decoded from pkt to stderr */ void ssdv_print_header_stderr(uint8_t *pkt) { ssdv_print_header(pkt, stderr); return; @@ -97,13 +94,11 @@ void ssdv_print_header_stderr(uint8_t *pkt) { * and puts the length of the buffer in len_out */ uint8_t* ssdv_dec_buf_opts(ssdv_t *ssdv, uint8_t *src, size_t len_in, int verbose, int droptest, size_t *len_out) { - ssdv_mem_arena_t result = {0}; ssdv_mem_arena_t src_arena = {0}; src_arena.buf = src; src_arena.length = len_in; src_arena.used = len_in; - int src_good = src != 0 && len_in > 0; int i, c; @@ -129,7 +124,6 @@ uint8_t* ssdv_dec_buf_opts(ssdv_t *ssdv, uint8_t *src, size_t len_in, int verbos result.length = jpeg_length; i = 0; - size_t read_offset = 0; size_t bytes_read = 0; while((bytes_read = ssdv_memcpy_packet(&src_arena, &pkt_arena, read_offset, pkt_length)) > 0) @@ -173,6 +167,7 @@ uint8_t* ssdv_dec_buf_opts(ssdv_t *ssdv, uint8_t *src, size_t len_in, int verbos i++; } + /* Get the buffer of jpeg data and return */ ssdv_dec_get_jpeg(ssdv, &jpeg, &jpeg_length); result.buf = jpeg; result.used = jpeg_length; @@ -181,7 +176,7 @@ uint8_t* ssdv_dec_buf_opts(ssdv_t *ssdv, uint8_t *src, size_t len_in, int verbos return result.buf; } -// calls ssdv_dec_buf_opts with default parameters +/* calls ssdv_dec_buf_opts with default parameters */ uint8_t* ssdv_dec_buf(ssdv_t *ssdv, uint8_t *src, size_t len_in, size_t *len_out) { uint8_t* result; int droptest = 0; @@ -232,7 +227,7 @@ uint8_t* ssdv_enc_buf(ssdv_t *ssdv, uint8_t *src, size_t len_in, size_t *len_out while((c = ssdv_enc_get_packet(ssdv)) == SSDV_FEED_ME) { b_arena.used = 0; - //size_t r = fread(b, 1, 128, fin); + /*size_t r = fread(b, 1, 128, fin); */ size_t r = ssdv_memcpy_packet(&src_arena, &b_arena, read_offset, 128);; read_offset += r; @@ -255,7 +250,7 @@ uint8_t* ssdv_enc_buf(ssdv_t *ssdv, uint8_t *src, size_t len_in, size_t *len_out fprintf(stderr, "Total read: %u\n", read_offset); return 0; } - // Extend the buffer if we run out of room + /* Extend the buffer if we run out of room */ if (tmp.length - tmp.used < pkt_length) { alloc_count *= 2; tmp.buf = realloc(tmp.buf, alloc_count * alloc_size); @@ -341,7 +336,7 @@ int ssdv_dec_file_opts(ssdv_t *ssdv, FILE *fin, FILE *fout, int droptest, int ve return 0; } -// calls ssdv_dec_file_opts with default parameters +/* calls ssdv_dec_file_opts with default parameters */ int ssdv_dec_file(ssdv_t *ssdv, FILE *fin, FILE *fout) { int droptest = 0; int verbose = 0; diff --git a/ssdvutils.h b/ssdvutils.h index de61809..ca2263e 100755 --- a/ssdvutils.h +++ b/ssdvutils.h @@ -16,27 +16,25 @@ /* You should have received a copy of the GNU General Public License */ /* along with this program. If not, see . */ -/* - * ssdvutils.h added by GLRobotics 2025 - */ +/* ssdvutils.h added by GLRobotics 2025 */ #include #include #include "ssdv.h" -// Printing +/* Printing */ void ssdv_print_header(uint8_t *pkt, FILE* fd); void ssdv_print_header_stdout(uint8_t *pkt); void ssdv_print_header_stderr(uint8_t *pkt); -// Decoding +/* Decoding */ char ssdv_dec_init_default(ssdv_t *ssdv); uint8_t* ssdv_dec_buf_opts(ssdv_t *ssdv, uint8_t *src, size_t len_in, int verbose, int droptest, size_t *len_out); uint8_t* ssdv_dec_buf(ssdv_t *ssdv, uint8_t *src, size_t len_in, size_t *len_out); int ssdv_dec_file_opts(ssdv_t *ssdv, FILE *fin, FILE *fout, int droptest, int verbose); int ssdv_dec_file(ssdv_t *ssdv, FILE *fin, FILE *fout); -// Encoding +/* Encoding */ char ssdv_enc_init_default(ssdv_t *ssdv); uint8_t* ssdv_enc_buf(ssdv_t *ssdv, uint8_t *src, size_t len_in, size_t *len_out); int ssdv_enc_file(ssdv_t *ssdv, FILE *fin, FILE *fout); diff --git a/test.c b/test.c index 917d5a0..63ca337 100755 --- a/test.c +++ b/test.c @@ -1,3 +1,25 @@ + +/* SSDV - Slow Scan Digital Video */ +/*=======================================================================*/ +/* Copyright 2011-2016 Philip Heron */ +/* */ +/* This program is free software: you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, either version 3 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program. If not, see . */ + +/* ssdvutils.h added by GLRobotics 2025 */ + +// TODO(BP): REMOVE THIS FILE!!! + #include #include #include @@ -34,12 +56,10 @@ int main(int argc, char* argv[]) { char wb[] = "wb"; char encode = argc > 1; - fprintf(fout, "Pre-open Fin: %p, Fout: %p\n", fin, fout); - jpegFile = fopen("rpicam.jpg", encode? rb : wb); - ssdvFile = fopen("rpicam.ssdv", encode? wb : rb); + jpegFile = fopen("test.jpg", encode? rb : wb); + ssdvFile = fopen("test.ssdv", encode? wb : rb); fin = encode? jpegFile : ssdvFile; fout = (!encode)? jpegFile : ssdvFile; - printf("Fin: %p, Fout: %p\n", fin, fout); uint8_t *data = 0; size_t dataLen; From 606b66e54fffddb282d8006c1a6bcf924dcd0377 Mon Sep 17 00:00:00 2001 From: Bubbadime <146256626+Bubbadime@users.noreply.github.com> Date: Thu, 17 Jul 2025 18:56:08 +0100 Subject: [PATCH 07/14] Reorganize ssdvutils.c --- ssdvutils.c | 186 +++++++++++++++++++++++++++------------------------- ssdvutils.h | 2 +- 2 files changed, 96 insertions(+), 92 deletions(-) diff --git a/ssdvutils.c b/ssdvutils.c index 3735265..a30d2ec 100755 --- a/ssdvutils.c +++ b/ssdvutils.c @@ -44,18 +44,6 @@ static size_t ssdv_memcpy_packet(ssdv_mem_arena_t *src, ssdv_mem_arena_t *dest, return copy_length; } -/* Init the ssdv struct for encoding with default parameters */ -char ssdv_enc_init_default(ssdv_t *ssdv) { - char result = ssdv_enc_init(ssdv, SSDV_TYPE_NORMAL, "", 0, 4, 256); - return result; -} - -/* Init the ssdv struct for decoding with default parameters */ -char ssdv_dec_init_default(ssdv_t *ssdv) { - char result = ssdv_dec_init(ssdv, 256); - return result; -} - /* Print the header decoded from pkt into fd */ void ssdv_print_header(uint8_t *pkt, FILE* fd) { ssdv_packet_info_t p; @@ -89,6 +77,12 @@ void ssdv_print_header_stderr(uint8_t *pkt) { return; } +/* Init the ssdv struct for decoding with default parameters */ +char ssdv_dec_init_default(ssdv_t *ssdv) { + char result = ssdv_dec_init(ssdv, 256); + return result; +} + /* Decode a buffer of ssdv packets * Fills a buffer with the resulting jpeg binary data, * and puts the length of the buffer in len_out @@ -144,7 +138,6 @@ uint8_t* ssdv_dec_buf_opts(ssdv_t *ssdv, uint8_t *src, size_t len_in, int verbos break; } read_offset += 1; - skipped++; } @@ -153,7 +146,6 @@ uint8_t* ssdv_dec_buf_opts(ssdv_t *ssdv, uint8_t *src, size_t len_in, int verbos if(verbose) { - if(skipped > 0) { fprintf(stderr, "Skipped %d bytes.\n", skipped); @@ -185,6 +177,88 @@ uint8_t* ssdv_dec_buf(ssdv_t *ssdv, uint8_t *src, size_t len_in, size_t *len_out return result; } + +/* Decode a file of ssdv packets + * Reads data from fin, and write to fout + */ +int ssdv_dec_file_opts(ssdv_t *ssdv, FILE *fin, FILE *fout, int verbose, int droptest) { + + int i, c; + int errors; + int pkt_length = SSDV_PKT_SIZE; + int skipped; + + uint8_t pkt[SSDV_PKT_SIZE], *jpeg; + size_t jpeg_length; + + jpeg_length = 1024 * 1024 * 4; + jpeg = malloc(jpeg_length); + ssdv_dec_set_buffer(ssdv, jpeg, jpeg_length); + + /* Save the current file position to reset it after decoding */ + size_t fpos = ftell(fin); + fseek(fin, 0, SEEK_SET); + + i = 0; + while(fread(pkt, pkt_length, 1, fin) > 0) + { + /* Drop % of packets */ + if(droptest && (rand() / (RAND_MAX / 100) < droptest)) continue; + + /* Test the packet is valid */ + skipped = 0; + while((c = ssdv_dec_is_packet(pkt, pkt_length, &errors)) != 0) + { + /* Read 1 byte at a time until a new packet is found */ + memmove(&pkt[0], &pkt[1], pkt_length - 1); + if(fread(&pkt[pkt_length - 1], 1, 1, fin) <= 0) + { + break; + } + skipped++; + } + + /* No valid packet was found before EOF */ + if(c != 0) break; + + if(verbose) + { + if(skipped > 0) + { + fprintf(stderr, "Skipped %d bytes.\n", skipped); + } + + ssdv_print_header_stderr(pkt); + } + + /* Feed it to the decoder */ + ssdv_dec_feed(ssdv, pkt); + i++; + } + + ssdv_dec_get_jpeg(ssdv, &jpeg, &jpeg_length); + fwrite(jpeg, 1, jpeg_length, fout); + free(jpeg); + + fprintf(stderr, "Read %i packets\n", i); + fseek(fin, fpos, SEEK_SET); + return 0; +} + +/* calls ssdv_dec_file_opts with default parameters */ +int ssdv_dec_file(ssdv_t *ssdv, FILE *fin, FILE *fout) { + int droptest = 0; + int verbose = 0; + int result = ssdv_dec_file_opts(ssdv, fin, fout, droptest, verbose); + return result; +} + +/* Init the ssdv struct for encoding with default parameters */ +char ssdv_enc_init_default(ssdv_t *ssdv) { + char result = ssdv_enc_init(ssdv, SSDV_TYPE_NORMAL, "", 0, 4, 256); + return result; +} + /* Encode a buffer of jpeg data * Fills a buffer with the resulting ssdv packets, * and puts the length of the buffer in len_out @@ -216,7 +290,6 @@ uint8_t* ssdv_enc_buf(ssdv_t *ssdv, uint8_t *src, size_t len_in, size_t *len_out b_arena.buf = b; b_arena.length = 128; - ssdv_enc_set_buffer(ssdv, pkt); i = 0; @@ -233,7 +306,7 @@ uint8_t* ssdv_enc_buf(ssdv_t *ssdv, uint8_t *src, size_t len_in, size_t *len_out if(r <= 0) { - fprintf(stderr, "Premature end of buffer: %u\n", read_offset); + fprintf(stderr, "Premature end of buffer: %zu\n", read_offset); break; } ssdv_enc_feed(ssdv, b, r); @@ -247,7 +320,7 @@ uint8_t* ssdv_enc_buf(ssdv_t *ssdv, uint8_t *src, size_t len_in, size_t *len_out else if(c != SSDV_OK) { fprintf(stderr, "ssdv_enc_get_packet failed: %i\n", c); - fprintf(stderr, "Total read: %u\n", read_offset); + fprintf(stderr, "Total read: %zu\n", read_offset); return 0; } /* Extend the buffer if we run out of room */ @@ -271,79 +344,6 @@ uint8_t* ssdv_enc_buf(ssdv_t *ssdv, uint8_t *src, size_t len_in, size_t *len_out *len_out = result.used; return result.buf; } - -/* Decode a file of ssdv packets - * Reads data from fin, and write to fout - */ -int ssdv_dec_file_opts(ssdv_t *ssdv, FILE *fin, FILE *fout, int droptest, int verbose) { - - int i, c; - int errors; - int pkt_length = SSDV_PKT_SIZE; - int skipped; - - uint8_t pkt[SSDV_PKT_SIZE], *jpeg; - size_t jpeg_length; - - jpeg_length = 1024 * 1024 * 4; - jpeg = malloc(jpeg_length); - ssdv_dec_set_buffer(ssdv, jpeg, jpeg_length); - - i = 0; - while(fread(pkt, pkt_length, 1, fin) > 0) - { - /* Drop % of packets */ - if(droptest && (rand() / (RAND_MAX / 100) < droptest)) continue; - - /* Test the packet is valid */ - skipped = 0; - while((c = ssdv_dec_is_packet(pkt, pkt_length, &errors)) != 0) - { - /* Read 1 byte at a time until a new packet is found */ - memmove(&pkt[0], &pkt[1], pkt_length - 1); - - if(fread(&pkt[pkt_length - 1], 1, 1, fin) <= 0) - { - break; - } - - skipped++; - } - - /* No valid packet was found before EOF */ - if(c != 0) break; - - if(verbose) - { - if(skipped > 0) - { - fprintf(stderr, "Skipped %d bytes.\n", skipped); - } - - ssdv_print_header_stderr(pkt); - } - - /* Feed it to the decoder */ - ssdv_dec_feed(ssdv, pkt); - i++; - } - - ssdv_dec_get_jpeg(ssdv, &jpeg, &jpeg_length); - fwrite(jpeg, 1, jpeg_length, fout); - free(jpeg); - - fprintf(stderr, "Read %i packets\n", i); - return 0; -} - -/* calls ssdv_dec_file_opts with default parameters */ -int ssdv_dec_file(ssdv_t *ssdv, FILE *fin, FILE *fout) { - int droptest = 0; - int verbose = 0; - int result = ssdv_dec_file_opts(ssdv, fin, fout, droptest, verbose); - return result; -} - /* Encode a jpeg file to ssdv packets * Reads data from fin, and write to fout */ @@ -355,6 +355,10 @@ int ssdv_enc_file(ssdv_t *ssdv, FILE *fin, FILE *fout) { ssdv_enc_set_buffer(ssdv, pkt); + /* Save the current file position to reset it after encoding */ + size_t fpos = ftell(fin); + fseek(fin, 0, SEEK_SET); + i = 0; while(1) @@ -387,7 +391,7 @@ int ssdv_enc_file(ssdv_t *ssdv, FILE *fin, FILE *fout) { } fprintf(stderr, "Wrote %i packets\n", i); + fseek(fin, fpos, SEEK_SET); return 0; - } diff --git a/ssdvutils.h b/ssdvutils.h index ca2263e..a6ab55b 100755 --- a/ssdvutils.h +++ b/ssdvutils.h @@ -31,7 +31,7 @@ void ssdv_print_header_stderr(uint8_t *pkt); char ssdv_dec_init_default(ssdv_t *ssdv); uint8_t* ssdv_dec_buf_opts(ssdv_t *ssdv, uint8_t *src, size_t len_in, int verbose, int droptest, size_t *len_out); uint8_t* ssdv_dec_buf(ssdv_t *ssdv, uint8_t *src, size_t len_in, size_t *len_out); -int ssdv_dec_file_opts(ssdv_t *ssdv, FILE *fin, FILE *fout, int droptest, int verbose); +int ssdv_dec_file_opts(ssdv_t *ssdv, FILE *fin, FILE *fout, int verbose, int droptest); int ssdv_dec_file(ssdv_t *ssdv, FILE *fin, FILE *fout); /* Encoding */ From 93b92e12719620607ca1cb57dc33faa4f8e02445 Mon Sep 17 00:00:00 2001 From: Bubbadime <146256626+Bubbadime@users.noreply.github.com> Date: Thu, 17 Jul 2025 18:56:45 +0100 Subject: [PATCH 08/14] Make a much better test --- test.c | 108 ++++++++++++++++++++++++++------------------------------- 1 file changed, 50 insertions(+), 58 deletions(-) diff --git a/test.c b/test.c index 63ca337..f70a2e6 100755 --- a/test.c +++ b/test.c @@ -40,68 +40,60 @@ uint8_t* ssdv_read_file(FILE* f, size_t *len_out) { } int main(int argc, char* argv[]) { - FILE *fin = stdin; - FILE *fout = stdout; - char type = SSDV_TYPE_NORMAL; - int verbose = 1; - char callsign[7]; + FILE *encIn, *encOut; + FILE *decIn, *decOut, *decOutOpts; + FILE *printOut; uint8_t image_id = 0; int8_t quality = 4; int pkt_length = SSDV_PKT_SIZE; ssdv_t ssdv; - FILE *ssdvFile, *jpegFile; - - - char rb[] = "rb"; - char wb[] = "wb"; - char encode = argc > 1; - - jpegFile = fopen("test.jpg", encode? rb : wb); - ssdvFile = fopen("test.ssdv", encode? wb : rb); - fin = encode? jpegFile : ssdvFile; - fout = (!encode)? jpegFile : ssdvFile; - - uint8_t *data = 0; - size_t dataLen; - - switch(encode) - { - case 0: /* Decode */ - - if(ssdv_dec_init(&ssdv, pkt_length) != SSDV_OK) - { - return(-1); - } - -#define MODE_BUF 1 -#if MODE_BUF - uint8_t *decoded; - size_t decodedLen; - printf("Read file next\n"); - data = ssdv_read_file(fin, &dataLen); - decoded = ssdv_dec_buf(&ssdv, data, dataLen, &decodedLen); - fwrite(decoded, decodedLen, 1, fout); -#else - ssdv_dec_file(&ssdv, fin, fout); -#endif - break; - case 1: /* Encode */ - - if(ssdv_enc_init_default(&ssdv) != SSDV_OK) - { - return(-1); - } -#if MODE_BUF - uint8_t *encoded; - size_t encodedLen; - data = ssdv_read_file(fin, &dataLen); - encoded = ssdv_enc_buf(&ssdv, data, dataLen, &encodedLen); - fwrite(encoded, encodedLen, 1, fout); -#else - ssdv_enc_file(&ssdv, fin, fout); -#endif - break; - } + + encIn = fopen("in.jpeg", "rb"); + encOut = fopen("out.ssdv", "wb"); + + decIn = fopen("in.ssdv", "rb"); + decOut = fopen("out.jpeg", "wb"); + decOutOpts = fopen("out_opts.jpeg", "wb"); + + printOut = fopen("print.txt", "w"); + + uint8_t *encBufIn, *encBufOut; + uint8_t *decBufIn, *decBufOut, *decBufOutOpts; + + size_t encLenIn, encLenOut, encLenOutOpts; + size_t decLenIn, decLenOut, decLenOutOpts; + + encBufIn = ssdv_read_file(encIn, &encLenIn); + decBufIn = ssdv_read_file(decIn, &decLenIn); + + /* Decoding */ + ssdv_dec_init_default(&ssdv); + ssdv_dec_file(&ssdv, decIn, decOut); + fclose(decOut); + + ssdv_dec_init_default(&ssdv); + ssdv_dec_file_opts(&ssdv, decIn, decOutOpts, 1, 0); + fclose(decOutOpts); + + ssdv_dec_init_default(&ssdv); + decBufOut = ssdv_dec_buf(&ssdv, decBufIn, decLenIn, &decLenOut); + + ssdv_dec_init_default(&ssdv); + decBufOutOpts = ssdv_dec_buf_opts(&ssdv, decBufIn, decLenIn, 1, 0, &decLenOutOpts); + +/* Encoding */ + ssdv_enc_init_default(&ssdv); + ssdv_enc_file(&ssdv, encIn, encOut); + fclose(encOut); + + ssdv_enc_init_default(&ssdv); + encBufOut = ssdv_enc_buf(&ssdv, encBufIn, encLenIn, &encLenOut); + +/* Printing */ + ssdv_print_header(decBufOut, printOut); + ssdv_print_header_stdout(decBufOut); + ssdv_print_header_stderr(decBufOut); + return 0; } From 841959577c9626d29adf72fd7233a49047949c15 Mon Sep 17 00:00:00 2001 From: Bubbadime <146256626+Bubbadime@users.noreply.github.com> Date: Thu, 24 Jul 2025 18:41:41 +0100 Subject: [PATCH 09/14] API naming improvements --- ssdvutils.c | 6 +++--- ssdvutils.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ssdvutils.c b/ssdvutils.c index a30d2ec..2d94ca6 100755 --- a/ssdvutils.c +++ b/ssdvutils.c @@ -45,7 +45,7 @@ static size_t ssdv_memcpy_packet(ssdv_mem_arena_t *src, ssdv_mem_arena_t *dest, } /* Print the header decoded from pkt into fd */ -void ssdv_print_header(uint8_t *pkt, FILE* fd) { +void ssdv_fprint_header(uint8_t *pkt, FILE* fd) { ssdv_packet_info_t p; ssdv_dec_header(&p, pkt); fprintf(fd, "decoded image packet. callsign: \"%s\", image id: %d, resolution: %dx%d, packet id: %d \n" @@ -66,13 +66,13 @@ void ssdv_print_header(uint8_t *pkt, FILE* fd) { } /* Print the header decoded from pkt to stdout */ -void ssdv_print_header_stdout(uint8_t *pkt) { +void ssdv_print_header(uint8_t *pkt) { ssdv_print_header(pkt, stdout); return; } /* Print the header decoded from pkt to stderr */ -void ssdv_print_header_stderr(uint8_t *pkt) { +void ssdv_perror_header(uint8_t *pkt) { ssdv_print_header(pkt, stderr); return; } diff --git a/ssdvutils.h b/ssdvutils.h index a6ab55b..efbce41 100755 --- a/ssdvutils.h +++ b/ssdvutils.h @@ -23,9 +23,9 @@ #include "ssdv.h" /* Printing */ -void ssdv_print_header(uint8_t *pkt, FILE* fd); -void ssdv_print_header_stdout(uint8_t *pkt); -void ssdv_print_header_stderr(uint8_t *pkt); +void ssdv_fprint_header(uint8_t *pkt, FILE* fd); +void ssdv_print_header(uint8_t *pkt); +void ssdv_perror_header(uint8_t *pkt); /* Decoding */ char ssdv_dec_init_default(ssdv_t *ssdv); From 8bc3cd7a813f4de60dae5dad3613ca53acf5f3b5 Mon Sep 17 00:00:00 2001 From: Bubbadime <146256626+Bubbadime@users.noreply.github.com> Date: Thu, 24 Jul 2025 18:51:46 +0100 Subject: [PATCH 10/14] Fix API usage --- Makefile | 2 +- ssdvutils.c | 8 ++++---- test.c | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 48a3dd1..553ede3 100755 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CC=gcc CFLAGS=-g -O3 -Wall LDFLAGS=-g -all: ssdv libssdv.so test +all: ssdv libssdv.so ssdv: main.o ssdv.o rs8.o ssdv.h rs8.h $(CC) $(LDFLAGS) main.o ssdv.o rs8.o -o ssdv diff --git a/ssdvutils.c b/ssdvutils.c index 2d94ca6..97d479e 100755 --- a/ssdvutils.c +++ b/ssdvutils.c @@ -67,13 +67,13 @@ void ssdv_fprint_header(uint8_t *pkt, FILE* fd) { /* Print the header decoded from pkt to stdout */ void ssdv_print_header(uint8_t *pkt) { - ssdv_print_header(pkt, stdout); + ssdv_fprint_header(pkt, stdout); return; } /* Print the header decoded from pkt to stderr */ void ssdv_perror_header(uint8_t *pkt) { - ssdv_print_header(pkt, stderr); + ssdv_fprint_header(pkt, stderr); return; } @@ -150,7 +150,7 @@ uint8_t* ssdv_dec_buf_opts(ssdv_t *ssdv, uint8_t *src, size_t len_in, int verbos { fprintf(stderr, "Skipped %d bytes.\n", skipped); } - ssdv_print_header_stderr(pkt); + ssdv_perror_header(pkt); pkt_arena.used = 0; } @@ -228,7 +228,7 @@ int ssdv_dec_file_opts(ssdv_t *ssdv, FILE *fin, FILE *fout, int verbose, int dro fprintf(stderr, "Skipped %d bytes.\n", skipped); } - ssdv_print_header_stderr(pkt); + ssdv_perror_header(pkt); } /* Feed it to the decoder */ diff --git a/test.c b/test.c index f70a2e6..4196f37 100755 --- a/test.c +++ b/test.c @@ -90,9 +90,9 @@ int main(int argc, char* argv[]) { encBufOut = ssdv_enc_buf(&ssdv, encBufIn, encLenIn, &encLenOut); /* Printing */ - ssdv_print_header(decBufOut, printOut); - ssdv_print_header_stdout(decBufOut); - ssdv_print_header_stderr(decBufOut); + ssdv_fprint_header(decBufOut, printOut); + ssdv_print_header(decBufOut); + ssdv_perror_header(decBufOut); return 0; } From c6f96e74e634bb94ef7c887d64fadd777a4b9658 Mon Sep 17 00:00:00 2001 From: Bubbadime <146256626+Bubbadime@users.noreply.github.com> Date: Fri, 25 Jul 2025 16:23:21 +0100 Subject: [PATCH 11/14] remove test.c and related --- .gitignore | 1 - Makefile | 3 -- test.c | 99 ------------------------------------------------------ 3 files changed, 103 deletions(-) delete mode 100755 test.c diff --git a/.gitignore b/.gitignore index a088a38..1b2a138 100755 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ ssdv -test *.o *.lo *.so diff --git a/Makefile b/Makefile index 553ede3..686454f 100755 --- a/Makefile +++ b/Makefile @@ -11,9 +11,6 @@ ssdv: main.o ssdv.o rs8.o ssdv.h rs8.h libssdv.so: ssdvutils.lo ssdv.lo rs8.lo ssdv.h rs8.h $(CC) -shared $(LDFLAGS) ssdvutils.lo ssdv.lo rs8.lo -o libssdv.so -test: test.c libssdv.so - $(CC) $(LDFLAGS) test.c -l:libssdv.so -o test - .c.o: $(CC) $(CFLAGS) -c $< -o $@ diff --git a/test.c b/test.c deleted file mode 100755 index 4196f37..0000000 --- a/test.c +++ /dev/null @@ -1,99 +0,0 @@ - -/* SSDV - Slow Scan Digital Video */ -/*=======================================================================*/ -/* Copyright 2011-2016 Philip Heron */ -/* */ -/* This program is free software: you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation, either version 3 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program. If not, see . */ - -/* ssdvutils.h added by GLRobotics 2025 */ - -// TODO(BP): REMOVE THIS FILE!!! - -#include -#include -#include -#include "ssdv.h" -#include "ssdvutils.h" - -uint8_t* ssdv_read_file(FILE* f, size_t *len_out) { - uint8_t* result = 0; - size_t fcur = ftell(f); - fseek(f, 0, SEEK_END); - size_t fsize = ftell(f); - result = malloc(fsize); - *len_out = fsize; - fseek(f, 0, SEEK_SET); - fread(result, *len_out, 1, f); - fseek(f, fcur, SEEK_SET); - return result; -} - -int main(int argc, char* argv[]) { - FILE *encIn, *encOut; - FILE *decIn, *decOut, *decOutOpts; - FILE *printOut; - uint8_t image_id = 0; - int8_t quality = 4; - int pkt_length = SSDV_PKT_SIZE; - ssdv_t ssdv; - - encIn = fopen("in.jpeg", "rb"); - encOut = fopen("out.ssdv", "wb"); - - decIn = fopen("in.ssdv", "rb"); - decOut = fopen("out.jpeg", "wb"); - decOutOpts = fopen("out_opts.jpeg", "wb"); - - printOut = fopen("print.txt", "w"); - - uint8_t *encBufIn, *encBufOut; - uint8_t *decBufIn, *decBufOut, *decBufOutOpts; - - size_t encLenIn, encLenOut, encLenOutOpts; - size_t decLenIn, decLenOut, decLenOutOpts; - - encBufIn = ssdv_read_file(encIn, &encLenIn); - decBufIn = ssdv_read_file(decIn, &decLenIn); - - /* Decoding */ - ssdv_dec_init_default(&ssdv); - ssdv_dec_file(&ssdv, decIn, decOut); - fclose(decOut); - - ssdv_dec_init_default(&ssdv); - ssdv_dec_file_opts(&ssdv, decIn, decOutOpts, 1, 0); - fclose(decOutOpts); - - ssdv_dec_init_default(&ssdv); - decBufOut = ssdv_dec_buf(&ssdv, decBufIn, decLenIn, &decLenOut); - - ssdv_dec_init_default(&ssdv); - decBufOutOpts = ssdv_dec_buf_opts(&ssdv, decBufIn, decLenIn, 1, 0, &decLenOutOpts); - -/* Encoding */ - ssdv_enc_init_default(&ssdv); - ssdv_enc_file(&ssdv, encIn, encOut); - fclose(encOut); - - ssdv_enc_init_default(&ssdv); - encBufOut = ssdv_enc_buf(&ssdv, encBufIn, encLenIn, &encLenOut); - -/* Printing */ - ssdv_fprint_header(decBufOut, printOut); - ssdv_print_header(decBufOut); - ssdv_perror_header(decBufOut); - - return 0; -} - From d053a5699830f519f9892306f93bcd6185991d57 Mon Sep 17 00:00:00 2001 From: Bubbadime <146256626+Bubbadime@users.noreply.github.com> Date: Fri, 25 Jul 2025 18:23:07 +0100 Subject: [PATCH 12/14] (Possibly) final cleanup --- Makefile | 2 +- ssdv.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 686454f..41ebad1 100755 --- a/Makefile +++ b/Makefile @@ -27,5 +27,5 @@ install: all install -m 644 rs8.h ${DESTDIR}/usr/include/ssdv clean: - rm -f *.o *.lo ssdv libssdv.so test + rm -f *.o *.lo ssdv libssdv.so diff --git a/ssdv.c b/ssdv.c index 3fe0dbc..22256f0 100755 --- a/ssdv.c +++ b/ssdv.c @@ -675,8 +675,8 @@ static char ssdv_have_marker(ssdv_t *s) /* Copy the data before processing */ if(s->marker_len > TBL_LEN + HBUFF_LEN - s->stbl_len) { - fprintf(stderr, "SSDV out of memory - marker len = %hu\n", s->marker_len); /* Not enough memory ... shouldn't happen! */ + fprintf(stderr, "Error: Not enough memory\n"); return(SSDV_ERROR); } From fc140e1f2f1b0a1a94a372b6576792d1e03fe388 Mon Sep 17 00:00:00 2001 From: Bubbadime <146256626+Bubbadime@users.noreply.github.com> Date: Thu, 31 Jul 2025 17:55:12 +0100 Subject: [PATCH 13/14] Use the correct packet size in utils.c --- ssdv.c | 0 ssdvutils.c | 26 +++++++++++--------------- ssdvutils.h | 0 3 files changed, 11 insertions(+), 15 deletions(-) mode change 100755 => 100644 ssdv.c mode change 100755 => 100644 ssdvutils.c mode change 100755 => 100644 ssdvutils.h diff --git a/ssdv.c b/ssdv.c old mode 100755 new mode 100644 diff --git a/ssdvutils.c b/ssdvutils.c old mode 100755 new mode 100644 index 97d479e..4815865 --- a/ssdvutils.c +++ b/ssdvutils.c @@ -97,7 +97,6 @@ uint8_t* ssdv_dec_buf_opts(ssdv_t *ssdv, uint8_t *src, size_t len_in, int verbos int i, c; int errors; - int pkt_length = SSDV_PKT_SIZE; int skipped; uint8_t pkt[SSDV_PKT_SIZE], *jpeg; @@ -120,7 +119,7 @@ uint8_t* ssdv_dec_buf_opts(ssdv_t *ssdv, uint8_t *src, size_t len_in, int verbos i = 0; size_t read_offset = 0; size_t bytes_read = 0; - while((bytes_read = ssdv_memcpy_packet(&src_arena, &pkt_arena, read_offset, pkt_length)) > 0) + while((bytes_read = ssdv_memcpy_packet(&src_arena, &pkt_arena, read_offset, ssdv->pkt_size)) > 0) { read_offset += bytes_read; /* Drop % of packets */ @@ -128,10 +127,10 @@ uint8_t* ssdv_dec_buf_opts(ssdv_t *ssdv, uint8_t *src, size_t len_in, int verbos /* Test the packet is valid */ skipped = 0; - while((c = ssdv_dec_is_packet(pkt, pkt_length, &errors)) != 0) + while((c = ssdv_dec_is_packet(pkt, ssdv->pkt_size, &errors)) != 0) { /* Read 1 byte at a time until a new packet is found */ - memmove(&pkt[0], &pkt[1], pkt_length - 1); + memmove(&pkt[0], &pkt[1], ssdv->pkt_size - 1); pkt_arena.used -= 1; if ((bytes_read = ssdv_memcpy_packet(&src_arena, &pkt_arena, read_offset, 1)) <= 0) { @@ -185,7 +184,6 @@ int ssdv_dec_file_opts(ssdv_t *ssdv, FILE *fin, FILE *fout, int verbose, int dro int i, c; int errors; - int pkt_length = SSDV_PKT_SIZE; int skipped; uint8_t pkt[SSDV_PKT_SIZE], *jpeg; @@ -200,18 +198,18 @@ int ssdv_dec_file_opts(ssdv_t *ssdv, FILE *fin, FILE *fout, int verbose, int dro fseek(fin, 0, SEEK_SET); i = 0; - while(fread(pkt, pkt_length, 1, fin) > 0) + while(fread(pkt, ssdv->pkt_size, 1, fin) > 0) { /* Drop % of packets */ if(droptest && (rand() / (RAND_MAX / 100) < droptest)) continue; /* Test the packet is valid */ skipped = 0; - while((c = ssdv_dec_is_packet(pkt, pkt_length, &errors)) != 0) + while((c = ssdv_dec_is_packet(pkt, ssdv->pkt_size, &errors)) != 0) { /* Read 1 byte at a time until a new packet is found */ - memmove(&pkt[0], &pkt[1], pkt_length - 1); - if(fread(&pkt[pkt_length - 1], 1, 1, fin) <= 0) + memmove(&pkt[0], &pkt[1], ssdv->pkt_size - 1); + if(fread(&pkt[ssdv->pkt_size - 1], 1, 1, fin) <= 0) { break; } @@ -283,10 +281,9 @@ uint8_t* ssdv_enc_buf(ssdv_t *ssdv, uint8_t *src, size_t len_in, size_t *len_out tmp.length = alloc_size; int i, c; - int pkt_length = SSDV_PKT_SIZE; uint8_t pkt[SSDV_PKT_SIZE], b[128]; pkt_arena.buf = pkt; - pkt_arena.length = pkt_length; + pkt_arena.length = ssdv->pkt_size; b_arena.buf = b; b_arena.length = 128; @@ -324,14 +321,14 @@ uint8_t* ssdv_enc_buf(ssdv_t *ssdv, uint8_t *src, size_t len_in, size_t *len_out return 0; } /* Extend the buffer if we run out of room */ - if (tmp.length - tmp.used < pkt_length) { + if (tmp.length - tmp.used < ssdv->pkt_size) { alloc_count *= 2; tmp.buf = realloc(tmp.buf, alloc_count * alloc_size); tmp.length = alloc_count * alloc_size; fprintf(stderr, "Had to realloc: %zu bytes used\n", alloc_count * alloc_size); } - ssdv_memcpy_packet(&pkt_arena, &tmp, 0, pkt_length); + ssdv_memcpy_packet(&pkt_arena, &tmp, 0, ssdv->pkt_size); i++; } if (tmp.length != tmp.used) { @@ -350,7 +347,6 @@ uint8_t* ssdv_enc_buf(ssdv_t *ssdv, uint8_t *src, size_t len_in, size_t *len_out int ssdv_enc_file(ssdv_t *ssdv, FILE *fin, FILE *fout) { int i, c; - int pkt_length = SSDV_PKT_SIZE; uint8_t pkt[SSDV_PKT_SIZE], b[128]; ssdv_enc_set_buffer(ssdv, pkt); @@ -386,7 +382,7 @@ int ssdv_enc_file(ssdv_t *ssdv, FILE *fin, FILE *fout) { return(-1); } - fwrite(pkt, 1, pkt_length, fout); + fwrite(pkt, 1, ssdv->pkt_size, fout); i++; } diff --git a/ssdvutils.h b/ssdvutils.h old mode 100755 new mode 100644 From 74858c2cf2b99aaedad34eccac01409eee5aa592 Mon Sep 17 00:00:00 2001 From: Bubbadime <146256626+Bubbadime@users.noreply.github.com> Date: Wed, 27 Aug 2025 21:05:53 +0100 Subject: [PATCH 14/14] Fix decoder not working unless verbose output is turned on --- ssdvutils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ssdvutils.c b/ssdvutils.c index 4815865..fc011c5 100644 --- a/ssdvutils.c +++ b/ssdvutils.c @@ -150,8 +150,8 @@ uint8_t* ssdv_dec_buf_opts(ssdv_t *ssdv, uint8_t *src, size_t len_in, int verbos fprintf(stderr, "Skipped %d bytes.\n", skipped); } ssdv_perror_header(pkt); - pkt_arena.used = 0; } + pkt_arena.used = 0; /* Feed it to the decoder */ ssdv_dec_feed(ssdv, pkt);