/* If any buffer copy / swapping is signalled it should be done here. */ static int swap_frame_buffers (VP8_COMMON *cm) { int err = 0; /* The alternate reference frame or golden frame can be updated * using the new, last, or golden/alt ref frame. If it * is updated using the newly decoded frame it is a refresh. * An update using the last or golden/alt ref frame is a copy. */ if (cm->copy_buffer_to_arf) { int new_fb = 0; if (cm->copy_buffer_to_arf == 1) new_fb = cm->lst_fb_idx; else if (cm->copy_buffer_to_arf == 2) new_fb = cm->gld_fb_idx; else err = -1; ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->alt_fb_idx, new_fb); } if (cm->copy_buffer_to_gf) { int new_fb = 0; if (cm->copy_buffer_to_gf == 1) new_fb = cm->lst_fb_idx; else if (cm->copy_buffer_to_gf == 2) new_fb = cm->alt_fb_idx; else err = -1; ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->gld_fb_idx, new_fb); } if (cm->refresh_golden_frame) ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->gld_fb_idx, cm->new_fb_idx); if (cm->refresh_alt_ref_frame) ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->alt_fb_idx, cm->new_fb_idx); if (cm->refresh_last_frame) { ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->lst_fb_idx, cm->new_fb_idx); cm->frame_to_show = &cm->yv12_fb[cm->lst_fb_idx]; } else cm->frame_to_show = &cm->yv12_fb[cm->new_fb_idx]; cm->fb_idx_ref_cnt[cm->new_fb_idx]--; return err; }
vpx_codec_err_t vp10_set_reference_dec(VP10_COMMON *cm, VP9_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd) { RefBuffer *ref_buf = NULL; RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs; // TODO(jkoleszar): The decoder doesn't have any real knowledge of what the // encoder is using the frame buffers for. This is just a stub to keep the // vpxenc --test-decode functionality working, and will be replaced in a // later commit that adds VP9-specific controls for this functionality. if (ref_frame_flag == VP9_LAST_FLAG) { ref_buf = &cm->frame_refs[0]; } else if (ref_frame_flag == VP9_GOLD_FLAG) { ref_buf = &cm->frame_refs[1]; } else if (ref_frame_flag == VP9_ALT_FLAG) { ref_buf = &cm->frame_refs[2]; } else { vpx_internal_error(&cm->error, VPX_CODEC_ERROR, "Invalid reference frame"); return cm->error.error_code; } if (!equal_dimensions(ref_buf->buf, sd)) { vpx_internal_error(&cm->error, VPX_CODEC_ERROR, "Incorrect buffer dimensions"); } else { int *ref_fb_ptr = &ref_buf->idx; // Find an empty frame buffer. const int free_fb = get_free_fb(cm); if (cm->new_fb_idx == INVALID_IDX) return VPX_CODEC_MEM_ERROR; // Decrease ref_count since it will be increased again in // ref_cnt_fb() below. --frame_bufs[free_fb].ref_count; // Manage the reference counters and copy image. ref_cnt_fb(frame_bufs, ref_fb_ptr, free_fb); ref_buf->buf = &frame_bufs[*ref_fb_ptr].buf; vp8_yv12_copy_frame(sd, ref_buf->buf); } return cm->error.error_code; }
/* If any buffer updating is signaled it should be done here. */ static void swap_frame_buffers(VP9D_COMP *pbi) { int ref_index = 0, mask; VP9_COMMON *const cm = &pbi->common; for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) { if (mask & 1) ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->ref_frame_map[ref_index], cm->new_fb_idx); ++ref_index; } cm->frame_to_show = get_frame_new_buffer(cm); cm->fb_idx_ref_cnt[cm->new_fb_idx]--; // Invalidate these references until the next frame starts. for (ref_index = 0; ref_index < 3; ref_index++) cm->active_ref_idx[ref_index] = INT_MAX; }
vpx_codec_err_t vp9_set_reference_dec(VP9D_PTR ptr, VP9_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd) { VP9D_COMP *pbi = (VP9D_COMP *) ptr; VP9_COMMON *cm = &pbi->common; int *ref_fb_ptr = NULL; /* TODO(jkoleszar): The decoder doesn't have any real knowledge of what the * encoder is using the frame buffers for. This is just a stub to keep the * vpxenc --test-decode functionality working, and will be replaced in a * later commit that adds VP9-specific controls for this functionality. */ if (ref_frame_flag == VP9_LAST_FLAG) { ref_fb_ptr = &pbi->common.active_ref_idx[0]; } else if (ref_frame_flag == VP9_GOLD_FLAG) { ref_fb_ptr = &pbi->common.active_ref_idx[1]; } else if (ref_frame_flag == VP9_ALT_FLAG) { ref_fb_ptr = &pbi->common.active_ref_idx[2]; } else { vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR, "Invalid reference frame"); return pbi->common.error.error_code; } if (!equal_dimensions(&cm->yv12_fb[*ref_fb_ptr], sd)) { vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR, "Incorrect buffer dimensions"); } else { // Find an empty frame buffer. const int free_fb = get_free_fb(cm); // Decrease fb_idx_ref_cnt since it will be increased again in // ref_cnt_fb() below. cm->fb_idx_ref_cnt[free_fb]--; // Manage the reference counters and copy image. ref_cnt_fb(cm->fb_idx_ref_cnt, ref_fb_ptr, free_fb); vp8_yv12_copy_frame(sd, &cm->yv12_fb[*ref_fb_ptr]); } return pbi->common.error.error_code; }
vpx_codec_err_t vp8dx_set_reference(VP8D_COMP *pbi, enum vpx_ref_frame_type ref_frame_flag, YV12_BUFFER_CONFIG *sd) { VP8_COMMON *cm = &pbi->common; int *ref_fb_ptr = NULL; int free_fb; if (ref_frame_flag == VP8_LAST_FRAME) ref_fb_ptr = &cm->lst_fb_idx; else if (ref_frame_flag == VP8_GOLD_FRAME) ref_fb_ptr = &cm->gld_fb_idx; else if (ref_frame_flag == VP8_ALTR_FRAME) ref_fb_ptr = &cm->alt_fb_idx; else{ vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR, "Invalid reference frame"); return pbi->common.error.error_code; } if(cm->yv12_fb[*ref_fb_ptr].y_height != sd->y_height || cm->yv12_fb[*ref_fb_ptr].y_width != sd->y_width || cm->yv12_fb[*ref_fb_ptr].uv_height != sd->uv_height || cm->yv12_fb[*ref_fb_ptr].uv_width != sd->uv_width){ vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR, "Incorrect buffer dimensions"); } else{ /* Find an empty frame buffer. */ free_fb = get_free_fb(cm); /* Decrease fb_idx_ref_cnt since it will be increased again in * ref_cnt_fb() below. */ cm->fb_idx_ref_cnt[free_fb]--; /* Manage the reference counters and copy image. */ ref_cnt_fb (cm->fb_idx_ref_cnt, ref_fb_ptr, free_fb); vp8_yv12_copy_frame(sd, &cm->yv12_fb[*ref_fb_ptr]); } return pbi->common.error.error_code; }
/* If any buffer updating is signaled it should be done here. */ static void swap_frame_buffers(VP9Decoder *pbi) { int ref_index = 0, mask; VP9_COMMON *const cm = &pbi->common; for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) { if (mask & 1) { const int old_idx = cm->ref_frame_map[ref_index]; ref_cnt_fb(cm->frame_bufs, &cm->ref_frame_map[ref_index], cm->new_fb_idx); if (old_idx >= 0 && cm->frame_bufs[old_idx].ref_count == 0) cm->release_fb_cb(cm->cb_priv, &cm->frame_bufs[old_idx].raw_frame_buffer); } ++ref_index; } cm->frame_to_show = get_frame_new_buffer(cm); cm->frame_bufs[cm->new_fb_idx].ref_count--; // Invalidate these references until the next frame starts. for (ref_index = 0; ref_index < 3; ref_index++) cm->frame_refs[ref_index].idx = INT_MAX; }