diff options
Diffstat (limited to 'src/libvdpau/dpb.c')
-rw-r--r-- | src/libvdpau/dpb.c | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c new file mode 100644 index 000000000..460149ea3 --- /dev/null +++ b/src/libvdpau/dpb.c @@ -0,0 +1,222 @@ +/* + * dpb.c + * + * Created on: 07.12.2008 + * Author: julian + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "dpb.h" + +struct decoded_picture* init_decoded_picture(struct nal_unit *src_nal, + VdpVideoSurface surface) +{ + struct decoded_picture *pic = malloc(sizeof(struct decoded_picture)); + pic->nal = init_nal_unit(); + copy_nal_unit(pic->nal, src_nal); + pic->surface = surface; + pic->next = NULL; + + return pic; +} + +void free_decoded_picture(struct decoded_picture *pic) +{ + free_nal_unit(pic->nal); +} + +struct decoded_picture* dpb_get_picture(struct dpb *dpb, uint32_t picnum) +{ + struct decoded_picture *pic = dpb->pictures; + + if (pic != NULL) + do { + if (pic->nal->curr_pic_num == picnum) + return pic; + } while ((pic = pic->next) != NULL); + + return NULL; +} + +struct decoded_picture* dpb_get_picture_by_ltpn(struct dpb *dpb, + uint32_t longterm_picnum) +{ + struct decoded_picture *pic = dpb->pictures; + + if (pic != NULL) + do { + if (pic->nal->long_term_pic_num == longterm_picnum) + return pic; + } while ((pic = pic->next) != NULL); + + return NULL; +} + +struct decoded_picture* dpb_get_picture_by_ltidx(struct dpb *dpb, + uint32_t longterm_idx) +{ + struct decoded_picture *pic = dpb->pictures; + + if (pic != NULL) + do { + if (pic->nal->long_term_frame_idx == longterm_idx) + return pic; + } while ((pic = pic->next) != NULL); + + return NULL; +} + +int dpb_remove_picture(struct dpb *dpb, uint32_t picnum) +{ + struct decoded_picture *pic = dpb->pictures; + struct decoded_picture *last_pic = NULL; + + if (pic != NULL) + do { + if (pic->nal->curr_pic_num == picnum) { + // FIXME: free the picture.... + + if (last_pic != NULL) + last_pic->next = pic->next; + else + dpb->pictures = pic->next; + + free_decoded_picture(pic); + return 0; + } + + last_pic = pic; + } while ((pic = pic->next) != NULL); + + return -1; +} + +int dpb_remove_picture_by_ltpn(struct dpb *dpb, uint32_t longterm_picnum) +{ + struct decoded_picture *pic = dpb->pictures; + struct decoded_picture *last_pic = NULL; + + if (pic != NULL) + do { + if (pic->nal->long_term_pic_num == longterm_picnum) { + // FIXME: free the picture.... + + if (last_pic != NULL) + last_pic->next = pic->next; + else + dpb->pictures = pic->next; + + free_decoded_picture(pic); + return 0; + } + + last_pic = pic; + } while ((pic = pic->next) != NULL); + + return -1; +} + +int dpb_remove_picture_by_ltidx(struct dpb *dpb, uint32_t longterm_idx) +{ + struct decoded_picture *pic = dpb->pictures; + struct decoded_picture *last_pic = NULL; + + if (pic != NULL) + do { + if (pic->nal->long_term_frame_idx == longterm_idx) { + // FIXME: free the picture.... + + if (last_pic != NULL) + last_pic->next = pic->next; + else + dpb->pictures = pic->next; + + free_decoded_picture(pic); + return 0; + } + + last_pic = pic; + } while ((pic = pic->next) != NULL); + + return -1; +} + +int dpb_remove_ltidx_gt(struct dpb *dpb, uint32_t longterm_max) +{ + struct decoded_picture *pic = dpb->pictures; + struct decoded_picture *last_pic = NULL; + + if (pic != NULL) + do { + if (pic->nal->long_term_frame_idx > longterm_max) { + // FIXME: free the picture.... + if (last_pic != NULL) + last_pic->next = pic->next; + else + dpb->pictures = pic->next; + + + free_decoded_picture(pic); + + /* don't increase last_pic to current pic + * in case we delete current pic */ + continue; + } + + last_pic = pic; + } while ((pic = pic->next) != NULL); + + return 0; +} + +int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic) +{ + pic->next = dpb->pictures; + dpb->pictures = pic; + + return 0; +} + +int dpb_flush(struct dpb *dpb) +{ + struct decoded_picture *pic = dpb->pictures; + struct decoded_picture *last_pic = NULL; + + if (pic != NULL) + do { + //FIXME: free the picture + + last_pic = pic; + } while ((pic = pic->next) != NULL); + + dpb->pictures = NULL; + + return 0; +} + +void fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist) +{ + struct decoded_picture *pic = dpb->pictures; + struct decoded_picture *last_pic = NULL; + + int i = 0; + + if (pic != NULL) + do { + if (pic->nal->nal_ref_idc != 0) { + reflist[i].surface = pic->surface; + reflist[i].is_long_term = pic->nal->used_for_long_term_ref; + reflist[i].top_is_reference = pic->nal->slc->field_pic_flag + ? (pic->nal->slc->bottom_field_flag ? 0 : 1) : 1; + reflist[i].bottom_is_reference = pic->nal->slc->field_pic_flag + ? (pic->nal->slc->bottom_field_flag ? 1 : 0) : 1; + reflist[i].field_order_cnt[0] = pic->nal->top_field_order_cnt; + reflist[i].field_order_cnt[1] = pic->nal->bottom_field_order_cnt; + i++; + } + last_pic = pic; + } while ((pic = pic->next) != NULL && i < 16); +} |