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
