static void init_picture (GstVaapiDecoderVp8 * decoder, GstVaapiPicture * picture) { GstVaapiDecoderVp8Private *const priv = &decoder->priv; GstVp8FrameHdr *const frame_hdr = &priv->frame_hdr; picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME; picture->type = frame_hdr->key_frame ? GST_VAAPI_PICTURE_TYPE_I : GST_VAAPI_PICTURE_TYPE_P; picture->pts = GST_VAAPI_DECODER_CODEC_FRAME (decoder)->pts; if (!frame_hdr->show_frame) GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_SKIPPED); }
static GstVaapiDecoderStatus decode_frame(GstVaapiDecoderVC1 *decoder, GstVC1BDU *rbdu, GstVC1BDU *ebdu) { GstVaapiDecoderVC1Private * const priv = decoder->priv; GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr; GstVC1AdvancedSeqHdr *advanced = &seq_hdr->advanced; GstVC1FrameHdr * const frame_hdr = &priv->frame_hdr; GstVC1ParserResult result; GstVaapiPicture *picture; GstVaapiSlice *slice; GstVaapiDecoderStatus status; VASliceParameterBufferVC1 *slice_param; GstClockTime pts; gint32 poc; status = ensure_context(decoder); if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) { GST_DEBUG("failed to reset context"); return status; } if (priv->current_picture ) { if(!decode_current_picture(decoder)) return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; } picture = GST_VAAPI_PICTURE_NEW(VC1, decoder); if (!picture) { GST_DEBUG("failed to allocate picture"); return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED; } if (!gst_vc1_bitplanes_ensure_size(priv->bitplanes, seq_hdr)) { GST_DEBUG("failed to allocate bitplanes"); return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED; } memset(frame_hdr, 0, sizeof(*frame_hdr)); result = gst_vc1_parse_frame_header( rbdu->data + rbdu->offset, rbdu->size, frame_hdr, seq_hdr, priv->bitplanes ); if (result != GST_VC1_PARSER_OK) { GST_DEBUG("failed to parse frame layer"); return get_status(result); } switch (frame_hdr->ptype) { case GST_VC1_PICTURE_TYPE_I: picture->type = GST_VAAPI_PICTURE_TYPE_I; GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE); break; case GST_VC1_PICTURE_TYPE_SKIPPED: case GST_VC1_PICTURE_TYPE_P: picture->type = GST_VAAPI_PICTURE_TYPE_P; GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE); break; case GST_VC1_PICTURE_TYPE_B: picture->type = GST_VAAPI_PICTURE_TYPE_B; priv->successive_bfrm_cnt += 1; break; case GST_VC1_PICTURE_TYPE_BI: picture->type = GST_VAAPI_PICTURE_TYPE_BI; priv->successive_bfrm_cnt += 1; break; default: GST_DEBUG("unsupported picture type %d", frame_hdr->ptype); return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; } /*As far as dpb is only storing the reference pictures, always increesing poc should work fine. But we should explictly calculate the pts of frames*/ if(!GST_VAAPI_PICTURE_IS_REFERENCE(picture)) picture->poc = priv->frm_cnt - 1; else picture->poc = priv->frm_cnt; gst_vaapi_decoder_get_framerate(GST_VAAPI_DECODER_CAST(decoder), &priv->fps_n, &priv->fps_d); pts = gst_util_uint64_scale(picture->poc, GST_SECOND * priv->fps_d, priv->fps_n); if(GST_VAAPI_PICTURE_IS_REFERENCE(picture)){ if (priv->successive_bfrm_cnt) { poc = priv->frm_cnt - priv->successive_bfrm_cnt - 1; pts = gst_util_uint64_scale(picture->poc, GST_SECOND * priv->fps_d, priv->fps_n); gst_vaapi_dpb_reset_pts (priv->dpb, poc, pts); priv->successive_bfrm_cnt = 0; } } picture->pts = pts; priv->frm_cnt++; if (!fill_picture(decoder, picture)) return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; slice = GST_VAAPI_SLICE_NEW( VC1, decoder, ebdu->data + ebdu->sc_offset, ebdu->size + ebdu->offset - ebdu->sc_offset ); if (!slice) { GST_DEBUG("failed to allocate slice"); return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED; } gst_vaapi_picture_add_slice(picture, slice); /* Fill in VASliceParameterBufferVC1 */ slice_param = slice->param; slice_param->macroblock_offset = 8 * (ebdu->offset - ebdu->sc_offset) + frame_hdr->header_size; slice_param->slice_vertical_position = 0; gst_vaapi_picture_replace(&priv->current_picture, picture); gst_vaapi_picture_unref(picture); return GST_VAAPI_DECODER_STATUS_SUCCESS; }