Order FSM functions bottom up
authorMathis Rosenhauer <rosenhauer@dkrz.de>
Fri, 2 Nov 2012 16:57:50 +0000 (17:57 +0100)
committerThomas Jahns <jahns@dkrz.de>
Tue, 19 Feb 2013 10:33:00 +0000 (11:33 +0100)
src/encode.c

index 0483db9..9ee9803 100644 (file)
 #define ROS -1
 
 static int m_get_block(struct aec_stream *strm);
-static int m_get_rsi_resumable(struct aec_stream *strm);
-static int m_check_zero_block(struct aec_stream *strm);
-static int m_select_code_option(struct aec_stream *strm);
-static int m_flush_block(struct aec_stream *strm);
-static int m_flush_block_resumable(struct aec_stream *strm);
-static int m_encode_splitting(struct aec_stream *strm);
-static int m_encode_uncomp(struct aec_stream *strm);
-static int m_encode_se(struct aec_stream *strm);
-static int m_encode_zero(struct aec_stream *strm);
 
 static inline void emit(struct internal_state *state,
                         uint32_t data, int bits)
@@ -394,181 +385,48 @@ static int assess_se_option(uint64_t limit, struct aec_stream *strm)
  *
  */
 
-static int m_get_block(struct aec_stream *strm)
+static int m_flush_block_resumable(struct aec_stream *strm)
 {
     /**
-       Provide the next block of preprocessed input data.
-
-       Pull in a whole Reference Sample Interval (RSI) of data if
-       block buffer is empty.
+       Slow and restartable flushing
     */
-
     struct internal_state *state = strm->state;
 
-    if (strm->avail_out > state->cds_len) {
-        if (!state->direct_out) {
-            state->direct_out = 1;
-            *strm->next_out = *state->cds;
-            state->cds = strm->next_out;
-        }
-    } else {
-        if (state->zero_blocks == 0 || state->direct_out) {
-            /* copy leftover from last block */
-            *state->cds_buf = *state->cds;
-            state->cds = state->cds_buf;
-        }
-        state->direct_out = 0;
-    }
-
-    if (state->blocks_avail == 0) {
-        state->block = state->data_pp;
-
-        if (strm->avail_in >= state->block_len * strm->rsi) {
-            state->get_rsi(strm);
-            state->blocks_avail = strm->rsi - 1;
+    while(state->cds_buf + state->i < state->cds) {
+        if (strm->avail_out == 0)
+            return M_EXIT;
 
-            if (strm->flags & AEC_DATA_PREPROCESS) {
-                state->preprocess(strm);
-                state->ref = 1;
-            }
-            return m_check_zero_block(strm);
-        } else {
-            state->i = 0;
-            state->mode = m_get_rsi_resumable;
-        }
-    } else {
-        state->ref = 0;
-        state->block += strm->block_size;
-        state->blocks_avail--;
-        return m_check_zero_block(strm);
+        *strm->next_out++ = state->cds_buf[state->i];
+        strm->avail_out--;
+        strm->total_out++;
+        state->i++;
     }
+    state->mode = m_get_block;
     return M_CONTINUE;
 }
 
-static int m_get_rsi_resumable(struct aec_stream *strm)
-{
-    /**
-       Get RSI while input buffer is short.
-
-       Let user provide more input. Once we got all input pad buffer
-       to full RSI.
-    */
-
-    int j;
-    struct internal_state *state = strm->state;
-
-    do {
-        if (strm->avail_in > 0) {
-            state->data_raw[state->i] = state->get_sample(strm);
-        } else {
-            if (state->flush == AEC_FLUSH) {
-                if (state->i > 0) {
-                    for (j = state->i; j < strm->rsi * strm->block_size; j++)
-                        state->data_raw[j] = state->data_raw[state->i - 1];
-                    state->i = strm->rsi * strm->block_size;
-                } else {
-                    if (state->zero_blocks) {
-                        state->mode = m_encode_zero;
-                        return M_CONTINUE;
-                    }
-
-                    emit(state, 0, state->bits);
-                    if (state->direct_out == 0)
-                        *strm->next_out++ = *state->cds;
-                    strm->avail_out--;
-                    strm->total_out++;
-
-                    return M_EXIT;
-                }
-            } else {
-                return M_EXIT;
-            }
-        }
-    } while (++state->i < strm->rsi * strm->block_size);
-
-    state->blocks_avail = strm->rsi - 1;
-    if (strm->flags & AEC_DATA_PREPROCESS) {
-        state->preprocess(strm);
-        state->ref = 1;
-    }
-
-    return m_check_zero_block(strm);
-}
-
-static int m_check_zero_block(struct aec_stream *strm)
+static int m_flush_block(struct aec_stream *strm)
 {
     /**
-       Check if input block is all zero.
+       Flush block in direct_out mode by updating counters.
 
-       Aggregate consecutive zero blocks until we find !0 or reach the
-       end of a segment or RSI.
+       Fall back to slow flushing if in buffered mode.
     */
-
+    int n;
     struct internal_state *state = strm->state;
-    uint32_t *p = state->block + state->ref;
-    uint32_t *end = state->block + strm->block_size;
 
-    while(p < end && *p == 0)
-        p++;
-
-    if (p < end) {
-        if (state->zero_blocks) {
-            /* The current block isn't zero but we have to emit a
-             * previous zero block first. The current block will be
-             * handled later.
-             */
-            state->block -= strm->block_size;
-            state->blocks_avail++;
-            state->mode = m_encode_zero;
-            return M_CONTINUE;
-        }
-        state->mode = m_select_code_option;
-        return M_CONTINUE;
-    } else {
-        state->zero_blocks++;
-        if (state->zero_blocks == 1) {
-            state->zero_ref = state->ref;
-            state->zero_ref_sample = state->block[0];
-        }
-        if (state->blocks_avail == 0
-            || (strm->rsi - state->blocks_avail) % 64 == 0) {
-            if (state->zero_blocks > 4)
-                state->zero_blocks = ROS;
-            state->mode = m_encode_zero;
-            return M_CONTINUE;
-        }
+    if (state->direct_out) {
+        n = state->cds - strm->next_out;
+        strm->next_out += n;
+        strm->avail_out -= n;
+        strm->total_out += n;
         state->mode = m_get_block;
         return M_CONTINUE;
     }
-}
-
-static int m_select_code_option(struct aec_stream *strm)
-{
-    /**
-       Decide which code option to use.
-    */
-
-    uint64_t uncomp_len;
-    uint64_t split_len;
-    uint64_t se_len;
-    struct internal_state *state = strm->state;
-
-    uncomp_len = (strm->block_size - state->ref)
-        * strm->bit_per_sample;
-    split_len = assess_splitting_option(strm);
-    se_len = assess_se_option(split_len, strm);
 
-    if (split_len < uncomp_len) {
-        if (split_len < se_len)
-            return m_encode_splitting(strm);
-        else
-            return m_encode_se(strm);
-    } else {
-        if (uncomp_len <= se_len)
-            return m_encode_uncomp(strm);
-        else
-            return m_encode_se(strm);
-    }
+    state->i = 0;
+    state->mode = m_flush_block_resumable;
+    return M_CONTINUE;
 }
 
 static int m_encode_splitting(struct aec_stream *strm)
@@ -643,47 +501,180 @@ static int m_encode_zero(struct aec_stream *strm)
     return m_flush_block(strm);
 }
 
-static int m_flush_block(struct aec_stream *strm)
+static int m_select_code_option(struct aec_stream *strm)
 {
     /**
-       Flush block in direct_out mode by updating counters.
+       Decide which code option to use.
+    */
 
-       Fall back to slow flushing if in buffered mode.
+    uint64_t uncomp_len;
+    uint64_t split_len;
+    uint64_t se_len;
+    struct internal_state *state = strm->state;
+
+    uncomp_len = (strm->block_size - state->ref)
+        * strm->bit_per_sample;
+    split_len = assess_splitting_option(strm);
+    se_len = assess_se_option(split_len, strm);
+
+    if (split_len < uncomp_len) {
+        if (split_len < se_len)
+            return m_encode_splitting(strm);
+        else
+            return m_encode_se(strm);
+    } else {
+        if (uncomp_len <= se_len)
+            return m_encode_uncomp(strm);
+        else
+            return m_encode_se(strm);
+    }
+}
+
+static int m_check_zero_block(struct aec_stream *strm)
+{
+    /**
+       Check if input block is all zero.
+
+       Aggregate consecutive zero blocks until we find !0 or reach the
+       end of a segment or RSI.
     */
-    int n;
+
     struct internal_state *state = strm->state;
+    uint32_t *p = state->block + state->ref;
+    uint32_t *end = state->block + strm->block_size;
 
-    if (state->direct_out) {
-        n = state->cds - strm->next_out;
-        strm->next_out += n;
-        strm->avail_out -= n;
-        strm->total_out += n;
+    while(p < end && *p == 0)
+        p++;
+
+    if (p < end) {
+        if (state->zero_blocks) {
+            /* The current block isn't zero but we have to emit a
+             * previous zero block first. The current block will be
+             * handled later.
+             */
+            state->block -= strm->block_size;
+            state->blocks_avail++;
+            state->mode = m_encode_zero;
+            return M_CONTINUE;
+        }
+        state->mode = m_select_code_option;
+        return M_CONTINUE;
+    } else {
+        state->zero_blocks++;
+        if (state->zero_blocks == 1) {
+            state->zero_ref = state->ref;
+            state->zero_ref_sample = state->block[0];
+        }
+        if (state->blocks_avail == 0
+            || (strm->rsi - state->blocks_avail) % 64 == 0) {
+            if (state->zero_blocks > 4)
+                state->zero_blocks = ROS;
+            state->mode = m_encode_zero;
+            return M_CONTINUE;
+        }
         state->mode = m_get_block;
         return M_CONTINUE;
     }
+}
 
-    state->i = 0;
-    state->mode = m_flush_block_resumable;
-    return M_CONTINUE;
+static int m_get_rsi_resumable(struct aec_stream *strm)
+{
+    /**
+       Get RSI while input buffer is short.
+
+       Let user provide more input. Once we got all input pad buffer
+       to full RSI.
+    */
+
+    int j;
+    struct internal_state *state = strm->state;
+
+    do {
+        if (strm->avail_in > 0) {
+            state->data_raw[state->i] = state->get_sample(strm);
+        } else {
+            if (state->flush == AEC_FLUSH) {
+                if (state->i > 0) {
+                    for (j = state->i; j < strm->rsi * strm->block_size; j++)
+                        state->data_raw[j] = state->data_raw[state->i - 1];
+                    state->i = strm->rsi * strm->block_size;
+                } else {
+                    if (state->zero_blocks) {
+                        state->mode = m_encode_zero;
+                        return M_CONTINUE;
+                    }
+
+                    emit(state, 0, state->bits);
+                    if (state->direct_out == 0)
+                        *strm->next_out++ = *state->cds;
+                    strm->avail_out--;
+                    strm->total_out++;
+
+                    return M_EXIT;
+                }
+            } else {
+                return M_EXIT;
+            }
+        }
+    } while (++state->i < strm->rsi * strm->block_size);
+
+    state->blocks_avail = strm->rsi - 1;
+    if (strm->flags & AEC_DATA_PREPROCESS) {
+        state->preprocess(strm);
+        state->ref = 1;
+    }
+
+    return m_check_zero_block(strm);
 }
 
-static int m_flush_block_resumable(struct aec_stream *strm)
+static int m_get_block(struct aec_stream *strm)
 {
     /**
-       Slow and restartable flushing
+       Provide the next block of preprocessed input data.
+
+       Pull in a whole Reference Sample Interval (RSI) of data if
+       block buffer is empty.
     */
+
     struct internal_state *state = strm->state;
 
-    while(state->cds_buf + state->i < state->cds) {
-        if (strm->avail_out == 0)
-            return M_EXIT;
+    if (strm->avail_out > state->cds_len) {
+        if (!state->direct_out) {
+            state->direct_out = 1;
+            *strm->next_out = *state->cds;
+            state->cds = strm->next_out;
+        }
+    } else {
+        if (state->zero_blocks == 0 || state->direct_out) {
+            /* copy leftover from last block */
+            *state->cds_buf = *state->cds;
+            state->cds = state->cds_buf;
+        }
+        state->direct_out = 0;
+    }
 
-        *strm->next_out++ = state->cds_buf[state->i];
-        strm->avail_out--;
-        strm->total_out++;
-        state->i++;
+    if (state->blocks_avail == 0) {
+        state->block = state->data_pp;
+
+        if (strm->avail_in >= state->block_len * strm->rsi) {
+            state->get_rsi(strm);
+            state->blocks_avail = strm->rsi - 1;
+
+            if (strm->flags & AEC_DATA_PREPROCESS) {
+                state->preprocess(strm);
+                state->ref = 1;
+            }
+            return m_check_zero_block(strm);
+        } else {
+            state->i = 0;
+            state->mode = m_get_rsi_resumable;
+        }
+    } else {
+        state->ref = 0;
+        state->block += strm->block_size;
+        state->blocks_avail--;
+        return m_check_zero_block(strm);
     }
-    state->mode = m_get_block;
     return M_CONTINUE;
 }
 
@@ -816,8 +807,8 @@ int aec_encode(struct aec_stream *strm, int flush)
        encoder.
     */
     int n;
-    struct internal_state *state;
-    state = strm->state;
+    struct internal_state *state = strm->state;
+
     state->flush = flush;
 
     while (state->mode(strm) == M_CONTINUE);