From: David Flynn <dav...@rd.bbc.co.uk>

Traditionally, clients were required to wrap the decoder with a TLB,
that stored presentation time vs input picture number; when pulling
a picture, the presentation time would be extracted from the TLB.

Clients may be simplified by allowing schroedinger to do the tagging
based on simple rules:
 - a buffer may be supplied with a tag and free function
 - the tag is associated with the first byte of the buffer data
 - when using the autoparse api, the tag becomes associated with
   the next picture data unit to commence at or after the start of
   the buffer.
 - in cases where the above rule would associate multiple tags
   with one picture, the oldest shall take precedence.
 - tags are made avaliable as a member of the SchroFrame structure.
 - the contents of the tag are transparent to the decoder.

Signed-off-by: David Flynn <dav...@rd.bbc.co.uk>
---
 schroedinger/schrobuffer.c     |    2 +
 schroedinger/schrobuffer.h     |    2 +
 schroedinger/schrobufferlist.c |   63 ++++++++++++++++++++++++++++++++++-----
 schroedinger/schrodecoder.c    |   24 +++++++++++++++
 schroedinger/schrodecoder.h    |    9 ++++++
 schroedinger/schroframe.h      |    4 ++
 6 files changed, 96 insertions(+), 8 deletions(-)

diff --git a/schroedinger/schrobuffer.c b/schroedinger/schrobuffer.c
index 3e1636a..a38916d 100644
--- a/schroedinger/schrobuffer.c
+++ b/schroedinger/schrobuffer.c
@@ -82,6 +82,8 @@ schro_buffer_unref (SchroBuffer * buffer)
     SCHRO_DEBUG("free %p", buffer);
     if (buffer->free)
       buffer->free (buffer, buffer->priv);
+    if (buffer->tag_free)
+      buffer->tag_free (buffer->tag);
     schro_free (buffer);
   }
 }
diff --git a/schroedinger/schrobuffer.h b/schroedinger/schrobuffer.h
index f3df89c..c822049 100644
--- a/schroedinger/schrobuffer.h
+++ b/schroedinger/schrobuffer.h
@@ -20,6 +20,8 @@ struct _SchroBuffer
 
   void (*free) (SchroBuffer *, void *);
   void *priv;
+  void (*tag_free) (void *); /* NB, must be able to handle tag_free(NULL) */
+  void *tag;
 };
 
 SchroBuffer *schro_buffer_new (void);
diff --git a/schroedinger/schrobufferlist.c b/schroedinger/schrobufferlist.c
index ae7e379..05a588b 100644
--- a/schroedinger/schrobufferlist.c
+++ b/schroedinger/schrobufferlist.c
@@ -232,8 +232,10 @@ schro_buflist_flush (SchroBufferList *buflist, unsigned 
amount)
 SchroBuffer *
 schro_buflist_extract (SchroBufferList *buflist, unsigned start, unsigned len)
 {
-  SchroBuffer *buf;
-  unsigned start_orig = start;
+  SchroBuffer *buf, *dst;
+  void *tag = NULL;
+  void (*tag_free) (void *) = NULL;
+  unsigned pos = start;
   int bufidx;
   uint8_t tmp;
 
@@ -249,19 +251,64 @@ schro_buflist_extract (SchroBufferList *buflist, unsigned 
start, unsigned len)
   }
   /* guaranteed that the range is wholly contained within buflist */
 
-  bufidx = schro_buflist_internal_seek(buflist, &start);
+  bufidx = schro_buflist_internal_seek(buflist, &pos);
   SCHRO_ASSERT(bufidx < buflist->list->n);
 
   buf = buflist->list->members[bufidx];
 
-  if (start + len <= buf->length) {
+  /* Semantics for private void* in buffers in a bufferlist:
+   *  - Shall be associated with the next dataunit to commence after (or at)
+   *    the start of the buffer in the bufferist.
+   *  - May only be extracted once.
+   *  - If multiple void* could apply to the next dataunit, behaviour is 
undefined
+   *    NB: this implementation will discard all but the first.
+   *  - Ownership of the tag is transfered to the output buffer
+   */
+  tag = buf->tag;
+  tag_free = buf->tag_free;
+  buf->tag = NULL;
+
+  if (pos + len <= buf->length) {
     /* Special case, if the requested range is contained within a single
      * buffer, then use a subbuffer */
-    return schro_buffer_new_subbuffer (buf, start, len);
+    dst = schro_buffer_new_subbuffer (buf, pos, len);
+    dst->tag = tag;
+    dst->tag_free = tag_free;
+    return dst;
   }
 
-  buf = schro_buffer_new_and_alloc (len);
-  schro_buflist_peekbytes (buf->data, len, buflist, start_orig);
+  /* dataunit spans multiple buffers */
+  dst = schro_buffer_new_and_alloc (len);
+  dst->tag = tag;
+  dst->tag_free = tag_free;
+  tag = NULL;
+  schro_buflist_peekbytes (dst->data, len, buflist, start);
+
+  /* sort out rescuing the first tag that was in the extracted
+   * region and saving it ready for extraction at start+len. */
+  len += pos;
+  for (pos = 0; pos < len;)
+  {
+    buf = buflist->list->members[bufidx];
+    if (!tag) {
+      /* find the first non null tag we come across, take it,
+       * and [2] store it in the last buffer read from */
+      tag = buf->tag;
+      buf->tag = NULL;
+    }
+    /* any intermediate tags are discarded */
+    if (buf->tag_free) {
+      buf->tag_free(buf->tag);
+      buf->tag = NULL;
+    }
+    pos += buf->length;
+    bufidx++;
+  }
+  /* [2] store in last buffer of buflist */
+  /* xxx, this may need to be moved to the next buffer if
+   * exact consumption of buf occurs */
+  buf->tag = tag;
+  buf->tag_free = tag_free;
 
-  return buf;
+  return dst;
 }
diff --git a/schroedinger/schrodecoder.c b/schroedinger/schrodecoder.c
index 66f8516..3f3fb38 100644
--- a/schroedinger/schrodecoder.c
+++ b/schroedinger/schrodecoder.c
@@ -653,6 +653,10 @@ schro_decoder_pull (SchroDecoder *decoder)
 
   /* XXX would be nice to warn if expected picture not present */
   frame = schro_frame_ref (picture->output_picture);
+  frame->tag = picture->tag;
+  frame->tag_free = picture->tag_free;
+  picture->tag = NULL;
+
   schro_picture_unref (picture);
 
   return frame;
@@ -1021,9 +1025,13 @@ schro_decoder_push (SchroDecoder *decoder, SchroBuffer 
*buffer)
   }
 
   if (SCHRO_PARSE_CODE_IS_PICTURE(parse_code)) {
+    SchroDecoder *decoder = instance->decoder;
 
     if (!instance->have_sequence_header) {
       SCHRO_INFO ("no sequence header -- dropping picture");
+      if (decoder->free_picture_tag)
+        decoder->free_picture_tag(decoder->next_picture_tag);
+      decoder->next_picture_tag = NULL;
       schro_buffer_unref (buffer);
       return SCHRO_DECODER_OK;
     }
@@ -1060,6 +1068,17 @@ schro_decoder_autoparse_push (SchroDecoder *decoder, 
SchroBuffer *buffer)
     if (!buffer)
       return SCHRO_DECODER_NEED_BITS;
 
+    /* Buffers may have associated (tagged) private data.
+     * This data is to be associated with the next(/this) picture data unit */
+    if (buffer->tag) {
+      if (decoder->free_picture_tag) {
+        decoder->free_picture_tag (decoder->next_picture_tag);
+      }
+      decoder->next_picture_tag = buffer->tag;
+      decoder->free_picture_tag = buffer->tag_free;
+    }
+    buffer->tag_free = buffer->tag = NULL;
+
     switch (schro_decoder_push (decoder, buffer)) {
     default:
       break;
@@ -1085,6 +1104,11 @@ schro_decoder_iterate_picture (SchroDecoderInstance 
*instance, SchroBuffer *buff
 
   picture->input_buffer = buffer;
 
+  picture->tag = decoder->next_picture_tag;
+  picture->tag_free = decoder->free_picture_tag;
+  decoder->free_picture_tag =
+  decoder->next_picture_tag = NULL;
+
   params->num_refs = SCHRO_PARSE_CODE_NUM_REFS(parse_code);
   params->is_lowdelay = SCHRO_PARSE_CODE_IS_LOW_DELAY(parse_code);
   params->is_noarith = !SCHRO_PARSE_CODE_USING_AC(parse_code);
diff --git a/schroedinger/schrodecoder.h b/schroedinger/schrodecoder.h
index 8281efe..156ebae 100644
--- a/schroedinger/schrodecoder.h
+++ b/schroedinger/schrodecoder.h
@@ -52,6 +52,11 @@ struct _SchroDecoder {
   SchroBufferList *input_buflist;
   SchroParseSyncState *sps;
 
+  /* private data that is supplied with the input bitstream and
+   * is to be associated with the next picture to occur */
+  void *next_picture_tag;
+  void (*free_picture_tag) (void*);
+
   SchroDecoderInstance *instance;
 };
 
@@ -141,6 +146,10 @@ struct _SchroPicture {
 
   int has_md5;
   uint8_t md5_checksum[32];
+
+  /* private data that is associated with this picture */
+  void *tag;
+  void (*tag_free) (void*);
 };
 #endif
 
diff --git a/schroedinger/schroframe.h b/schroedinger/schroframe.h
index 4b0bb76..ac8516e 100644
--- a/schroedinger/schroframe.h
+++ b/schroedinger/schroframe.h
@@ -88,6 +88,10 @@ struct _SchroFrame {
   void *virt_priv2;
 
   int extension;
+
+  /* private data that is associated with this picture */
+  void *tag;
+  void (*tag_free) (void*);
 };
 
 struct _SchroUpsampledFrame {
-- 
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
Schrodinger-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/schrodinger-devel

Reply via email to