Browse Source

Commit version 0.2 of libufodecode

Matthias Vogelgesang 11 years ago
parent
commit
45cc082d46
6 changed files with 246 additions and 119 deletions
  1. 3 3
      CMakeLists.txt
  2. 26 0
      NEWS
  3. 1 2
      src/ufodecode-private.h
  4. 39 62
      src/ufodecode.c
  5. 62 14
      src/ufodecode.h
  6. 115 38
      test/ipedec.c

+ 3 - 3
CMakeLists.txt

@@ -1,11 +1,11 @@
 cmake_minimum_required(VERSION 2.8)
 set(TARNAME "libufodecode")
 
-set(LIBUFODECODE_API_VERSION "0.1.0")
-set(LIBUFODECODE_ABI_VERSION "0.1.0")
+set(LIBUFODECODE_API_VERSION "0.2.0")
+set(LIBUFODECODE_ABI_VERSION "0.2.0")
 set(LIBUFODECODE_ABI_MAJOR_VERSION "0")
 
-set(PACKAGE_VERSION "0.1.0")
+set(PACKAGE_VERSION "0.2.0")
 set(PACKAGE_NAME "${TARNAME}")
 set(PACKAGE_TARNAME "${TARNAME}")
 set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")

+ 26 - 0
NEWS

@@ -0,0 +1,26 @@
+Changes in ufodecode 0.2.0
+==========================
+
+Name change
+-----------
+
+In accordance to the rest of the software, the type names changed from
+`ufo_decoder_t` to `UfoDecoder`. Moreover there is no typedef for pointers to
+`UfoDecoder` structures.
+
+
+API breakage
+------------
+
+To simplify debugging, all status data is passed from the decoded frame to the
+caller of `ufo_decoder_decode_frame()` and `ufo_decoder_get_next_frame()` by
+means of the new `UfoDecoderMeta` structure as defined in `ufodecode.h`.
+
+
+Minor changes
+-------------
+
+- The decoder supports version 4 and 5 of the UFO camera frame format.
+- `ipedec` now has a proper command line interface.
+- `ipedec` prints the frame meta data when using the verbose command line switch
+  (`-v` or `--verbose`).

+ 1 - 2
src/ufodecode-private.h

@@ -3,13 +3,12 @@
 
 #include <stdbool.h>
 
-struct ufo_decoder_t {
+struct _UfoDecoder {
     int32_t     height;
     uint32_t    width;
     uint32_t   *raw;
     size_t      num_bytes; 
     uint32_t    current_pos;
-    uint32_t    old_time_stamp;
 };
 
 

+ 39 - 62
src/ufodecode.c

@@ -69,20 +69,19 @@ typedef struct {
  * \return A new decoder instance that can be used to iterate over the frames
  * using ufo_decoder_get_next_frame.
  */
-ufo_decoder
+UfoDecoder *
 ufo_decoder_new (int32_t height, uint32_t width, uint32_t *raw, size_t num_bytes)
 {
     if (width % IPECAMERA_PIXELS_PER_CHANNEL)
         return NULL;
 
-    ufo_decoder decoder = malloc(sizeof(struct ufo_decoder_t));
+    UfoDecoder *decoder = malloc(sizeof(UfoDecoder));
 
     if (decoder == NULL)
         return NULL;
 
     decoder->width = width;
     decoder->height = height;
-    decoder->old_time_stamp = 0;
     ufo_decoder_set_raw_data(decoder, raw, num_bytes);
     return decoder;
 }
@@ -90,10 +89,10 @@ ufo_decoder_new (int32_t height, uint32_t width, uint32_t *raw, size_t num_bytes
 /**
  * \brief Release decoder instance
  *
- * \param decoder An ufo_decoder instance
+ * \param decoder An UfoDecoder instance
  */
 void
-ufo_decoder_free(ufo_decoder decoder)
+ufo_decoder_free(UfoDecoder *decoder)
 {
     free(decoder);
 }
@@ -101,12 +100,12 @@ ufo_decoder_free(ufo_decoder decoder)
 /**
  * \brief Set raw data stream
  *
- * \param decoder An ufo_decoder instance
+ * \param decoder An UfoDecoder instance
  * \param raw Raw data stream
  * \param num_bytes Size of data stream buffer in bytes
  */
 void
-ufo_decoder_set_raw_data(ufo_decoder decoder, uint32_t *raw, size_t num_bytes)
+ufo_decoder_set_raw_data(UfoDecoder *decoder, uint32_t *raw, size_t num_bytes)
 {
     decoder->raw = raw;
     decoder->num_bytes = num_bytes;
@@ -114,9 +113,8 @@ ufo_decoder_set_raw_data(ufo_decoder decoder, uint32_t *raw, size_t num_bytes)
 }
 
 static int
-ufo_decode_frame_channels_v0(ufo_decoder     decoder, 
+ufo_decode_frame_channels_v0(UfoDecoder     *decoder, 
                              uint16_t       *pixel_buffer, 
-                             uint16_t       *cmask, 
                              uint32_t       *raw, 
                              size_t          num_words, 
                              size_t         *offset)
@@ -159,9 +157,6 @@ ufo_decode_frame_channels_v0(ufo_decoder     decoder,
         CHECK_FLAG("row number, only %i rows requested", row < num_rows, row, num_rows);
         CHECK_FLAG("pixel size, only 10 bits are supported", bpp == 10, bpp);
         CHECK_FLAG("channel, limited by %zu output channels", channel < cpl, channel, cpl);
-        CHECK_FLAG("channel (line %i), duplicate entry",
-                (!cmask) || (cmask[row] & (1<<channel_order[channel])) == 0,
-                channel_order[channel], row);
 #endif
 
         if ((row > num_rows) || (channel > cpl) || (pixels > IPECAMERA_PIXELS_PER_CHANNEL))
@@ -170,9 +165,6 @@ ufo_decode_frame_channels_v0(ufo_decoder     decoder,
         channel = channel_order[channel];
         int base = row * IPECAMERA_WIDTH + channel * IPECAMERA_PIXELS_PER_CHANNEL;
 
-        if (cmask) 
-            cmask[row] |= (1 << channel);
-
         /* "Correct" missing pixel */
         if ((row < 2) && (pixels == (IPECAMERA_PIXELS_PER_CHANNEL - 1))) {
             pixel_buffer[base] = 0;
@@ -259,9 +251,8 @@ ufo_decode_frame_channels_v0(ufo_decoder     decoder,
 }
 
 static int
-ufo_decode_frame_channels_v4(ufo_decoder     decoder,
+ufo_decode_frame_channels_v4(UfoDecoder     *decoder,
                              uint16_t       *pixel_buffer, 
-                             uint16_t       *cmask, 
                              uint32_t       *raw, 
                              size_t          num_words, 
                              size_t          num_rows, 
@@ -307,9 +298,6 @@ ufo_decode_frame_channels_v4(ufo_decoder     decoder,
 
         CHECK_FLAG("pixel size, only 10 bits are supported", bpp == 10, bpp);
         CHECK_FLAG("channel, limited by %zu output channels", channel < channels_per_row, channel, channels_per_row);
-        CHECK_FLAG("channel (line %i), duplicate entry",
-                (!cmask) || (cmask[row] & (1 << channel_order[channel])) == 0,
-                channel_order[channel], row);
 #endif
 
         if ((channel > channels_per_row) || (pixels > IPECAMERA_PIXELS_PER_CHANNEL))
@@ -318,9 +306,6 @@ ufo_decode_frame_channels_v4(ufo_decoder     decoder,
         channel = channel_order[channel];
         int base = row * IPECAMERA_WIDTH + channel * IPECAMERA_PIXELS_PER_CHANNEL;
 
-        if (cmask) 
-            cmask[row] |= (1 << channel);
-
         /* "Correct" missing pixel */
         if ((row < 2) && (pixels == (IPECAMERA_PIXELS_PER_CHANNEL - 1))) {
             pixel_buffer[base] = 0;
@@ -407,9 +392,8 @@ ufo_decode_frame_channels_v4(ufo_decoder     decoder,
 }
 
 static int
-ufo_decode_frame_channels_v5(ufo_decoder     decoder, 
+ufo_decode_frame_channels_v5(UfoDecoder     *decoder, 
                              uint16_t       *pixel_buffer, 
-                             uint16_t       *cmask, 
                              uint32_t       *raw, 
                              size_t          num_words, 
                              size_t          num_rows, 
@@ -549,25 +533,21 @@ void ufo_deinterlace_weave(const uint16_t *in1, const uint16_t *in2, uint16_t *o
  *
  * This function tries to decode the supplied data
  *
- * \param decoder An ufo_decoder instance
+ * \param decoder An UfoDecoder instance
  * \param raw Raw data stream
  * \param num_bytes Size of data stream buffer in bytes
  * \param pixels If pointer with NULL content is passed, a new buffer is
  * allocated otherwise, this user-supplied buffer is used.
  * \param frame_number Frame number as reported in the header
  * \param time_stamp Time stamp of the frame as reported in the header
- * \paran cmask Change-mask
  *
  * \return number of decoded bytes or 0 in case of error
  */
-size_t ufo_decoder_decode_frame(ufo_decoder  decoder,
-                                uint32_t    *raw, 
-                                size_t       num_bytes, 
-                                uint16_t    *pixels, 
-                                uint32_t    *num_rows, 
-                                uint32_t    *frame_number,
-                                uint32_t    *time_stamp, 
-                                uint16_t    *cmask)
+size_t ufo_decoder_decode_frame(UfoDecoder      *decoder,
+                                uint32_t        *raw, 
+                                size_t           num_bytes, 
+                                uint16_t        *pixels, 
+                                UfoDecoderMeta  *meta)
 {
     int err = 0;
     size_t pos = 0;
@@ -591,19 +571,22 @@ size_t ufo_decoder_decode_frame(ufo_decoder  decoder,
         case 0:
             CHECK_VALUE(raw[pos++], 0x56666666);
             CHECK_VALUE(raw[pos] >> 28, 0x5);
-            *frame_number = raw[pos++] & 0xFFFFFFF;
+            meta->frame_number = raw[pos++] & 0xFFFFFFF;
             CHECK_VALUE(raw[pos] >> 28, 0x5);
-            *time_stamp = raw[pos++] & 0xFFFFFFF;
+            meta->time_stamp = raw[pos++] & 0xFFFFFFF;
             break;
 
         case 4:
         case 5:
             CHECK_VALUE(raw[pos] >> 28, 0x5);
-            rows_per_frame = raw[pos] & 0x7FF;
+            meta->cmosis_start_address = (raw[pos] >> 21) & 0x1FF;
+            meta->n_skipped_rows = (raw[pos] >> 15) & 0x3F;
+            meta->n_rows = rows_per_frame = raw[pos] & 0x7FF;
             pos++;
-            *frame_number = raw[pos++] & 0x1FFFFFF;
+
+            meta->frame_number = raw[pos++] & 0x1FFFFFF;
             CHECK_VALUE(raw[pos] >> 24, 0x50);
-            *time_stamp = raw[pos++] & 0xFFFFFF;
+            meta->time_stamp = raw[pos++] & 0xFFFFFF;
             break;
 
         default:
@@ -616,13 +599,13 @@ size_t ufo_decoder_decode_frame(ufo_decoder  decoder,
 #else
     switch (version) {
         case 0:
-            *frame_number = raw[pos + 6] & 0xFFFFFFF;
-            *time_stamp = raw[pos + 7] & 0xFFFFFFF;
+            meta->frame_number = raw[pos + 6] & 0xFFFFFFF;
+            meta->time_stamp = raw[pos + 7] & 0xFFFFFFF;
             break;
         case 4:
         case 5:
-            *frame_number = raw[pos + 6] & 0x1FFFFFF;
-            *time_stamp = raw[pos + 7] & 0xFFFFFF;
+            meta->frame_number = raw[pos + 6] & 0x1FFFFFF;
+            meta->time_stamp = raw[pos + 7] & 0xFFFFFF;
             break;
         default:
             fprintf(stderr, "Unsupported data format detected\n");
@@ -632,17 +615,15 @@ size_t ufo_decoder_decode_frame(ufo_decoder  decoder,
     pos += 8;
 #endif
 
-    *num_rows = rows_per_frame;
-
     switch (version) {
         case 0:
-            err = ufo_decode_frame_channels_v0(decoder, pixels, cmask, raw + pos, num_words - pos - 8, &advance);
+            err = ufo_decode_frame_channels_v0(decoder, pixels, raw + pos, num_words - pos - 8, &advance);
             break;
         case 4:
-            err = ufo_decode_frame_channels_v4(decoder, pixels, cmask, raw + pos, num_words - pos - 8, rows_per_frame, &advance);
+            err = ufo_decode_frame_channels_v4(decoder, pixels, raw + pos, num_words - pos - 8, rows_per_frame, &advance);
             break;
         case 5:
-            err = ufo_decode_frame_channels_v5(decoder, pixels, cmask, raw + pos, num_words - pos - 8, rows_per_frame, &advance);
+            err = ufo_decode_frame_channels_v5(decoder, pixels, raw + pos, num_words - pos - 8, rows_per_frame, &advance);
             break;
         default:
             break;
@@ -655,10 +636,11 @@ size_t ufo_decoder_decode_frame(ufo_decoder  decoder,
 
 #ifdef CHECKS
     CHECK_VALUE(raw[pos++], 0x0AAAAAAA);
+
+    meta->status1.bits = raw[pos++];
+    meta->status2.bits = raw[pos++];
+    meta->status3.bits = raw[pos++];
     pos++;
-    pos++; /* 0x840dffff expected */
-    pos++; /* 0x0f001001 expected */
-    pos++; /* 0x28000111 explains problems if status2 is wrong */
     pos++;
     CHECK_VALUE(raw[pos++], 0x00000000);
     CHECK_VALUE(raw[pos++], 0x01111111);
@@ -678,24 +660,20 @@ size_t ufo_decoder_decode_frame(ufo_decoder  decoder,
  * This function tries to decode the next frame in the currently set raw data
  * stream. 
  *
- * \param decoder An ufo_decoder instance
+ * \param decoder An UfoDecoder instance
  * \param pixels If pointer with NULL content is passed, a new buffer is
  * allocated otherwise, this user-supplied buffer is used.
  * \param num_rows Number of actual decoded rows
  * \param frame_number Frame number as reported in the header
  * \param time_stamp Time stamp of the frame as reported in the header
- * \paran cmask Change-mask
  *
  * \return 0 in case of no error, EIO if end of stream was reached, ENOMEM if
  * NULL was passed but no memory could be allocated, EILSEQ if data stream is
  * corrupt and EFAULT if pixels is a NULL-pointer.
  */
-int ufo_decoder_get_next_frame(ufo_decoder    decoder, 
-                               uint16_t     **pixels, 
-                               uint32_t      *num_rows, 
-                               uint32_t      *frame_number, 
-                               uint32_t      *time_stamp, 
-                               uint16_t      *cmask)
+int ufo_decoder_get_next_frame(UfoDecoder     *decoder, 
+                               uint16_t      **pixels, 
+                               UfoDecoderMeta *meta)
 {
     uint32_t *raw = decoder->raw;
     size_t pos = decoder->current_pos;
@@ -720,8 +698,7 @@ int ufo_decoder_get_next_frame(ufo_decoder    decoder,
     while ((pos < num_words) && (raw[pos] != 0x51111111))
         pos++;
 
-    advance = ufo_decoder_decode_frame(decoder, raw + pos, decoder->num_bytes -
-            pos, *pixels, num_rows, frame_number, time_stamp, cmask);
+    advance = ufo_decoder_decode_frame(decoder, raw + pos, decoder->num_bytes - pos, *pixels, meta);
 
     /*
      * On error, advance is 0 but we have to advance at least a bit to net get

+ 62 - 14
src/ufodecode.h

@@ -3,34 +3,82 @@
 
 #include <inttypes.h>
 
-typedef struct ufo_decoder_t *ufo_decoder;
+typedef struct _UfoDecoder UfoDecoder;
+
+typedef struct {
+    unsigned    dummy1:2;
+    unsigned    fsm_master_readout:4;
+    unsigned    dummy2:4;
+    unsigned    fsm_daq:4;
+    unsigned    pixel_full:1;
+    unsigned    control_lock:1;
+    unsigned    data_lock:16;
+} UfoDecoderStatus1;
+
+typedef struct {
+    unsigned    end_of_frames:1;
+    unsigned    busy_or:1;
+    unsigned    busy_ddr:1;
+    unsigned    busy_interl:1;
+    unsigned    error_status:4;   /* What the heck? */
+    unsigned    data_fifo_read_count:10;
+    unsigned    data_fifo_full:1;
+    unsigned    data_fifo_empty:1;
+    unsigned    dummy:2;
+    unsigned    ddr_fifo_write_count:8;
+    unsigned    ddr_fifo_full:1;
+    unsigned    ddr_fifo_empty:1;
+} UfoDecoderStatus2;
+
+typedef struct {
+    unsigned    dummy:2;
+    unsigned    row_counter:10;
+    unsigned    pixel_counter:8;
+    unsigned    ddr_read:4;
+    unsigned    ddr_write:4;
+    unsigned    ddr_arbiter:4;
+} UfoDecoderStatus3;
+
+typedef struct {
+    uint32_t        frame_number;
+    uint32_t        time_stamp;
+    uint32_t        n_rows;
+    uint8_t         n_skipped_rows;
+    uint16_t        cmosis_start_address;
+    union {
+        uint32_t            bits;
+        UfoDecoderStatus1   desc;
+    }                       status1;
+    union {
+        uint32_t            bits; 
+        UfoDecoderStatus2   desc;
+    }                       status2;
+    union {
+        uint32_t            bits; 
+        UfoDecoderStatus3   desc;
+    }                       status3;
+} UfoDecoderMeta;
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-ufo_decoder ufo_decoder_new             (int32_t         height, 
+UfoDecoder *ufo_decoder_new             (int32_t         height, 
                                          uint32_t        width, 
                                          uint32_t       *raw, 
                                          size_t          num_bytes);
-void        ufo_decoder_free            (ufo_decoder     decoder);
-size_t      ufo_decoder_decode_frame    (ufo_decoder     decoder, 
+void        ufo_decoder_free            (UfoDecoder     *decoder);
+size_t      ufo_decoder_decode_frame    (UfoDecoder     *decoder, 
                                          uint32_t       *raw, 
                                          size_t          num_bytes, 
                                          uint16_t       *pixels, 
-                                         uint32_t       *num_rows, 
-                                         uint32_t       *frame_number, 
-                                         uint32_t       *time_stamp, 
-                                         uint16_t       *cmask);
-void        ufo_decoder_set_raw_data    (ufo_decoder     decoder,
+                                         UfoDecoderMeta *meta);
+void        ufo_decoder_set_raw_data    (UfoDecoder     *decoder,
                                          uint32_t       *raw,
                                          size_t          num_bytes);
-int         ufo_decoder_get_next_frame  (ufo_decoder     decoder, 
+int         ufo_decoder_get_next_frame  (UfoDecoder     *decoder, 
                                          uint16_t      **pixels, 
-                                         uint32_t       *num_rows, 
-                                         uint32_t       *frame_number, 
-                                         uint32_t       *time_stamp, 
-                                         uint16_t       *cmask);
+                                         UfoDecoderMeta *meta_data);
 void        ufo_deinterlace_interpolate (const uint16_t *frame_in, 
                                          uint16_t       *frame_out, 
                                          int             width, 

+ 115 - 38
test/ipedec.c

@@ -8,8 +8,8 @@
 #include <getopt.h>
 #include <ufodecode.h>
 
-
-static int read_raw_file(const char *filename, char **buffer, size_t *length)
+static int
+read_raw_file(const char *filename, char **buffer, size_t *length)
 {
     FILE *fp = fopen(filename, "rb"); 
     if (fp == NULL)
@@ -35,7 +35,8 @@ static int read_raw_file(const char *filename, char **buffer, size_t *length)
     return 0;
 }
 
-static void usage(void)
+static void
+usage(void)
 {
     printf("usage: ipedec [--num-rows=ROWS] [--clear-frame] FILE [FILE ...]\n\
 Options:\n\
@@ -45,74 +46,150 @@ Options:\n\
   -c, --clear-frame  Clear the frame for each iteration\n");
 }
 
-static void process_file(const char *filename, int rows, int clear_frame, int verbose)
+static void
+print_meta_data (UfoDecoderMeta *meta)
+{
+    printf("  frame_number    = %i\n", meta->frame_number);
+    printf("  time_stamp      = %i\n", meta->time_stamp);
+    printf("  n_rows          = %i\n", meta->n_rows);
+    printf("  n_skipped_rows  = %i\n", meta->n_skipped_rows);
+
+    printf("  status1\n");
+    printf("    fsm_master_readout = %i\n", meta->status1.desc.fsm_master_readout);
+    printf("    fsm_daq         = %i\n", meta->status1.desc.fsm_daq);
+    printf("    pixel_full      = %i\n", meta->status1.desc.pixel_full);
+    printf("    control_lock    = %i\n", meta->status1.desc.control_lock);
+    printf("    data_lock       = %i\n", meta->status1.desc.data_lock);
+
+    printf("  status2\n");
+    printf("    end_of_frames   = %i\n", meta->status2.desc.end_of_frames);
+    printf("    busy_or         = %i\n", meta->status2.desc.busy_or);
+    printf("    busy_ddr        = %i\n", meta->status2.desc.busy_ddr);
+    printf("    busy_interl     = %i\n", meta->status2.desc.busy_interl);
+    printf("    error_status    = %i\n", meta->status2.desc.error_status);
+    printf("    data_fifo_read_count = %i\n", meta->status2.desc.data_fifo_read_count);
+    printf("    data_fifo_full       = %i\n", meta->status2.desc.data_fifo_full);
+    printf("    data_fifo_empty      = %i\n", meta->status2.desc.data_fifo_empty);
+    printf("    ddr_fifo_write_count = %i\n", meta->status2.desc.ddr_fifo_write_count);
+    printf("    ddr_fifo_full        = %i\n", meta->status2.desc.ddr_fifo_full);
+    printf("    ddr_fifo_empty       = %i\n", meta->status2.desc.ddr_fifo_empty);
+
+    printf("  status3\n");
+    printf("    row_counter     = %i\n", meta->status3.desc.row_counter);
+    printf("    pixel_counter   = %i\n", meta->status3.desc.pixel_counter);
+    printf("    ddr_read        = %i\n", meta->status3.desc.ddr_read);
+    printf("    ddr_write       = %i\n", meta->status3.desc.ddr_write);
+    printf("    ddr_arbiter     = %i\n", meta->status3.desc.ddr_arbiter);
+    printf("\n");
+}
+
+typedef struct {
+    struct timeval  start;
+    long            seconds;
+    long            useconds;
+} Timer;
+
+static Timer *
+timer_new (void)
+{
+    Timer *t = (Timer *) malloc (sizeof (Timer));
+    t->seconds = t->useconds = 0L;
+    return t;
+}
+
+static void
+timer_destroy (Timer *t)
+{
+    free (t);
+}
+
+static void
+timer_start (Timer *t)
+{
+    gettimeofday(&t->start, NULL);
+}
+
+static void
+timer_stop (Timer *t)
+{
+    struct timeval end;
+
+    gettimeofday(&end, NULL);
+    t->seconds += end.tv_sec - t->start.tv_sec;
+    t->useconds += end.tv_usec - t->start.tv_usec;
+}
+
+static void
+process_file(const char *filename, int rows, int clear_frame, int verbose)
 {
-    char *buffer = NULL;
-    size_t num_bytes = 0;
-    int err = 0;
-    uint16_t *pixels = (uint16_t *) malloc(2048 * 1088 * sizeof(uint16_t));
-    uint32_t num_rows, frame_number, time_stamp, old_time_stamp = 0;
-    int num_frames = 0;
-    struct timeval start, end;
-    long seconds = 0L, useconds = 0L;
-    int error = read_raw_file(filename, &buffer, &num_bytes);
+    UfoDecoder      *decoder;
+    UfoDecoderMeta   meta = {0};
+    Timer           *timer;
+    char            *buffer;
+    size_t           num_bytes;
+    int              error;
+    uint16_t        *pixels;
+    uint32_t         time_stamp, old_time_stamp;
+    int              n_frames = 0;
+    FILE            *fp;
+    char             output_name[256];
+    
+    error = read_raw_file(filename, &buffer, &num_bytes);
 
     if (error) {
         fprintf(stderr, "Error reading %s: %s\n", filename, strerror(error));
         return;
     }
 
-    ufo_decoder decoder = ufo_decoder_new(rows, 2048, (uint32_t *) buffer, num_bytes);
+    decoder = ufo_decoder_new(rows, 2048, (uint32_t *) buffer, num_bytes);
 
-    if (!decoder) {
+    if (decoder == NULL) {
         fprintf(stderr, "Failed to initialize decoder\n");
         return;
     }
 
-    char output_name[256];
     snprintf(output_name, 256, "%s.raw", filename);
-    FILE *fp = fopen(output_name, "wb");
+    fp = fopen(output_name, "wb");
 
     if (!fp) {
         fprintf(stderr, "Failed to open file for writing\n");
         return;
     }
 
-    while (err != EIO) {
+    timer = timer_new ();
+    pixels = (uint16_t *) malloc(2048 * 1088 * sizeof(uint16_t));
+    n_frames = 0;
+
+    while (error != EIO) {
         if (clear_frame)
             memset(pixels, 0, 2048 * 1088 * sizeof(uint16_t));
 
-        gettimeofday(&start, NULL);
-        err = ufo_decoder_get_next_frame(decoder, &pixels, &num_rows, &frame_number, &time_stamp, NULL);
-        gettimeofday(&end, NULL);
-
-        if (verbose) {
-            int time_stamp_diff = 80 * (time_stamp - old_time_stamp);
-
-            if (time_stamp_diff != 0)
-                printf(" %d\t %d\n", 1000000000 / time_stamp_diff, num_rows);
+        timer_start (timer);
+        error = ufo_decoder_get_next_frame(decoder, &pixels, &meta);
+        timer_stop (timer);
 
-            old_time_stamp = time_stamp;
-        }
+        if (!error) {
+            if (verbose) {
+                printf("Status for frame %i\n", n_frames);
+                print_meta_data (&meta);
+            }
 
-        if (!err) {
-            num_frames++;
-            seconds += end.tv_sec - start.tv_sec;
-            useconds += end.tv_usec - start.tv_usec;
+            n_frames++;
             fwrite(pixels, sizeof(uint16_t), 2048 * 1088, fp);
         }
-        else if (err != EIO)
-            fprintf(stderr, "Failed to decode frame %i\n", num_frames); 
+        else if (error != EIO)
+            fprintf(stderr, "Failed to decode frame %i\n", n_frames); 
     }
 
     fclose(fp);
 
-    float mtime = seconds * 1000.0 + useconds / 1000.0;
-    printf("Decoded %i frames in %.5fms\n", num_frames, mtime);
+    float mtime = timer->seconds * 1000.0 + timer->useconds / 1000.0;
+    printf("Decoded %i frames in %.5fms\n", n_frames, mtime);
 
     free(pixels);
-    ufo_decoder_free(decoder);
     free(buffer);
+    timer_destroy (timer);
+    ufo_decoder_free(decoder);
 }
 
 int main(int argc, char const* argv[])