From: David Flynn <[email protected]>

Behavious is backwards compatible when pushing single aligned data units.

incorporates:
 - schroparse: remove useless tests, add guarantee comments

Signed-off-by: David Flynn <[email protected]>
---
 schroedinger/schrodecoder.c |   20 +++++-
 schroedinger/schrodecoder.h |    5 ++
 schroedinger/schroparse.c   |  159 +++++++++++++++++++++++++++++++++++++++++++
 schroedinger/schroparse.h   |   11 +++
 4 files changed, 194 insertions(+), 1 deletions(-)

diff --git a/schroedinger/schrodecoder.c b/schroedinger/schrodecoder.c
index b3f4c83..a189c7d 100644
--- a/schroedinger/schrodecoder.c
+++ b/schroedinger/schrodecoder.c
@@ -114,6 +114,9 @@ schro_decoder_new (void)
   decoder->skip_value = 1.0;
   decoder->skip_ratio = 1.0;
 
+  decoder->input_buflist = schro_buflist_new ();
+  decoder->sps = schro_parse_sync_new ();
+
   decoder->reference_queue = schro_queue_new (SCHRO_LIMIT_REFERENCE_FRAMES,
       (SchroQueueFreeFunc)schro_picture_unref);
   decoder->output_queue = schro_queue_new (SCHRO_LIMIT_REFERENCE_FRAMES,
@@ -705,7 +708,7 @@ schro_decoder_set_flushing (SchroDecoder *decoder, int 
value)
 }
 
 int
-schro_decoder_push (SchroDecoder *decoder, SchroBuffer *buffer)
+schro_decoder_push_old (SchroDecoder *decoder, SchroBuffer *buffer)
 {
   SchroUnpack unpack;
   int parse_code;
@@ -788,6 +791,21 @@ schro_decoder_push (SchroDecoder *decoder, SchroBuffer 
*buffer)
 }
 
 int
+schro_decoder_push (SchroDecoder *decoder, SchroBuffer *buffer)
+{
+  /* 1. buffer is added to the decoder input queue.
+   * 2. The synchronizer extracts (if possible) a data unit for parsing */
+  if (buffer)
+    schro_buflist_append (decoder->input_buflist, buffer);
+
+  buffer = schro_parse_sync (decoder->sps, decoder->input_buflist);
+  if (!buffer)
+    return SCHRO_DECODER_OK;
+
+  return schro_decoder_push_old (decoder, buffer);
+}
+
+int
 schro_decoder_iterate_picture (SchroDecoder *decoder, SchroBuffer *buffer, 
SchroUnpack *unpack, int parse_code)
 {
   SchroPicture *picture;
diff --git a/schroedinger/schrodecoder.h b/schroedinger/schrodecoder.h
index 8e35214..3e0cdf3 100644
--- a/schroedinger/schrodecoder.h
+++ b/schroedinger/schrodecoder.h
@@ -11,6 +11,8 @@
 #include <schroedinger/schroqueue.h>
 #include <schroedinger/schroasync.h>
 #include <schroedinger/schroarith.h>
+#include <schroedinger/schrobufferlist.h>
+#include <schroedinger/schroparse.h>
 
 SCHRO_BEGIN_DECLS
 
@@ -42,6 +44,9 @@ struct _SchroDecoder {
   SchroOpenGL *opengl;
   int use_opengl;
 
+  SchroBufferList *input_buflist;
+  SchroParseSyncState *sps;
+
   SchroPictureNumber next_frame_number;
 
   int major_version;
diff --git a/schroedinger/schroparse.c b/schroedinger/schroparse.c
index 36a4d35..1e80a21 100644
--- a/schroedinger/schroparse.c
+++ b/schroedinger/schroparse.c
@@ -176,3 +176,162 @@ schro_parse_decode_sequence_header (uint8_t *data, int 
length,
   return TRUE;
 }
 
+typedef struct parse_info {
+  uint32_t next_parse_offset;
+  uint32_t prev_parse_offset;
+  uint_least8_t parse_code;
+} parse_info_t;
+
+/* decode a parse info structure, storing the results in @*pi@
+ * returns 0 if decoding is unsuccessful
+ * returns 1 on success */
+int
+schro_parse_decode_parseinfo (uint8_t *data, unsigned length, parse_info_t *pi)
+{
+  if (length < 13) {
+    return 0;
+  }
+
+  if (data[0] != 'B' || data[1] != 'B' || data[2] != 'C' || data[3] != 'D') {
+    return 0;
+  }
+
+  pi->parse_code = data[4];
+  pi->next_parse_offset = data[5] << 24 | data[6] << 16 | data[7] << 8 | 
data[8];
+  pi->prev_parse_offset = data[9] << 24 | data[10] << 16 | data[11] << 8 | 
data[12];
+  return 1;
+}
+
+struct _SchroParseSyncState
+{
+  int sync_state;
+  unsigned offset;
+  uint32_t last_npo;
+};
+
+enum {
+  NOT_SYNCED = 0,
+  TRY_SYNC,
+  SYNCED,
+  SYNCED_INCOMPLETEDU,
+};
+
+SchroParseSyncState *
+schro_parse_sync_new (void)
+{
+  return schro_malloc0 (sizeof(SchroParseSyncState));
+}
+
+void
+schro_parse_sync_free (SchroParseSyncState *sps)
+{
+  schro_free (sps);
+}
+
+SchroBuffer *
+schro_parse_sync (SchroParseSyncState *sps, SchroBufferList *buflist)
+{
+  uint8_t tmp[13];
+  const uint8_t *parse_code_prefix = (const uint8_t*)"BBCD";
+  parse_info_t pu = {0};
+  SchroBuffer *du;
+
+  do {
+    switch (sps->sync_state) {
+    case NOT_SYNCED: { /* -> TRY_SYNC | NOT_SYNCED */
+      /* find start code (offset), stop so as to include a whole PI */
+      int found = schro_buflist_findbytes (buflist, &sps->offset, 
parse_code_prefix, 4);
+      /* xxx, worth flushing upto this point, although that is
+       * quite complicated. */
+      if (!found) {
+        return NULL;
+      }
+      /* protect the case where there aren't 9 more bytes after end of
+       * parse_code_prefix: offset + 12 = last byte of parse_info */
+      if (!schro_buflist_peekbytes (tmp, 1, buflist, sps->offset+12)) {
+        return NULL;
+      }
+      /* found, fall through */
+    }
+    case TRY_SYNC: { /* -> SYNCED | NOT_SYNCED */
+      parse_info_t pu1;
+      /* NB, we are guaranteed that reading 13 bytes from sps->offset will
+       * succeed, since NOT_SYNCED will not advance to this point if not */
+      schro_buflist_peekbytes (tmp, 13, buflist, sps->offset);
+      if (!schro_parse_decode_parseinfo (tmp, 13, &pu1)) {
+        goto try_sync_fail;
+      }
+      /* Check that prev_parse_offset doesn't reference something not yet seen 
*/
+      if (sps->offset < pu1.prev_parse_offset) {
+        goto try_sync_fail;
+      }
+      /* NB, guaranteed that there are 13 bytes avaliable */
+      schro_buflist_peekbytes (tmp, 13, buflist, sps->offset - 
pu1.prev_parse_offset);
+      if (!schro_parse_decode_parseinfo (tmp, 13, &pu)) {
+        goto try_sync_fail;
+      }
+      if (pu1.prev_parse_offset != pu.next_parse_offset) {
+try_sync_fail:
+        sps->sync_state = NOT_SYNCED;
+        sps->offset++;
+        /* find somewhere else to try again */
+        break;
+      }
+      sps->last_npo = pu.next_parse_offset;
+      /* offset was pointing at pu1, rewind to point at pu */
+      sps->offset -= pu.next_parse_offset;
+      sps->sync_state = SYNCED;
+      break;
+    }
+    case SYNCED: { /* -> SYNCED | SYNCED_INCOMPLETEDU | NOT_SYNCED */
+      int a;
+      if (schro_buflist_peekbytes (tmp, 13, buflist, sps->offset) < 13)
+        return NULL;
+      a = schro_parse_decode_parseinfo (tmp, 13, &pu);
+      if (!a || (sps->last_npo != pu.prev_parse_offset)) {
+        sps->sync_state = NOT_SYNCED;
+        break;
+      }
+      sps->last_npo = pu.next_parse_offset;
+      sps->sync_state = SYNCED;
+      break;
+    }
+    case SYNCED_INCOMPLETEDU: { /* -> SYNCED */
+      /* NB, this is safe -- to get here we must've already read pu
+       * previously, so no need to check that it is ok again */
+      schro_buflist_peekbytes (tmp, 13, buflist, sps->offset);
+      schro_parse_decode_parseinfo (tmp, 13, &pu);
+      sps->sync_state = SYNCED;
+      /* assume that the DU is complete this time */
+      break;
+    }
+    }
+  } while (NOT_SYNCED == sps->sync_state);
+
+  /*
+   * synced, attempt to extract a data unit
+   */
+
+  /* fixup for case where pu.next_parse_offset = 0 (eg, EOS) */
+  if (!pu.next_parse_offset) {
+    pu.next_parse_offset = 13;
+  }
+
+  /* flush everything upto the DU */
+  schro_buflist_flush (buflist, sps->offset);
+  sps->offset = 0;
+
+  /* try to extract the complete DU */
+  du = schro_buflist_extract(buflist, 0, pu.next_parse_offset);
+  if (!du) {
+    /* the whole DU isn't in the buffer, try again */
+    sps->sync_state = SYNCED_INCOMPLETEDU;
+    return NULL;
+  }
+
+  /* flush everything upto the end of DU */
+  schro_buflist_flush (buflist, pu.next_parse_offset);
+
+  return du;
+}
+
diff --git a/schroedinger/schroparse.h b/schroedinger/schroparse.h
index 39a0e9a..e80e9c4 100644
--- a/schroedinger/schroparse.h
+++ b/schroedinger/schroparse.h
@@ -3,12 +3,23 @@
 #define __SCHRO_PARSE_H__
 
 #include <schroedinger/schrovideoformat.h>
+#include <schroedinger/schrobufferlist.h>
 
 SCHRO_BEGIN_DECLS
 
 int schro_parse_decode_sequence_header (uint8_t *data, int length,
     SchroVideoFormat *video_format);
 
+#ifdef SCHRO_ENABLE_UNSTABLE_API
+
+typedef struct _SchroParseSyncState SchroParseSyncState;
+
+SchroParseSyncState *schro_parse_sync_new (void);
+void schro_parse_sync_free (SchroParseSyncState *);
+SchroBuffer *schro_parse_sync (SchroParseSyncState *sps, SchroBufferList 
*input_bufer);
+
+#endif
+
 SCHRO_END_DECLS
 
 #endif
-- 
1.5.6.5


------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
Schrodinger-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/schrodinger-devel

Reply via email to