From: David Flynn <[email protected]>

Previously the SchroDecoder encapsulated all the state for decoding
a sequence.

Seperating the per sequence state into a SchroDecoderInstance allows
for:
 - pipelined parsing of EOS and the subsequent sequence.
 - pipelined decoding of pictures in both sequences.

This patch does not implement any of the above new features, just
refactors the current code to use a SchroDecoderInstance

includes:
 - decoder: fix missing init of instance->decoder

Signed-off-by: David Flynn <[email protected]>
---
 schroedinger/schrodecoder.c |  325 +++++++++++++++++++++++--------------------
 schroedinger/schrodecoder.h |   54 +++++---
 2 files changed, 212 insertions(+), 167 deletions(-)

diff --git a/schroedinger/schrodecoder.c b/schroedinger/schrodecoder.c
index acc85b4..6f6c7ee 100644
--- a/schroedinger/schrodecoder.c
+++ b/schroedinger/schrodecoder.c
@@ -78,11 +78,11 @@ static void schro_decoder_x_wavelet_transform 
(SchroAsyncStage *stage);
 static void schro_decoder_x_combine (SchroAsyncStage *stage);
 static void schro_decoder_x_upsample (SchroAsyncStage *stage);
 
-static void schro_decoder_reference_add (SchroDecoder *decoder,
+static void schro_decoder_reference_add (SchroDecoderInstance *instance,
     SchroPicture *picture);
-static SchroPicture * schro_decoder_reference_get (SchroDecoder *decoder,
+static SchroPicture * schro_decoder_reference_get (SchroDecoderInstance 
*instance,
     SchroPictureNumber frame_number);
-static void schro_decoder_reference_retire (SchroDecoder *decoder,
+static void schro_decoder_reference_retire (SchroDecoderInstance *instance,
     SchroPictureNumber frame_number);
 static void schro_decoder_decode_subband (SchroPicture *picture,
     SchroPictureSubbandContext *ctx);
@@ -95,6 +95,41 @@ static void schro_picturequeue_rob_insert (SchroPictureQueue 
*queue, SchroPictur
 
 /* API */
 
+SchroDecoderInstance *
+schro_decoder_instance_new (SchroDecoder *decoder)
+{
+  SchroDecoderInstance *instance;
+
+  instance = schro_malloc0 (sizeof(SchroDecoderInstance));
+
+  instance->decoder = decoder;
+
+  instance->reference_queue = schro_queue_new (SCHRO_LIMIT_REFERENCE_FRAMES,
+      (SchroQueueFreeFunc)schro_picture_unref);
+  instance->output_queue = schro_queue_new (SCHRO_LIMIT_REFERENCE_FRAMES,
+      (SchroQueueFreeFunc)schro_frame_unref);
+
+  instance->reorder_buffer_size = 2+1;
+  instance->reorder_buffer = schro_queue_new (instance->reorder_buffer_size,
+      (SchroQueueFreeFunc)schro_picture_unref);
+
+  return instance;
+}
+
+void
+schro_decoder_instance_free (SchroDecoderInstance *instance)
+{
+  schro_queue_free (instance->output_queue);
+  schro_queue_free (instance->reference_queue);
+  schro_queue_free (instance->reorder_buffer);
+
+  if (instance->sequence_header_buffer) {
+    schro_buffer_unref (instance->sequence_header_buffer);
+  }
+
+  schro_free (instance);
+}
+
 /**
  * schro_decoder_new:
  *
@@ -118,15 +153,6 @@ schro_decoder_new (void)
   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,
-      (SchroQueueFreeFunc)schro_frame_unref);
-
-  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 ();
 #ifdef HAVE_CUDA
   decoder->cuda_domain = schro_memory_domain_new_cuda ();
@@ -160,6 +186,8 @@ schro_decoder_new (void)
   }
 #endif
 
+  decoder->instance = schro_decoder_instance_new (decoder);
+
   return decoder;
 }
 
@@ -176,9 +204,10 @@ schro_decoder_free (SchroDecoder *decoder)
     schro_async_free (decoder->async);
   }
 
-  schro_queue_free (decoder->output_queue);
-  schro_queue_free (decoder->reference_queue);
-  schro_queue_free (decoder->reorder_buffer);
+  schro_decoder_instance_free (decoder->instance);
+
+  if (decoder->input_buflist) schro_buflist_free (decoder->input_buflist);
+  schro_parse_sync_free (decoder->sps);
 
   if (decoder->error_message) schro_free (decoder->error_message);
 
@@ -190,7 +219,6 @@ schro_decoder_free (SchroDecoder *decoder)
   if (decoder->cuda_domain) schro_memory_domain_free (decoder->cuda_domain);
   if (decoder->opengl_domain) schro_memory_domain_free 
(decoder->opengl_domain);
 
-  if (decoder->sequence_header_buffer) schro_buffer_unref 
(decoder->sequence_header_buffer);
 
   schro_free (decoder);
 }
@@ -206,11 +234,12 @@ schro_decoder_free (SchroDecoder *decoder)
  * Returns: a new picture
  */
 SchroPicture *
-schro_picture_new (SchroDecoder *decoder)
+schro_picture_new (SchroDecoderInstance *instance)
 {
+  SchroDecoder *decoder = instance->decoder;
   SchroPicture *picture;
   SchroFrameFormat frame_format;
-  SchroVideoFormat *video_format = &decoder->video_format;
+  SchroVideoFormat *video_format = &instance->video_format;
   int picture_width, picture_height;
   int iwt_width, iwt_height;
   int picture_chroma_width, picture_chroma_height;
@@ -218,7 +247,7 @@ schro_picture_new (SchroDecoder *decoder)
   picture = schro_malloc0 (sizeof(SchroPicture));
   picture->refcount = 1;
 
-  picture->decoder = decoder;
+  picture->decoder_instance = instance;
 
   picture->params.video_format = video_format;
 
@@ -324,27 +353,15 @@ schro_decoder_reset (SchroDecoder *decoder)
 {
   schro_async_lock (decoder->async);
 
-  schro_queue_clear (decoder->reorder_buffer);
-  schro_queue_clear (decoder->reference_queue);
-  schro_queue_clear (decoder->output_queue);
-
   schro_buflist_free (decoder->input_buflist);
   decoder->input_buflist = schro_buflist_new ();
 
   schro_parse_sync_free (decoder->sps);
   decoder->sps = schro_parse_sync_new ();
 
-  if (decoder->sequence_header_buffer) {
-    schro_buffer_unref (decoder->sequence_header_buffer);
-  }
-  decoder->sequence_header_buffer = NULL;
-
-  decoder->next_frame_number = 0;
-  decoder->have_frame_number = FALSE;
+  schro_decoder_instance_free (decoder->instance);
+  decoder->instance = schro_decoder_instance_new (decoder);
 
-  decoder->first_seqhdr = FALSE;
-  decoder->end_of_stream = FALSE;
-  decoder->flushing = FALSE;
   schro_async_unlock (decoder->async);
 
   decoder->error = FALSE;
@@ -360,6 +377,7 @@ schro_decoder_reset (SchroDecoder *decoder)
  *
  * Returns: a video format structure
  */
+/* xxx: this is nolonger api/client thread safe with respect to reset */
 SchroVideoFormat *
 schro_decoder_get_video_format (SchroDecoder *decoder)
 {
@@ -368,7 +386,7 @@ schro_decoder_get_video_format (SchroDecoder *decoder)
   /* FIXME check that decoder is in the right state */
 
   format = malloc(sizeof(SchroVideoFormat));
-  memcpy (format, &decoder->video_format, sizeof(SchroVideoFormat));
+  memcpy (format, &decoder->instance->video_format, sizeof(SchroVideoFormat));
 
   return format;
 }
@@ -385,11 +403,12 @@ schro_decoder_get_video_format (SchroDecoder *decoder)
 SchroPictureNumber
 schro_decoder_get_picture_number (SchroDecoder *decoder)
 {
+  SchroDecoderInstance *instance = decoder->instance;
   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 (instance->reorder_buffer->n >= instance->reorder_buffer_size ||
+      decoder->coded_order || instance->flushing) {
+    picture = schro_queue_peek (instance->reorder_buffer);
   }
   if (picture)
     return picture->picture_number;
@@ -411,7 +430,7 @@ schro_decoder_get_picture_number (SchroDecoder *decoder)
 void
 schro_decoder_add_output_picture (SchroDecoder *decoder, SchroFrame *frame)
 {
-  schro_queue_add (decoder->output_queue, frame);
+  schro_queue_add (decoder->instance->output_queue, frame);
 }
 
 /**
@@ -436,7 +455,7 @@ void
 schro_decoder_set_earliest_frame (SchroDecoder *decoder,
     SchroPictureNumber earliest_frame)
 {
-  decoder->earliest_frame = earliest_frame;
+    /* todo: deprecate this function? */
 }
 
 /**
@@ -487,13 +506,14 @@ schro_decoder_set_picture_order (SchroDecoder *decoder, 
int order)
 static int
 schro_decoder_pull_is_ready_locked (SchroDecoder *decoder)
 {
+  SchroDecoderInstance *instance = decoder->instance;
   SchroPicture *picture = NULL;
 
   /* 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);
+  if (instance->reorder_buffer->n >= instance->reorder_buffer_size ||
+      decoder->coded_order || instance->flushing) {
+    picture = schro_queue_peek (instance->reorder_buffer);
   }
 
   /* XXX, maybe warn if expected picture not in RoB */
@@ -540,7 +560,7 @@ schro_decoder_pull (SchroDecoder *decoder)
   schro_async_lock (decoder->async);
 
   if (schro_decoder_pull_is_ready_locked (decoder)) {
-    picture = schro_queue_pull (decoder->reorder_buffer);
+    picture = schro_queue_pull (decoder->instance->reorder_buffer);
   }
 
   schro_async_unlock (decoder->async);
@@ -577,10 +597,11 @@ schro_decoder_push_ready (SchroDecoder *decoder)
 static int
 schro_decoder_need_output_frame_locked (SchroDecoder *decoder)
 {
-  int num_frames_in_hand = decoder->output_queue->n;
+  SchroDecoderInstance *instance = decoder->instance;
+  int num_frames_in_hand = instance->output_queue->n;
   int i;
-  for(i=0;i<decoder->reorder_buffer->n;i++){
-    SchroPicture *picture = decoder->reorder_buffer->elements[i];
+  for(i=0; i < instance->reorder_buffer->n; i++){
+    SchroPicture *picture = instance->reorder_buffer->elements[i];
     if (!picture->output_picture)
       num_frames_in_hand--;
   }
@@ -602,9 +623,10 @@ schro_decoder_need_output_frame (SchroDecoder *decoder)
 static int
 schro_decoder_get_status_locked (SchroDecoder *decoder)
 {
+  SchroDecoderInstance *instance = decoder->instance;
   /* NB, this function should be `pure' (no sideeffects),
    * since it is called in a context which should not update state */
-  if (decoder->first_seqhdr) {
+  if (instance->first_seqhdr) {
     return SCHRO_DECODER_FIRST_ACCESS_UNIT;
   }
   if (schro_decoder_pull_is_ready_locked (decoder)) {
@@ -613,19 +635,19 @@ schro_decoder_get_status_locked (SchroDecoder *decoder)
   if (decoder->error) {
     return SCHRO_DECODER_ERROR;
   }
-  if (decoder->sequence_header_buffer &&
+  if (instance->sequence_header_buffer &&
       schro_decoder_need_output_frame_locked (decoder)) {
     return SCHRO_DECODER_NEED_FRAME;
   }
-  if (!schro_queue_is_full (decoder->reorder_buffer) && !decoder->flushing) {
+  if (!schro_queue_is_full (instance->reorder_buffer) && !instance->flushing) {
     return SCHRO_DECODER_NEED_BITS;
   }
 
   /* 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) {
+  if (instance->flushing && !instance->reorder_buffer->n) {
+    if (instance->end_of_stream) {
       return SCHRO_DECODER_EOS;
     } else {
       return SCHRO_DECODER_STALLED;
@@ -652,11 +674,12 @@ schro_decoder_get_status (SchroDecoder *decoder)
 static void
 schro_decoder_dump (SchroDecoder *decoder)
 {
+  SchroDecoderInstance *instance = decoder->instance;
   int i;
 
   SCHRO_ERROR("index, picture_number, busy, state, needed_state, working");
-  for(i=0;i<decoder->reorder_buffer->n;i++){
-    SchroPicture *picture = decoder->reorder_buffer->elements[i];
+  for(i=0; i < instance->reorder_buffer->n; i++){
+    SchroPicture *picture = instance->reorder_buffer->elements[i];
 
     SCHRO_ERROR("%d: %d %d %04x %04x %04x",
         i, picture->picture_number,
@@ -666,7 +689,7 @@ schro_decoder_dump (SchroDecoder *decoder)
         0 /*picture->working*/);
   }
 #if 0
-  SCHRO_ERROR("next_frame_number %d", decoder->next_frame_number);
+  SCHRO_ERROR("next_frame_number %d", instance->next_frame_number);
 #endif
 }
 
@@ -690,7 +713,7 @@ schro_decoder_wait (SchroDecoder *decoder)
     ret = schro_decoder_get_status_locked (decoder);
     if (ret == SCHRO_DECODER_FIRST_ACCESS_UNIT) {
       /* clean up for next iteration */
-      decoder->first_seqhdr = 0;
+      decoder->instance->first_seqhdr = 0;
     }
     if (ret != SCHRO_DECODER_WAIT) {
       break;
@@ -713,8 +736,8 @@ schro_decoder_wait (SchroDecoder *decoder)
 int
 schro_decoder_push_end_of_stream (SchroDecoder *decoder)
 {
-  decoder->flushing = TRUE;
-  decoder->end_of_stream = TRUE;
+  decoder->instance->flushing = TRUE;
+  decoder->instance->end_of_stream = TRUE;
   return SCHRO_DECODER_EOS;
 }
 
@@ -732,11 +755,11 @@ schro_decoder_set_flushing (SchroDecoder *decoder, int 
value)
 }
 
 void
-schro_decoder_push_old (SchroDecoder *decoder, SchroBuffer *buffer)
+schro_decoder_push_old (SchroDecoderInstance *instance, SchroBuffer *buffer)
 {
   SchroUnpack unpack;
   int parse_code;
-  decoder->flushing = FALSE;
+  instance->flushing = FALSE;
 
   schro_unpack_init_with_data (&unpack, buffer->data, buffer->length, 1);
   parse_code = schro_decoder_decode_parse_header(&unpack);
@@ -748,15 +771,14 @@ schro_decoder_push_old (SchroDecoder *decoder, 
SchroBuffer *buffer)
 
   if (parse_code == SCHRO_PARSE_CODE_SEQUENCE_HEADER) {
     SCHRO_INFO ("decoding sequence header");
-    if (!decoder->sequence_header_buffer) {
-      schro_decoder_parse_sequence_header(decoder, &unpack);
-      decoder->sequence_header_buffer = schro_buffer_dup (buffer);
-      decoder->first_seqhdr = TRUE;
+    if (!instance->sequence_header_buffer) {
+      schro_decoder_parse_sequence_header(instance, &unpack);
+      instance->sequence_header_buffer = schro_buffer_dup (buffer);
+      instance->first_seqhdr = TRUE;
     } else {
       if (!schro_decoder_compare_sequence_header_buffer (buffer,
-            decoder->sequence_header_buffer)) {
-      } else {
-        schro_decoder_error (decoder, "sequence header changed");
+            instance->sequence_header_buffer)) {
+        schro_decoder_error (instance->decoder, "sequence header changed");
       }
     }
 
@@ -772,9 +794,9 @@ schro_decoder_push_old (SchroDecoder *decoder, SchroBuffer 
*buffer)
     if (code == SCHRO_AUX_DATA_MD5_CHECKSUM) {
       int i;
       for(i=0;i<16;i++){
-        decoder->md5_checksum[i] = schro_unpack_decode_bits (&unpack, 8);
+        instance->md5_checksum[i] = schro_unpack_decode_bits (&unpack, 8);
       }
-      decoder->has_md5 = TRUE;
+      instance->has_md5 = TRUE;
     }
 
     schro_buffer_unref (buffer);
@@ -789,20 +811,20 @@ schro_decoder_push_old (SchroDecoder *decoder, 
SchroBuffer *buffer)
   if (SCHRO_PARSE_CODE_IS_END_OF_SEQUENCE (parse_code)) {
     SCHRO_DEBUG ("decoding end sequence");
     schro_buffer_unref (buffer);
-    decoder->end_of_stream = TRUE;
-    decoder->flushing = TRUE;
+    instance->end_of_stream = TRUE;
+    instance->flushing = TRUE;
     return;
   }
 
   if (SCHRO_PARSE_CODE_IS_PICTURE(parse_code)) {
 
-    if (!decoder->sequence_header_buffer) {
+    if (!instance->sequence_header_buffer) {
       SCHRO_INFO ("no sequence header -- dropping picture");
       schro_buffer_unref (buffer);
       return;
     }
 
-    schro_decoder_iterate_picture (decoder, buffer, &unpack, parse_code);
+    schro_decoder_iterate_picture (instance, buffer, &unpack, parse_code);
     return;
   }
 
@@ -826,19 +848,20 @@ schro_decoder_push (SchroDecoder *decoder, SchroBuffer 
*buffer)
     /* has the syncroniser run out of buffer? */
     if (!buffer)
       break;
-    schro_decoder_push_old (decoder, buffer);
+    schro_decoder_push_old (decoder->instance, buffer);
   }
   /* peek at the next state */
   return schro_decoder_get_status_locked (decoder);
 }
 
 void
-schro_decoder_iterate_picture (SchroDecoder *decoder, SchroBuffer *buffer, 
SchroUnpack *unpack, int parse_code)
+schro_decoder_iterate_picture (SchroDecoderInstance *instance, SchroBuffer 
*buffer, SchroUnpack *unpack, int parse_code)
 {
+  SchroDecoder *decoder = instance->decoder;
   SchroPicture *picture;
   SchroParams *params;
 
-  picture = schro_picture_new (decoder);
+  picture = schro_picture_new (instance);
   params = &picture->params;
 
   picture->input_buffer = buffer;
@@ -848,10 +871,10 @@ schro_decoder_iterate_picture (SchroDecoder *decoder, 
SchroBuffer *buffer, Schro
   params->is_noarith = !SCHRO_PARSE_CODE_USING_AC(parse_code);
   picture->is_ref = SCHRO_PARSE_CODE_IS_REFERENCE(parse_code);
 
-  if (decoder->has_md5) {
+  if (instance->has_md5) {
     picture->has_md5 = TRUE;
-    memcpy (picture->md5_checksum, decoder->md5_checksum, 16);
-    decoder->has_md5 = FALSE;
+    memcpy (picture->md5_checksum, instance->md5_checksum, 16);
+    instance->has_md5 = FALSE;
   }
 
   schro_decoder_parse_picture_header(picture, unpack);
@@ -859,21 +882,23 @@ 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 (!instance->have_frame_number) {
     if (params->num_refs > 0) {
       SCHRO_ERROR("expected I frame after sequence header");
     }
-    decoder->next_frame_number = picture->picture_number;
-    decoder->have_frame_number = TRUE;
-    SCHRO_INFO("next frame number after seek %d", decoder->next_frame_number);
+    instance->next_frame_number = picture->picture_number;
+    instance->have_frame_number = TRUE;
+    SCHRO_INFO("next frame number after seek %d", instance->next_frame_number);
   }
 #endif
 
   if (picture->is_ref) {
-    schro_async_lock (decoder->async);
-    schro_decoder_reference_retire (decoder, picture->retired_picture_number);
-    schro_decoder_reference_add (decoder, picture);
-    schro_async_unlock (decoder->async);
+    /* xxx: why is this locked? -- no decoding should actually consult the
+     * reference buffer surely? */
+    schro_async_lock (instance->decoder->async);
+    schro_decoder_reference_retire (instance, picture->retired_picture_number);
+    schro_decoder_reference_add (instance, picture);
+    schro_async_unlock (instance->decoder->async);
   }
   schro_decoder_parse_picture (picture, unpack);
 
@@ -882,7 +907,7 @@ schro_decoder_iterate_picture (SchroDecoder *decoder, 
SchroBuffer *buffer, Schro
   }
 
 #if 0 // XXX
-  if (picture->picture_number < decoder->next_frame_number) {
+  if (picture->picture_number < instance->next_frame_number) {
     SCHRO_DEBUG("picture out of order, skipping");
     schro_picture_unref (picture);
     return SCHRO_DECODER_OK;
@@ -892,7 +917,7 @@ schro_decoder_iterate_picture (SchroDecoder *decoder, 
SchroBuffer *buffer, Schro
   from the previous gop (opengop)
 #endif
 
-  if (!decoder->video_format.interlaced_coding &&
+  if (!instance->video_format.interlaced_coding &&
       !picture->is_ref && decoder->skip_value > decoder->skip_ratio) {
     decoder->skip_value = (1-SCHRO_SKIP_TIME_CONSTANT) * decoder->skip_value;
     SCHRO_INFO("skipping frame %d", picture->picture_number);
@@ -914,7 +939,7 @@ schro_decoder_iterate_picture (SchroDecoder *decoder, 
SchroBuffer *buffer, Schro
       frame_format = schro_params_get_frame_format (8,
           params->video_format->chroma_format);
       ref = schro_frame_new_and_alloc (decoder->cpu_domain, frame_format,
-          decoder->video_format.width, decoder->video_format.height);
+          instance->video_format.width, instance->video_format.height);
       /* FIXME the allocated picture contains junk */
       picture->upsampled_frame = schro_upsampled_frame_new (ref);
     }
@@ -928,9 +953,9 @@ schro_decoder_iterate_picture (SchroDecoder *decoder, 
SchroBuffer *buffer, Schro
   schro_async_lock (decoder->async);
   SCHRO_DEBUG("adding %d to queue", picture->picture_number);
   if (!decoder->coded_order) {
-    schro_picturequeue_rob_insert (decoder->reorder_buffer, picture);
+    schro_picturequeue_rob_insert (instance->reorder_buffer, picture);
   } else {
-    schro_queue_add (decoder->reorder_buffer, picture);
+    schro_queue_add (instance->reorder_buffer, picture);
   }
   schro_async_signal_scheduler (decoder->async);
   schro_async_unlock (decoder->async);
@@ -946,26 +971,26 @@ schro_decoder_parse_picture (SchroPicture *picture, 
SchroUnpack *unpack)
   if (params->num_refs > 0) {
     SCHRO_DEBUG("inter");
 
-    schro_async_lock (picture->decoder->async);
-    picture->ref0 = schro_decoder_reference_get (picture->decoder, 
picture->reference1);
+    schro_async_lock (picture->decoder_instance->decoder->async);
+    picture->ref0 = schro_decoder_reference_get (picture->decoder_instance, 
picture->reference1);
     if (picture->ref0 == NULL) {
       picture->error = TRUE;
-      schro_async_unlock (picture->decoder->async);
+      schro_async_unlock (picture->decoder_instance->decoder->async);
       return;
     }
     schro_picture_ref (picture->ref0);
 
     picture->ref1 = NULL;
     if (params->num_refs > 1) {
-      picture->ref1 = schro_decoder_reference_get (picture->decoder, 
picture->reference2);
+      picture->ref1 = schro_decoder_reference_get (picture->decoder_instance, 
picture->reference2);
       if (picture->ref1 == NULL) {
         picture->error = TRUE;
-        schro_async_unlock (picture->decoder->async);
+        schro_async_unlock (picture->decoder_instance->decoder->async);
         return;
       }
       schro_picture_ref (picture->ref1);
     }
-    schro_async_unlock (picture->decoder->async);
+    schro_async_unlock (picture->decoder_instance->decoder->async);
 
     schro_unpack_byte_sync (unpack);
     schro_decoder_parse_picture_prediction_parameters (picture, unpack);
@@ -996,7 +1021,7 @@ schro_decoder_parse_picture (SchroPicture *picture, 
SchroUnpack *unpack)
     } else {
       schro_decoder_parse_transform_data (picture, unpack);
 
-      if (picture->decoder->use_opengl) {
+      if (picture->decoder_instance->decoder->use_opengl) {
 #ifdef HAVE_OPENGL
         schro_decoder_init_subband_frame_data (picture);
 #else
@@ -1057,8 +1082,8 @@ schro_decoder_async_schedule (SchroDecoder *decoder,
     render_ok = TRUE;
   }
 
-  for(i=0;i<decoder->reorder_buffer->n;i++){
-    SchroPicture *picture = decoder->reorder_buffer->elements[i];
+  for(i=0;i<decoder->instance->reorder_buffer->n;i++){
+    SchroPicture *picture = decoder->instance->reorder_buffer->elements[i];
     void *func = NULL;
     int stage = 0;
 
@@ -1132,7 +1157,8 @@ schro_decoder_async_schedule (SchroDecoder *decoder,
         picture->stages[SCHRO_DECODER_STAGE_MOTION_RENDER].is_done && 
render_ok) {
       if (!picture->output_picture) {
         /* NB, this may fail */
-        picture->output_picture = schro_queue_pull (decoder->output_queue);
+        /* xxx: consider behaviour when stream changes */
+        picture->output_picture = schro_queue_pull 
(decoder->instance->output_queue);
       }
       if (picture->output_picture) {
         func = schro_decoder_x_combine;
@@ -1174,7 +1200,7 @@ schro_decoder_x_render_motion (SchroAsyncStage *stage)
 {
   SchroPicture *picture = (SchroPicture *)stage->priv;
   SchroParams *params = &picture->params;
-  SchroDecoder *decoder = picture->decoder;
+  SchroDecoder *decoder = picture->decoder_instance->decoder;
 
   if (params->num_refs > 0) {
     SCHRO_DEBUG("motion render with %p and %p", picture->ref0, picture->ref1);
@@ -1253,9 +1279,11 @@ void
 schro_decoder_x_wavelet_transform (SchroAsyncStage *stage)
 {
   SchroPicture *picture = (SchroPicture *)stage->priv;
+  SchroDecoder *decoder = picture->decoder_instance->decoder;
+
   if (!picture->zero_residual) {
-    if (picture->decoder->use_cuda) {
-      picture->frame = schro_frame_clone (picture->decoder->cuda_domain,
+    if (decoder->use_cuda) {
+      picture->frame = schro_frame_clone (decoder->cuda_domain,
           picture->transform_frame);
 #ifdef HAVE_CUDA
       schro_frame_inverse_iwt_transform_cuda (picture->frame,
@@ -1263,11 +1291,11 @@ schro_decoder_x_wavelet_transform (SchroAsyncStage 
*stage)
 #else
       SCHRO_ASSERT(0);
 #endif
-    } else if (picture->decoder->use_opengl) {
+    } else if (decoder->use_opengl) {
 #ifdef HAVE_OPENGL
       picture->frame
-          = schro_opengl_frame_clone_and_push (picture->decoder->opengl,
-          picture->decoder->opengl_domain, picture->transform_frame);
+          = schro_opengl_frame_clone_and_push (decoder->opengl,
+          decoder->opengl_domain, picture->transform_frame);
 
       schro_opengl_frame_inverse_iwt_transform (picture->frame,
           &picture->params);
@@ -1285,7 +1313,7 @@ schro_decoder_x_combine (SchroAsyncStage *stage)
 {
   SchroPicture *picture = (SchroPicture *)stage->priv;
   SchroParams *params = &picture->params;
-  SchroDecoder *decoder = picture->decoder;
+  SchroDecoder *decoder = picture->decoder_instance->decoder;
   SchroFrame *planar_output_frame;
   SchroFrame *combined_frame;
   SchroFrame *output_frame;
@@ -1294,13 +1322,13 @@ schro_decoder_x_combine (SchroAsyncStage *stage)
     combined_frame = picture->mc_tmp_frame;
   } else {
     if (params->num_refs > 0) {
-      if (picture->decoder->use_cuda) {
+      if (decoder->use_cuda) {
 #ifdef HAVE_CUDA
         schro_gpuframe_add (picture->frame, picture->mc_tmp_frame);
 #else
         SCHRO_ASSERT(0);
 #endif
-      } else if (picture->decoder->use_opengl) {
+      } else if (decoder->use_opengl) {
 #ifdef HAVE_OPENGL
         schro_opengl_frame_add (picture->frame, picture->mc_tmp_frame);
 #else
@@ -1325,9 +1353,9 @@ schro_decoder_x_combine (SchroAsyncStage *stage)
 
   if (SCHRO_FRAME_IS_PACKED(picture->output_picture->format)) {
     planar_output_frame = schro_frame_new_and_alloc (decoder->cpu_domain,
-        schro_params_get_frame_format (8, decoder->video_format.chroma_format),
-        decoder->video_format.width, decoder->video_format.height);
-    if (picture->decoder->use_cuda) {
+        schro_params_get_frame_format (8, 
picture->decoder_instance->video_format.chroma_format),
+        picture->decoder_instance->video_format.width, 
picture->decoder_instance->video_format.height);
+    if (decoder->use_cuda) {
 #ifdef HAVE_CUDA
       SchroFrame *cuda_output_frame;
       cuda_output_frame = schro_frame_clone (decoder->cuda_domain,
@@ -1339,7 +1367,7 @@ schro_decoder_x_combine (SchroAsyncStage *stage)
 #else
       SCHRO_ASSERT(0);
 #endif
-    } else if (picture->decoder->use_opengl) {
+    } else if (decoder->use_opengl) {
 #ifdef HAVE_OPENGL
       SchroFrame *tmp_opengl_output_frame;
 
@@ -1361,7 +1389,7 @@ schro_decoder_x_combine (SchroAsyncStage *stage)
     }
   } else {
     planar_output_frame = schro_frame_ref(picture->output_picture);
-    if (picture->decoder->use_cuda) {
+    if (decoder->use_cuda) {
 #ifdef HAVE_CUDA
       SchroFrame *cuda_output_frame;
       cuda_output_frame = schro_frame_clone (decoder->cuda_domain,
@@ -1372,7 +1400,7 @@ schro_decoder_x_combine (SchroAsyncStage *stage)
 #else
       SCHRO_ASSERT(0);
 #endif
-    } else if (picture->decoder->use_opengl) {
+    } else if (decoder->use_opengl) {
 #ifdef HAVE_OPENGL
       SchroFrame *tmp_opengl_output_frame;
 
@@ -1398,19 +1426,19 @@ schro_decoder_x_combine (SchroAsyncStage *stage)
     frame_format = schro_params_get_frame_format (8,
         params->video_format->chroma_format);
 
-    if (picture->decoder->use_cuda) {
+    if (decoder->use_cuda) {
 #ifdef HAVE_CUDA
       ref = schro_frame_new_and_alloc (decoder->cuda_domain, frame_format,
-          decoder->video_format.width,
-          schro_video_format_get_picture_height(&decoder->video_format));
+          picture->decoder_instance->video_format.width,
+          
schro_video_format_get_picture_height(&picture->decoder_instance->video_format));
       schro_gpuframe_convert (ref, combined_frame);
 #else
       SCHRO_ASSERT(0);
 #endif
-    } else if (picture->decoder->use_opengl) {
+    } else if (decoder->use_opengl) {
 #ifdef HAVE_OPENGL
       ref = schro_opengl_frame_new (decoder->opengl, decoder->opengl_domain,
-          frame_format, decoder->video_format.width,
+          frame_format, picture->decoder_instance->video_format.width,
           schro_video_format_get_picture_height(&decoder->video_format));
       schro_opengl_frame_convert (ref, combined_frame);
 #else
@@ -1418,8 +1446,8 @@ schro_decoder_x_combine (SchroAsyncStage *stage)
 #endif
     } else {
       ref = schro_frame_new_and_alloc_extended (decoder->cpu_domain,
-          frame_format, decoder->video_format.width,
-          schro_video_format_get_picture_height(&decoder->video_format),
+          frame_format, picture->decoder_instance->video_format.width,
+          
schro_video_format_get_picture_height(&picture->decoder_instance->video_format),
           32);
       schro_frame_convert (ref, combined_frame);
       schro_frame_mc_edgeextend (ref);
@@ -1462,14 +1490,15 @@ void
 schro_decoder_x_upsample (SchroAsyncStage *stage)
 {
   SchroPicture *picture = (SchroPicture *)stage->priv;
+  SchroDecoder *decoder = picture->decoder_instance->decoder;
 
-  if (picture->decoder->use_cuda) {
+  if (decoder->use_cuda) {
 #ifdef HAVE_CUDA
     schro_upsampled_gpuframe_upsample (picture->upsampled_frame);
 #else
     SCHRO_ASSERT (0);
 #endif
-  } else if (picture->decoder->use_opengl) {
+  } else if (decoder->use_opengl) {
 #ifdef HAVE_OPENGL
     schro_opengl_upsampled_frame_upsample (picture->upsampled_frame);
 #else
@@ -1530,27 +1559,27 @@ schro_decoder_compare_sequence_header_buffer 
(SchroBuffer *a, SchroBuffer *b)
 }
 
 void
-schro_decoder_parse_sequence_header (SchroDecoder *decoder, SchroUnpack 
*unpack)
+schro_decoder_parse_sequence_header (SchroDecoderInstance *instance, 
SchroUnpack *unpack)
 {
   int bit;
   int index;
-  SchroVideoFormat *format = &decoder->video_format;
+  SchroVideoFormat *format = &instance->video_format;
 
   SCHRO_DEBUG("decoding sequence header");
 
   /* parse parameters */
-  decoder->major_version = schro_unpack_decode_uint (unpack);
-  SCHRO_DEBUG("major_version = %d", decoder->major_version);
-  decoder->minor_version = schro_unpack_decode_uint (unpack);
-  SCHRO_DEBUG("minor_version = %d", decoder->minor_version);
-  decoder->profile = schro_unpack_decode_uint (unpack);
-  SCHRO_DEBUG("profile = %d", decoder->profile);
-  decoder->level = schro_unpack_decode_uint (unpack);
-  SCHRO_DEBUG("level = %d", decoder->level);
-
-  if (!schro_decoder_check_version (decoder->major_version, 
decoder->minor_version)) {
+  instance->major_version = schro_unpack_decode_uint (unpack);
+  SCHRO_DEBUG("major_version = %d", instance->major_version);
+  instance->minor_version = schro_unpack_decode_uint (unpack);
+  SCHRO_DEBUG("minor_version = %d", instance->minor_version);
+  instance->profile = schro_unpack_decode_uint (unpack);
+  SCHRO_DEBUG("profile = %d", instance->profile);
+  instance->level = schro_unpack_decode_uint (unpack);
+  SCHRO_DEBUG("level = %d", instance->level);
+
+  if (!schro_decoder_check_version (instance->major_version, 
instance->minor_version)) {
     SCHRO_WARNING("Stream version number %d:%d not handled, expecting 
0:20071203, 1:0, 2:0, 2:1, or 2:2",
-        decoder->major_version, decoder->minor_version);
+        instance->major_version, instance->minor_version);
   }
 
   /* base video format */
@@ -1646,7 +1675,7 @@ schro_decoder_parse_sequence_header (SchroDecoder 
*decoder, SchroUnpack *unpack)
       if (index <= SCHRO_SIGNAL_RANGE_12BIT_VIDEO) {
         schro_video_format_set_std_signal_range (format, index);
       } else {
-        schro_decoder_error (decoder, "signal range index out of range");
+        schro_decoder_error (instance->decoder, "signal range index out of 
range");
       }
     }
   }
@@ -1664,7 +1693,7 @@ schro_decoder_parse_sequence_header (SchroDecoder 
*decoder, SchroUnpack *unpack)
     if (index <= SCHRO_COLOUR_SPEC_CINEMA) {
       schro_video_format_set_std_colour_spec (format, index);
     } else {
-      schro_decoder_error (decoder, "colour spec index out of range");
+      schro_decoder_error (instance->decoder, "colour spec index out of 
range");
     }
     if (index == 0) {
       /* colour primaries */
@@ -2781,31 +2810,31 @@ schro_decoder_decode_subband (SchroPicture *picture,
 /* reference pool */
 
 static void
-schro_decoder_reference_add (SchroDecoder *decoder, SchroPicture *picture)
+schro_decoder_reference_add (SchroDecoderInstance *instance, SchroPicture 
*picture)
 {
   SCHRO_DEBUG("adding %d", picture->picture_number);
 
-  if (schro_queue_is_full(decoder->reference_queue)) {
+  if (schro_queue_is_full(instance->reference_queue)) {
     SCHRO_ERROR("auto-retiring reference picture");
-    schro_queue_pop (decoder->reference_queue);
+    schro_queue_pop (instance->reference_queue);
   }
-  schro_queue_add (decoder->reference_queue, schro_picture_ref(picture));
+  schro_queue_add (instance->reference_queue, schro_picture_ref(picture));
 }
 
 static SchroPicture *
-schro_decoder_reference_get (SchroDecoder *decoder,
+schro_decoder_reference_get (SchroDecoderInstance *instance,
     SchroPictureNumber picture_number)
 {
   SCHRO_DEBUG("getting %d", picture_number);
-  return schro_picturequeue_find (decoder->reference_queue, picture_number);
+  return schro_picturequeue_find (instance->reference_queue, picture_number);
 }
 
 static void
-schro_decoder_reference_retire (SchroDecoder *decoder,
+schro_decoder_reference_retire (SchroDecoderInstance *instance,
     SchroPictureNumber picture_number)
 {
   SCHRO_DEBUG("retiring %d", picture_number);
-  schro_picturequeue_delete (decoder->reference_queue, picture_number);
+  schro_picturequeue_delete (instance->reference_queue, picture_number);
 }
 
 static void
diff --git a/schroedinger/schrodecoder.h b/schroedinger/schrodecoder.h
index 1030e0b..2c98901 100644
--- a/schroedinger/schrodecoder.h
+++ b/schroedinger/schrodecoder.h
@@ -21,6 +21,7 @@
 SCHRO_BEGIN_DECLS
 
 typedef struct _SchroDecoder SchroDecoder;
+typedef struct _SchroDecoderInstance SchroDecoderInstance;
 typedef struct _SchroPicture SchroPicture;
 typedef SchroQueue SchroPictureQueue;
 
@@ -34,23 +35,47 @@ typedef struct _SchroOpenGL SchroOpenGL;
 struct _SchroDecoder {
   /*< private >*/
 
-  /* the list of reference pictures */
-  SchroQueue *reference_queue;
-
-  /* a list of frames provided by the app that we'll decode into */
-  SchroQueue *output_queue;
-
   SchroMemoryDomain *cpu_domain;
   SchroMemoryDomain *cuda_domain;
   SchroMemoryDomain *opengl_domain;
+
   SchroAsync *async;
+
   int use_cuda;
   SchroOpenGL *opengl;
   int use_opengl;
 
+  double skip_value;
+  double skip_ratio;
+
+  /* output pictures in coded order */
+  int coded_order;
+
+  int error;
+  char *error_message;
+
   SchroBufferList *input_buflist;
   SchroParseSyncState *sps;
 
+  SchroDecoderInstance *instance;
+};
+
+struct _SchroDecoderInstance {
+  /*< private >*/
+
+  /* the decoder this sequence instance belongs to */
+  SchroDecoder *decoder;
+
+  /* the next sequence instance to supercede this */
+  SchroDecoderInstance *next;
+
+  /* the list of reference pictures */
+  SchroQueue *reference_queue;
+
+  /* a list of frames provided by the app that we'll decode into */
+  /* xxx: maybe this belongs in Decoder and not per instance */
+  SchroQueue *output_queue;
+
   SchroPictureNumber next_frame_number;
 
   int major_version;
@@ -66,19 +91,10 @@ struct _SchroDecoder {
   int first_seqhdr;
   int end_of_stream;
   int flushing;
-  int coded_order;
-
-  SchroPictureNumber earliest_frame;
 
   SchroBuffer *sequence_header_buffer;
   int have_frame_number;
 
-  double skip_value;
-  double skip_ratio;
-
-  int error;
-  char *error_message;
-
   int has_md5;
   uint8_t md5_checksum[32];
 };
@@ -86,7 +102,7 @@ struct _SchroDecoder {
 struct _SchroPicture {
   int refcount;
 
-  SchroDecoder *decoder;
+  SchroDecoderInstance *decoder_instance;
 
   int busy;
   int skip;
@@ -166,14 +182,14 @@ int schro_decoder_need_output_frame (SchroDecoder 
*decoder);
 #ifdef SCHRO_ENABLE_UNSTABLE_API
 
 int schro_decoder_decode_parse_header (SchroUnpack *unpack);
-void schro_decoder_parse_sequence_header (SchroDecoder *decoder, SchroUnpack 
*unpack);
+void schro_decoder_parse_sequence_header (SchroDecoderInstance *instance, 
SchroUnpack *unpack);
 int schro_decoder_compare_sequence_header_buffer (SchroBuffer *a, SchroBuffer 
*b);
 
 void schro_decoder_subband_dc_predict (SchroFrameData *fd);
 
 /* SchroPicture */
 
-SchroPicture * schro_picture_new (SchroDecoder *decoder);
+SchroPicture * schro_picture_new (SchroDecoderInstance *instance);
 SchroPicture * schro_picture_ref (SchroPicture *picture);
 void schro_picture_unref (SchroPicture *picture);
 
@@ -181,7 +197,7 @@ void schro_picture_unref (SchroPicture *picture);
 SchroPicture *schro_picturequeue_find (SchroPictureQueue *queue, 
SchroPictureNumber picture_number);
 void schro_picturequeue_delete (SchroPictureQueue *queue, SchroPictureNumber 
picture_number);
 
-void schro_decoder_iterate_picture (SchroDecoder *decoder, SchroBuffer 
*buffer, SchroUnpack *unpack, int parse_code);
+void schro_decoder_iterate_picture (SchroDecoderInstance *instance, 
SchroBuffer *buffer, SchroUnpack *unpack, int parse_code);
 void schro_decoder_parse_picture (SchroPicture *picture, SchroUnpack *unpack);
 void schro_decoder_parse_picture_header (SchroPicture *picture, SchroUnpack 
*unpack);
 void schro_decoder_parse_picture_prediction_parameters (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