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
