From: David Flynn <dav...@rd.bbc.co.uk> Traditionally, clients were required to wrap the decoder with a TLB, that stored presentation time vs input picture number; when pulling a picture, the presentation time would be extracted from the TLB.
Clients may be simplified by allowing schroedinger to do the tagging based on simple rules: - a buffer may be supplied with a tag and free function - the tag is associated with the first byte of the buffer data - when using the autoparse api, the tag becomes associated with the next picture data unit to commence at or after the start of the buffer. - in cases where the above rule would associate multiple tags with one picture, the oldest shall take precedence. - tags are made avaliable as a member of the SchroFrame structure. - the contents of the tag are transparent to the decoder. Signed-off-by: David Flynn <dav...@rd.bbc.co.uk> --- schroedinger/schrobuffer.c | 2 + schroedinger/schrobuffer.h | 2 + schroedinger/schrobufferlist.c | 63 ++++++++++++++++++++++++++++++++++----- schroedinger/schrodecoder.c | 24 +++++++++++++++ schroedinger/schrodecoder.h | 9 ++++++ schroedinger/schroframe.h | 4 ++ 6 files changed, 96 insertions(+), 8 deletions(-) diff --git a/schroedinger/schrobuffer.c b/schroedinger/schrobuffer.c index 3e1636a..a38916d 100644 --- a/schroedinger/schrobuffer.c +++ b/schroedinger/schrobuffer.c @@ -82,6 +82,8 @@ schro_buffer_unref (SchroBuffer * buffer) SCHRO_DEBUG("free %p", buffer); if (buffer->free) buffer->free (buffer, buffer->priv); + if (buffer->tag_free) + buffer->tag_free (buffer->tag); schro_free (buffer); } } diff --git a/schroedinger/schrobuffer.h b/schroedinger/schrobuffer.h index f3df89c..c822049 100644 --- a/schroedinger/schrobuffer.h +++ b/schroedinger/schrobuffer.h @@ -20,6 +20,8 @@ struct _SchroBuffer void (*free) (SchroBuffer *, void *); void *priv; + void (*tag_free) (void *); /* NB, must be able to handle tag_free(NULL) */ + void *tag; }; SchroBuffer *schro_buffer_new (void); diff --git a/schroedinger/schrobufferlist.c b/schroedinger/schrobufferlist.c index ae7e379..05a588b 100644 --- a/schroedinger/schrobufferlist.c +++ b/schroedinger/schrobufferlist.c @@ -232,8 +232,10 @@ schro_buflist_flush (SchroBufferList *buflist, unsigned amount) SchroBuffer * schro_buflist_extract (SchroBufferList *buflist, unsigned start, unsigned len) { - SchroBuffer *buf; - unsigned start_orig = start; + SchroBuffer *buf, *dst; + void *tag = NULL; + void (*tag_free) (void *) = NULL; + unsigned pos = start; int bufidx; uint8_t tmp; @@ -249,19 +251,64 @@ schro_buflist_extract (SchroBufferList *buflist, unsigned start, unsigned len) } /* guaranteed that the range is wholly contained within buflist */ - bufidx = schro_buflist_internal_seek(buflist, &start); + bufidx = schro_buflist_internal_seek(buflist, &pos); SCHRO_ASSERT(bufidx < buflist->list->n); buf = buflist->list->members[bufidx]; - if (start + len <= buf->length) { + /* Semantics for private void* in buffers in a bufferlist: + * - Shall be associated with the next dataunit to commence after (or at) + * the start of the buffer in the bufferist. + * - May only be extracted once. + * - If multiple void* could apply to the next dataunit, behaviour is undefined + * NB: this implementation will discard all but the first. + * - Ownership of the tag is transfered to the output buffer + */ + tag = buf->tag; + tag_free = buf->tag_free; + buf->tag = NULL; + + if (pos + len <= buf->length) { /* Special case, if the requested range is contained within a single * buffer, then use a subbuffer */ - return schro_buffer_new_subbuffer (buf, start, len); + dst = schro_buffer_new_subbuffer (buf, pos, len); + dst->tag = tag; + dst->tag_free = tag_free; + return dst; } - buf = schro_buffer_new_and_alloc (len); - schro_buflist_peekbytes (buf->data, len, buflist, start_orig); + /* dataunit spans multiple buffers */ + dst = schro_buffer_new_and_alloc (len); + dst->tag = tag; + dst->tag_free = tag_free; + tag = NULL; + schro_buflist_peekbytes (dst->data, len, buflist, start); + + /* sort out rescuing the first tag that was in the extracted + * region and saving it ready for extraction at start+len. */ + len += pos; + for (pos = 0; pos < len;) + { + buf = buflist->list->members[bufidx]; + if (!tag) { + /* find the first non null tag we come across, take it, + * and [2] store it in the last buffer read from */ + tag = buf->tag; + buf->tag = NULL; + } + /* any intermediate tags are discarded */ + if (buf->tag_free) { + buf->tag_free(buf->tag); + buf->tag = NULL; + } + pos += buf->length; + bufidx++; + } + /* [2] store in last buffer of buflist */ + /* xxx, this may need to be moved to the next buffer if + * exact consumption of buf occurs */ + buf->tag = tag; + buf->tag_free = tag_free; - return buf; + return dst; } diff --git a/schroedinger/schrodecoder.c b/schroedinger/schrodecoder.c index 66f8516..3f3fb38 100644 --- a/schroedinger/schrodecoder.c +++ b/schroedinger/schrodecoder.c @@ -653,6 +653,10 @@ schro_decoder_pull (SchroDecoder *decoder) /* XXX would be nice to warn if expected picture not present */ frame = schro_frame_ref (picture->output_picture); + frame->tag = picture->tag; + frame->tag_free = picture->tag_free; + picture->tag = NULL; + schro_picture_unref (picture); return frame; @@ -1021,9 +1025,13 @@ schro_decoder_push (SchroDecoder *decoder, SchroBuffer *buffer) } if (SCHRO_PARSE_CODE_IS_PICTURE(parse_code)) { + SchroDecoder *decoder = instance->decoder; if (!instance->have_sequence_header) { SCHRO_INFO ("no sequence header -- dropping picture"); + if (decoder->free_picture_tag) + decoder->free_picture_tag(decoder->next_picture_tag); + decoder->next_picture_tag = NULL; schro_buffer_unref (buffer); return SCHRO_DECODER_OK; } @@ -1060,6 +1068,17 @@ schro_decoder_autoparse_push (SchroDecoder *decoder, SchroBuffer *buffer) if (!buffer) return SCHRO_DECODER_NEED_BITS; + /* Buffers may have associated (tagged) private data. + * This data is to be associated with the next(/this) picture data unit */ + if (buffer->tag) { + if (decoder->free_picture_tag) { + decoder->free_picture_tag (decoder->next_picture_tag); + } + decoder->next_picture_tag = buffer->tag; + decoder->free_picture_tag = buffer->tag_free; + } + buffer->tag_free = buffer->tag = NULL; + switch (schro_decoder_push (decoder, buffer)) { default: break; @@ -1085,6 +1104,11 @@ schro_decoder_iterate_picture (SchroDecoderInstance *instance, SchroBuffer *buff picture->input_buffer = buffer; + picture->tag = decoder->next_picture_tag; + picture->tag_free = decoder->free_picture_tag; + decoder->free_picture_tag = + decoder->next_picture_tag = NULL; + params->num_refs = SCHRO_PARSE_CODE_NUM_REFS(parse_code); params->is_lowdelay = SCHRO_PARSE_CODE_IS_LOW_DELAY(parse_code); params->is_noarith = !SCHRO_PARSE_CODE_USING_AC(parse_code); diff --git a/schroedinger/schrodecoder.h b/schroedinger/schrodecoder.h index 8281efe..156ebae 100644 --- a/schroedinger/schrodecoder.h +++ b/schroedinger/schrodecoder.h @@ -52,6 +52,11 @@ struct _SchroDecoder { SchroBufferList *input_buflist; SchroParseSyncState *sps; + /* private data that is supplied with the input bitstream and + * is to be associated with the next picture to occur */ + void *next_picture_tag; + void (*free_picture_tag) (void*); + SchroDecoderInstance *instance; }; @@ -141,6 +146,10 @@ struct _SchroPicture { int has_md5; uint8_t md5_checksum[32]; + + /* private data that is associated with this picture */ + void *tag; + void (*tag_free) (void*); }; #endif diff --git a/schroedinger/schroframe.h b/schroedinger/schroframe.h index 4b0bb76..ac8516e 100644 --- a/schroedinger/schroframe.h +++ b/schroedinger/schroframe.h @@ -88,6 +88,10 @@ struct _SchroFrame { void *virt_priv2; int extension; + + /* private data that is associated with this picture */ + void *tag; + void (*tag_free) (void*); }; struct _SchroUpsampledFrame { -- 1.5.6.5 ------------------------------------------------------------------------------ This SF.net email is sponsored by: SourcForge Community SourceForge wants to tell your story. http://p.sf.net/sfu/sf-spreadtheword _______________________________________________ Schrodinger-devel mailing list Schrodinger-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/schrodinger-devel