diff options
Diffstat (limited to 'src/video_dec/libvdpau/nal.c')
-rw-r--r-- | src/video_dec/libvdpau/nal.c | 190 |
1 files changed, 162 insertions, 28 deletions
diff --git a/src/video_dec/libvdpau/nal.c b/src/video_dec/libvdpau/nal.c index b81c8fe1d..07c672e33 100644 --- a/src/video_dec/libvdpau/nal.c +++ b/src/video_dec/libvdpau/nal.c @@ -27,49 +27,183 @@ #include "nal.h" #include <xine/xine_internal.h> -struct nal_unit* init_nal_unit() +struct nal_buffer* create_nal_buffer(uint8_t max_size) { - struct nal_unit *nal = calloc(1, sizeof(struct nal_unit)); + struct nal_buffer *nal_buffer = calloc(1, sizeof(struct nal_buffer)); + nal_buffer->max_size = max_size; + + return nal_buffer; +} + +/** + * destroys a nal buffer. all referenced nals are released + */ +void free_nal_buffer(struct nal_buffer *nal_buffer) +{ + struct nal_unit *nal = nal_buffer->first; + + do { + struct nal_unit *delete = nal; + nal = nal->next; + release_nal_unit(delete); + } while(nal != NULL); + + free(nal_buffer); +} + +/** + * appends a nal unit to the end of the buffer + */ +void nal_buffer_append(struct nal_buffer *nal_buffer, struct nal_unit *nal) +{ + if(nal_buffer->used == nal_buffer->max_size) { + nal_buffer_remove(nal_buffer, nal_buffer->first); + } + + if (nal_buffer->first == NULL) { + nal_buffer->first = nal_buffer->last = nal; + nal->prev = nal->next = NULL; + + lock_nal_unit(nal); + nal_buffer->used++; + } else if (nal_buffer->last != NULL) { + nal_buffer->last->next = nal; + nal->prev = nal_buffer->last; + nal_buffer->last = nal; - /*nal->sps = calloc(1, sizeof(struct seq_parameter_set_rbsp)); - nal->pps = calloc(1, sizeof(struct pic_parameter_set_rbsp)); - nal->slc = calloc(1, sizeof(struct slice_header));*/ + lock_nal_unit(nal); + nal_buffer->used++; + } else { + printf("ERR: nal_buffer is in a broken state\n"); + } +} + +void nal_buffer_remove(struct nal_buffer *nal_buffer, struct nal_unit *nal) +{ + if (nal == nal_buffer->first && nal == nal_buffer->last) { + nal_buffer->first = nal_buffer->last = NULL; + } else { + if (nal == nal_buffer->first) { + nal_buffer->first = nal->next; + nal_buffer->first->prev = NULL; + } else { + nal->prev->next = nal->next; + } + + if (nal == nal_buffer->last) { + nal_buffer->last = nal->prev; + nal_buffer->last->next = NULL; + } else { + nal->next->prev = nal->prev; + } + } + + nal->next = nal->prev = NULL; + release_nal_unit(nal); + + nal_buffer->used--; +} + +void nal_buffer_flush(struct nal_buffer *nal_buffer) +{ + while(nal_buffer->used > 0) { + nal_buffer_remove(nal_buffer, nal_buffer->first); + } +} + +/** + * returns the last element in the buffer + */ +struct nal_unit *nal_buffer_get_last(struct nal_buffer *nal_buffer) +{ + return nal_buffer->last; +} + +/** + * get a nal unit from a nal_buffer from it's + * seq parameter_set_id + */ +struct nal_unit* nal_buffer_get_by_sps_id(struct nal_buffer *nal_buffer, + uint32_t seq_parameter_set_id) +{ + struct nal_unit *nal = nal_buffer->last; + + if (nal != NULL) { + do { + if(nal->nal_unit_type == NAL_SPS) { + if(nal->sps.seq_parameter_set_id == seq_parameter_set_id) { + return nal; + } + } + + nal = nal->prev; + } while(nal != NULL); + } + + return NULL; +} + +/** + * get a nal unit from a nal_buffer from it's + * pic parameter_set_id + */ +struct nal_unit* nal_buffer_get_by_pps_id(struct nal_buffer *nal_buffer, + uint32_t pic_parameter_set_id) +{ + struct nal_unit *nal = nal_buffer->last; + + if (nal != NULL) { + do { + if(nal->nal_unit_type == NAL_PPS) { + if(nal->pps.pic_parameter_set_id == pic_parameter_set_id) { + return nal; + } + } + + nal = nal->prev; + } while(nal != NULL); + } + + return NULL; +} + +/** + * create a new nal unit, with a lock_counter of 1 + */ +struct nal_unit* create_nal_unit() +{ + struct nal_unit *nal = calloc(1, sizeof(struct nal_unit)); + nal->lock_counter = 1; return nal; } -void free_nal_unit(struct nal_unit *nal) +void lock_nal_unit(struct nal_unit *nal) +{ + nal->lock_counter++; +} + +void release_nal_unit(struct nal_unit *nal) { if(!nal) return; - free(nal->sps); - free(nal->pps); - free(nal->slc); - free(nal); + nal->lock_counter--; + + if(nal->lock_counter <= 0) { + free(nal); + } } +/** + * creates a copy of a nal unit with a single lock + */ void copy_nal_unit(struct nal_unit *dest, struct nal_unit *src) { /* size without pps, sps and slc units: */ - int size = sizeof(struct nal_unit) - sizeof(struct seq_parameter_set_rbsp*) - - sizeof(struct pic_parameter_set_rbsp*) - sizeof(struct slice_header*); + int size = sizeof(struct nal_unit); xine_fast_memcpy(dest, src, size); - - if(!dest->sps) - dest->sps = calloc(1, sizeof(struct seq_parameter_set_rbsp)); - - if(!dest->pps) - dest->pps = calloc(1, sizeof(struct pic_parameter_set_rbsp)); - - if(!dest->slc) - dest->slc = calloc(1, sizeof(struct slice_header)); - - if(src->sps) - xine_fast_memcpy(dest->sps, src->sps, sizeof(struct seq_parameter_set_rbsp)); - if(src->pps) - xine_fast_memcpy(dest->pps, src->pps, sizeof(struct pic_parameter_set_rbsp)); - if(src->slc) - xine_fast_memcpy(dest->slc, src->slc, sizeof(struct slice_header)); + dest->lock_counter = 1; + dest->prev = dest->next = NULL; } |