From: David Flynn <[email protected]>

includes:
- decoder: fix outputing pictures in !coded_order
- decoder: fix semantics of get_picture_number, _pull, _ready

Extracting pictures in coded order doesn't require the RoB to be full
(and the system isn't flushing either)

Signed-off-by: David Flynn <[email protected]>
---
 schroedinger/schrodecoder.c |  138 ++++++++++++++++++++++++------------------
 schroedinger/schrodecoder.h |    5 +-
 2 files changed, 82 insertions(+), 61 deletions(-)

diff --git a/schroedinger/schrodecoder.c b/schroedinger/schrodecoder.c
index afd8b95..b8238e0 100644
--- a/schroedinger/schrodecoder.c
+++ b/schroedinger/schrodecoder.c
@@ -91,6 +91,7 @@ static void schro_decoder_picture_complete (SchroAsyncStage 
*stage);
 
 static void schro_decoder_error (SchroDecoder *decoder, const char *s);
 
+static void schro_picturequeue_rob_insert (SchroPictureQueue *queue, 
SchroPicture *pic);
 
 /* API */
 
@@ -122,8 +123,8 @@ schro_decoder_new (void)
   decoder->output_queue = schro_queue_new (SCHRO_LIMIT_REFERENCE_FRAMES,
       (SchroQueueFreeFunc)schro_frame_unref);
 
-  decoder->queue_depth = 4;
-  decoder->picture_queue = schro_queue_new (decoder->queue_depth,
+  decoder->reorder_buffer_size = 2+1;
+  decoder->reorder_buffer = schro_queue_new (decoder->reorder_buffer_size,
       (SchroQueueFreeFunc)schro_picture_unref);
 
   decoder->cpu_domain = schro_memory_domain_new_local ();
@@ -177,7 +178,7 @@ schro_decoder_free (SchroDecoder *decoder)
 
   schro_queue_free (decoder->output_queue);
   schro_queue_free (decoder->reference_queue);
-  schro_queue_free (decoder->picture_queue);
+  schro_queue_free (decoder->reorder_buffer);
 
   if (decoder->error_message) schro_free (decoder->error_message);
 
@@ -323,7 +324,7 @@ schro_decoder_reset (SchroDecoder *decoder)
 {
   schro_async_lock (decoder->async);
 
-  schro_queue_clear (decoder->picture_queue);
+  schro_queue_clear (decoder->reorder_buffer);
   schro_queue_clear (decoder->reference_queue);
   schro_queue_clear (decoder->output_queue);
 
@@ -383,7 +384,15 @@ schro_decoder_get_video_format (SchroDecoder *decoder)
 SchroPictureNumber
 schro_decoder_get_picture_number (SchroDecoder *decoder)
 {
-  return decoder->next_frame_number;
+  SchroPicture *picture = NULL;
+
+  if (decoder->reorder_buffer->n >= decoder->reorder_buffer_size ||
+      decoder->coded_order || decoder->flushing) {
+    picture = schro_queue_peek (decoder->reorder_buffer);
+  }
+  if (picture)
+    return picture->picture_number;
+  return SCHRO_PICTURE_NUMBER_INVALID;
 }
 
 /**
@@ -477,20 +486,17 @@ schro_decoder_set_picture_order (SchroDecoder *decoder, 
int order)
 static int
 schro_decoder_pull_is_ready_locked (SchroDecoder *decoder)
 {
-  SchroPicture *picture;
+  SchroPicture *picture = NULL;
 
-  if (decoder->coded_order) {
-    picture = schro_queue_peek (decoder->picture_queue);
-  } else {
-    picture = schro_picturequeue_find (decoder->picture_queue,
-        decoder->next_frame_number);
-  }
-  if (!picture && !decoder->flushing &&
-      schro_queue_is_full (decoder->picture_queue)) {
-    SCHRO_ERROR("failed to find picture %d", decoder->next_frame_number);
-    schro_decoder_error(decoder, "next picture not available in full queue");
-    return FALSE;
+  /* Not possible to pull from the RoB if not full */
+  /* NB, schro's RoB implementation can be larger than the spec */
+  if (decoder->reorder_buffer->n >= decoder->reorder_buffer_size ||
+      decoder->coded_order || decoder->flushing) {
+    picture = schro_queue_peek (decoder->reorder_buffer);
   }
+
+  /* XXX, maybe warn if expected picture not in RoB */
+
   if (picture && picture->stages[SCHRO_DECODER_STAGE_DONE].is_done) {
     return TRUE;
   }
@@ -523,34 +529,26 @@ schro_decoder_pull_is_ready_locked (SchroDecoder *decoder)
 SchroFrame *
 schro_decoder_pull (SchroDecoder *decoder)
 {
-  SchroPicture *picture;
+  SchroPicture *picture = NULL;
   SchroFrame *frame;
 
+#if 0
   SCHRO_DEBUG("searching for frame %d", decoder->next_frame_number);
+#endif
 
   schro_async_lock (decoder->async);
-  if (decoder->coded_order) {
-    picture = schro_queue_peek (decoder->picture_queue);
-  } else {
-    picture = schro_picturequeue_find (decoder->picture_queue, 
decoder->next_frame_number);
-  }
-  if (picture) {
-    if (picture->stages[SCHRO_DECODER_STAGE_DONE].is_done) {
-      schro_picturequeue_remove (decoder->picture_queue, 
picture->picture_number);
-    } else {
-      picture = NULL;
-    }
-  } else {
-    SCHRO_ERROR("next picture not in queue");
+
+  if (schro_decoder_pull_is_ready_locked (decoder)) {
+    picture = schro_queue_pull (decoder->reorder_buffer);
   }
+
   schro_async_unlock (decoder->async);
 
   if (!picture) {
     return NULL;
   }
 
-  decoder->next_frame_number++;
-
+  /* XXX would be nice to warn if expected picture not present */
   frame = schro_frame_ref (picture->output_picture);
   schro_picture_unref (picture);
 
@@ -588,8 +586,6 @@ schro_decoder_need_output_frame (SchroDecoder *decoder)
 static int
 schro_decoder_get_status_locked (SchroDecoder *decoder)
 {
-  SchroPicture *next_picture;
-
   if (schro_decoder_pull_is_ready_locked (decoder)) {
     return SCHRO_DECODER_OK;
   }
@@ -599,22 +595,20 @@ schro_decoder_get_status_locked (SchroDecoder *decoder)
   if (decoder->sequence_header_buffer &&
       schro_queue_is_empty (decoder->output_queue)) {
     int i;
-    for(i=0;i<decoder->picture_queue->n;i++){
-      SchroPicture *picture = decoder->picture_queue->elements[i].data;
+    for(i=0;i<decoder->reorder_buffer->n;i++){
+      SchroPicture *picture = decoder->reorder_buffer->elements[i];
       if (!picture->output_picture)
         return SCHRO_DECODER_NEED_FRAME;
     }
   }
-  if (!schro_queue_is_full (decoder->picture_queue) && !decoder->flushing) {
+  if (!schro_queue_is_full (decoder->reorder_buffer) && !decoder->flushing) {
     return SCHRO_DECODER_NEED_BITS;
   }
 
-  if (decoder->coded_order) {
-    next_picture = schro_queue_peek (decoder->picture_queue);
-  } else {
-    next_picture = schro_picturequeue_find (decoder->picture_queue, 
decoder->next_frame_number);
-  }
-  if (decoder->flushing && next_picture == NULL) {
+  /* surely this isn't right.  flushing implies EOS is on its way
+   * Actually, whats the difference between STALLED and WAIT ? */
+  /* or maybe, STALLED is when there is no work to be done */
+  if (decoder->flushing && !decoder->reorder_buffer->n) {
     if (decoder->end_of_stream) {
       return SCHRO_DECODER_EOS;
     } else {
@@ -645,8 +639,8 @@ schro_decoder_dump (SchroDecoder *decoder)
   int i;
 
   SCHRO_ERROR("index, picture_number, busy, state, needed_state, working");
-  for(i=0;i<decoder->picture_queue->n;i++){
-    SchroPicture *picture = decoder->picture_queue->elements[i];
+  for(i=0;i<decoder->reorder_buffer->n;i++){
+    SchroPicture *picture = decoder->reorder_buffer->elements[i];
 
     SCHRO_ERROR("%d: %d %d %04x %04x %04x",
         i, picture->picture_number,
@@ -655,7 +649,9 @@ schro_decoder_dump (SchroDecoder *decoder)
         0 /*picture->needed_state*/,
         0 /*picture->working*/);
   }
+#if 0
   SCHRO_ERROR("next_frame_number %d", decoder->next_frame_number);
+#endif
 }
 
 /**
@@ -841,6 +837,7 @@ schro_decoder_iterate_picture (SchroDecoder *decoder, 
SchroBuffer *buffer, Schro
 
   SCHRO_DEBUG("picturenumber: %u", picture->picture_number);
 
+#if 0 // XXX
   if (!decoder->have_frame_number) {
     if (params->num_refs > 0) {
       SCHRO_ERROR("expected I frame after sequence header");
@@ -849,6 +846,7 @@ schro_decoder_iterate_picture (SchroDecoder *decoder, 
SchroBuffer *buffer, Schro
     decoder->have_frame_number = TRUE;
     SCHRO_INFO("next frame number after seek %d", decoder->next_frame_number);
   }
+#endif
 
   if (picture->is_ref) {
     schro_async_lock (decoder->async);
@@ -862,11 +860,16 @@ schro_decoder_iterate_picture (SchroDecoder *decoder, 
SchroBuffer *buffer, Schro
     picture->skip = TRUE;
   }
 
+#if 0 // XXX
   if (picture->picture_number < decoder->next_frame_number) {
     SCHRO_DEBUG("picture out of order, skipping");
     schro_picture_unref (picture);
     return SCHRO_DECODER_OK;
   }
+  This should be combined with setting have_frame_number = TRUE.
+  Ie, want to use the definition of accessibility to skip pictures
+  from the previous gop (opengop)
+#endif
 
   if (!decoder->video_format.interlaced_coding &&
       !picture->is_ref && decoder->skip_value > decoder->skip_ratio) {
@@ -903,7 +906,11 @@ schro_decoder_iterate_picture (SchroDecoder *decoder, 
SchroBuffer *buffer, Schro
 
   schro_async_lock (decoder->async);
   SCHRO_DEBUG("adding %d to queue", picture->picture_number);
-  schro_queue_add (decoder->picture_queue, picture);
+  if (!decoder->coded_order) {
+    schro_picturequeue_rob_insert (decoder->reorder_buffer, picture);
+  } else {
+    schro_queue_add (decoder->reorder_buffer, picture);
+  }
   schro_async_signal_scheduler (decoder->async);
   schro_async_unlock (decoder->async);
 
@@ -1029,8 +1036,8 @@ schro_decoder_async_schedule (SchroDecoder *decoder,
     render_ok = TRUE;
   }
 
-  for(i=0;i<decoder->picture_queue->n;i++){
-    SchroPicture *picture = decoder->picture_queue->elements[i];
+  for(i=0;i<decoder->reorder_buffer->n;i++){
+    SchroPicture *picture = decoder->reorder_buffer->elements[i];
     void *func = NULL;
     int stage = 0;
 
@@ -2822,21 +2829,34 @@ schro_picturequeue_delete (SchroQueue *queue, 
SchroPictureNumber picture_number)
   }
 }
 
-SchroPicture *
-schro_picturequeue_remove (SchroQueue *queue, SchroPictureNumber 
picture_number)
+/* compare picture numbers in a way that handles wraph around */
+static inline int
+schro_picture_n_before_m (SchroPictureNumber n, SchroPictureNumber m)
+{
+  /* specified as: n occurs before m if:
+   *   (m - n) mod (1<<32) < D */
+  return (uint32_t)(m - n) < (1u<<31);
+}
+
+/* model the reorder buffer */
+static void
+schro_picturequeue_rob_insert (SchroPictureQueue *queue, SchroPicture *picture)
 {
   int i;
-  void *ret;
 
+  SCHRO_ASSERT (queue->n < queue->size);
+
+  /* find the position to insert before. */
   for(i=0;i<queue->n;i++){
-    if (((SchroPicture*)queue->elements[i])->picture_number == picture_number) 
{
-      ret = queue->elements[i];
-      memmove (queue->elements + i, queue->elements + i + 1,
-          sizeof(SchroQueueElement)*(queue->n - i - 1));
-      queue->n--;
-      return ret;
+    SchroPicture *pic = queue->elements[i];
+    if (schro_picture_n_before_m (picture->picture_number, 
pic->picture_number)) {
+      break;
     }
   }
 
-  return NULL;
+  /* make space and insert at i */
+  memmove (queue->elements + i + 1, queue->elements + i,
+          sizeof(SchroQueueElement)*(queue->n - i));
+  queue->n++;
+  queue->elements[i] = picture;
 }
diff --git a/schroedinger/schrodecoder.h b/schroedinger/schrodecoder.h
index 3e0cdf3..2191381 100644
--- a/schroedinger/schrodecoder.h
+++ b/schroedinger/schrodecoder.h
@@ -55,7 +55,9 @@ struct _SchroDecoder {
   int level;
   SchroVideoFormat video_format;
 
-  SchroPictureQueue *picture_queue;
+  SchroPictureQueue *reorder_buffer;
+
+  int reorder_buffer_size;
 
   int end_of_stream;
   int flushing;
@@ -173,7 +175,6 @@ void schro_picture_unref (SchroPicture *picture);
 /* Picture queue search functions */
 SchroPicture *schro_picturequeue_find (SchroPictureQueue *queue, 
SchroPictureNumber picture_number);
 void schro_picturequeue_delete (SchroPictureQueue *queue, SchroPictureNumber 
picture_number);
-SchroPicture *schro_picturequeue_remove (SchroPictureQueue *queue, 
SchroPictureNumber picture_number);
 
 int schro_decoder_iterate_picture (SchroDecoder *decoder, SchroBuffer *buffer, 
SchroUnpack *unpack, int parse_code);
 void schro_decoder_parse_picture (SchroPicture *picture, SchroUnpack *unpack);
-- 
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