static GstVaapiDecoderStatus decode_current_picture (GstVaapiDecoderVp8 * decoder) { GstVaapiDecoderVp8Private *const priv = &decoder->priv; GstVaapiPicture *const picture = priv->current_picture; if (!picture) return GST_VAAPI_DECODER_STATUS_SUCCESS; update_ref_frames (decoder); if (!gst_vaapi_picture_decode (picture)) goto error; if (!gst_vaapi_picture_output (picture)) goto error; gst_vaapi_picture_replace (&priv->current_picture, NULL); return GST_VAAPI_DECODER_STATUS_SUCCESS; /* ERRORS */ error: { /* XXX: fix for cases where first field failed to be decoded */ gst_vaapi_picture_replace (&priv->current_picture, NULL); return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; } }
static GstVaapiDecoderStatus decode_current_picture (GstVaapiDecoderJpeg * decoder) { GstVaapiDecoderJpegPrivate *const priv = &decoder->priv; GstVaapiPicture *const picture = priv->current_picture; if (!VALID_STATE (decoder, VALID_PICTURE)) goto drop_frame; priv->decoder_state = 0; if (!picture) return GST_VAAPI_DECODER_STATUS_SUCCESS; if (!gst_vaapi_picture_decode (picture)) goto error; if (!gst_vaapi_picture_output (picture)) goto error; gst_vaapi_picture_replace (&priv->current_picture, NULL); return GST_VAAPI_DECODER_STATUS_SUCCESS; /* ERRORS */ error: { gst_vaapi_picture_replace (&priv->current_picture, NULL); return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; } drop_frame: { priv->decoder_state = 0; return (GstVaapiDecoderStatus) GST_VAAPI_DECODER_STATUS_DROP_FRAME; } }
static void gst_vaapi_decoder_vp8_close (GstVaapiDecoderVp8 * decoder) { GstVaapiDecoderVp8Private *const priv = &decoder->priv; gst_vaapi_picture_replace (&priv->last_picture, NULL); gst_vaapi_picture_replace (&priv->golden_ref_picture, NULL); gst_vaapi_picture_replace (&priv->alt_ref_picture, NULL); gst_vaapi_picture_replace (&priv->current_picture, NULL); }
static void update_ref_frames (GstVaapiDecoderVp8 * decoder) { GstVaapiDecoderVp8Private *const priv = &decoder->priv; GstVaapiPicture *picture = priv->current_picture; GstVp8FrameHdr *const frame_hdr = &priv->frame_hdr; // update picture reference if (frame_hdr->key_frame) { gst_vaapi_picture_replace (&priv->golden_ref_picture, picture); gst_vaapi_picture_replace (&priv->alt_ref_picture, picture); } else { // process refresh_alternate_frame/copy_buffer_to_alternate first if (frame_hdr->refresh_alternate_frame) { gst_vaapi_picture_replace (&priv->alt_ref_picture, picture); } else { switch (frame_hdr->copy_buffer_to_alternate) { case 0: // do nothing break; case 1: gst_vaapi_picture_replace (&priv->alt_ref_picture, priv->last_picture); break; case 2: gst_vaapi_picture_replace (&priv->alt_ref_picture, priv->golden_ref_picture); break; default: GST_WARNING ("WARNING: VP8 decoder: unrecognized copy_buffer_to_alternate"); } } if (frame_hdr->refresh_golden_frame) { gst_vaapi_picture_replace (&priv->golden_ref_picture, picture); } else { switch (frame_hdr->copy_buffer_to_golden) { case 0: // do nothing break; case 1: gst_vaapi_picture_replace (&priv->golden_ref_picture, priv->last_picture); break; case 2: gst_vaapi_picture_replace (&priv->golden_ref_picture, priv->alt_ref_picture); break; default: GST_WARNING ("WARNING: VP8 decoder: unrecognized copy_buffer_to_golden"); } } } if (frame_hdr->key_frame || frame_hdr->refresh_last) gst_vaapi_picture_replace (&priv->last_picture, picture); }
static void gst_vaapi_decoder_vc1_close(GstVaapiDecoderVC1 *decoder) { GstVaapiDecoderVC1Private * const priv = decoder->priv; gst_vaapi_picture_replace(&priv->current_picture, NULL); if (priv->sub_buffer) { gst_buffer_unref(priv->sub_buffer); priv->sub_buffer = NULL; } if (priv->bitplanes) { gst_vc1_bitplanes_free(priv->bitplanes); priv->bitplanes = NULL; } if (priv->dpb) { gst_vaapi_dpb_unref(priv->dpb); priv->dpb = NULL; } if (priv->adapter) { gst_adapter_clear(priv->adapter); g_object_unref(priv->adapter); priv->adapter = NULL; } }
static GstVaapiDecoderStatus decode_picture (GstVaapiDecoderVp8 * decoder, const guchar * buf, guint buf_size) { GstVaapiDecoderVp8Private *const priv = &decoder->priv; GstVaapiPicture *picture; GstVaapiDecoderStatus status; status = ensure_context (decoder); if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) return status; /* Create new picture */ picture = GST_VAAPI_PICTURE_NEW (VP8, decoder); if (!picture) { GST_ERROR ("failed to allocate picture"); return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED; } gst_vaapi_picture_replace (&priv->current_picture, picture); gst_vaapi_picture_unref (picture); status = ensure_quant_matrix (decoder, picture); if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) return status; status = ensure_probability_table (decoder, picture); if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) return status; init_picture (decoder, picture); if (!fill_picture (decoder, picture)) return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; return decode_slice (decoder, picture, buf, buf_size); }
static GstVaapiDecoderStatus decode_picture( GstVaapiDecoderJpeg *decoder, guint8 profile, guchar *buf, guint buf_size, GstClockTime pts ) { GstVaapiDecoderJpegPrivate * const priv = decoder->priv; GstJpegFrameHdr * const frame_hdr = &priv->frame_hdr; GstVaapiPicture *picture; GstVaapiDecoderStatus status; switch (profile) { case GST_JPEG_MARKER_SOF_MIN: priv->profile = GST_VAAPI_PROFILE_JPEG_BASELINE; break; default: GST_ERROR("unsupported profile %d", profile); return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE; } memset(frame_hdr, 0, sizeof(*frame_hdr)); if (!gst_jpeg_parse_frame_hdr(frame_hdr, buf, buf_size, 0)) { GST_ERROR("failed to parse image"); return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER; } priv->height = frame_hdr->height; priv->width = frame_hdr->width; status = ensure_context(decoder); if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) { GST_ERROR("failed to reset context"); return status; } if (priv->current_picture && !decode_current_picture(decoder)) return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; picture = GST_VAAPI_PICTURE_NEW(JPEGBaseline, decoder); if (!picture) { GST_ERROR("failed to allocate picture"); return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED; } gst_vaapi_picture_replace(&priv->current_picture, picture); gst_vaapi_picture_unref(picture); if (!fill_picture(decoder, picture, frame_hdr)) return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; /* Update presentation time */ picture->pts = pts; return GST_VAAPI_DECODER_STATUS_SUCCESS; }
static void gst_vaapi_decoder_jpeg_close(GstVaapiDecoderJpeg *decoder) { GstVaapiDecoderJpegPrivate * const priv = &decoder->priv; gst_vaapi_picture_replace(&priv->current_picture, NULL); /* Reset all */ priv->profile = GST_VAAPI_PROFILE_JPEG_BASELINE; priv->width = 0; priv->height = 0; priv->is_opened = FALSE; priv->profile_changed = TRUE; }
static gboolean decode_current_picture(GstVaapiDecoderJpeg *decoder) { GstVaapiDecoderJpegPrivate * const priv = decoder->priv; GstVaapiPicture * const picture = priv->current_picture; gboolean success = TRUE; if (picture) { if (!gst_vaapi_picture_decode(picture)) success = FALSE; else if (!gst_vaapi_picture_output(picture)) success = FALSE; gst_vaapi_picture_replace(&priv->current_picture, NULL); } return success; }
static gboolean decode_current_picture(GstVaapiDecoderVC1 *decoder) { GstVaapiDecoderVC1Private * const priv = decoder->priv; GstVaapiPicture * const picture = priv->current_picture; if (picture) { if (!gst_vaapi_picture_decode(picture)) return FALSE; if (GST_VAAPI_PICTURE_IS_COMPLETE(picture)) { if (!gst_vaapi_dpb_add(priv->dpb, picture)) return FALSE; gst_vaapi_picture_replace(&priv->current_picture, NULL); } } return TRUE; }
static GstVaapiDecoderStatus gst_vaapi_decoder_jpeg_start_frame (GstVaapiDecoder * base_decoder, GstVaapiDecoderUnit * base_unit) { GstVaapiDecoderJpeg *const decoder = GST_VAAPI_DECODER_JPEG_CAST (base_decoder); GstVaapiDecoderJpegPrivate *const priv = &decoder->priv; GstVaapiPicture *picture; GstVaapiDecoderStatus status; if (!VALID_STATE (decoder, GOT_SOF)) return GST_VAAPI_DECODER_STATUS_SUCCESS; status = ensure_context (decoder); if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) { GST_ERROR ("failed to reset context"); return status; } picture = GST_VAAPI_PICTURE_NEW (JPEGBaseline, decoder); if (!picture) { GST_ERROR ("failed to allocate picture"); return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED; } gst_vaapi_picture_replace (&priv->current_picture, picture); gst_vaapi_picture_unref (picture); if (!fill_picture (decoder, picture, &priv->frame_hdr)) return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; status = fill_quantization_table (decoder, picture); if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) return status; /* Update presentation time */ picture->pts = GST_VAAPI_DECODER_CODEC_FRAME (decoder)->pts; return GST_VAAPI_DECODER_STATUS_SUCCESS; }
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; }