static GstFlowReturn gst_msdkdec_finish_task (GstMsdkDec * thiz, MsdkDecTask * task) { GstVideoDecoder *decoder = GST_VIDEO_DECODER (thiz); GstFlowReturn flow; GstVideoCodecFrame *frame; MsdkSurface *surface; mfxStatus status; GList *l; if (G_LIKELY (task->sync_point)) { status = MFXVideoCORE_SyncOperation (gst_msdk_context_get_session (thiz->context), task->sync_point, 300000); if (status != MFX_ERR_NONE) { GST_ERROR_OBJECT (thiz, "failed to do sync operation"); return GST_FLOW_ERROR; } } if (G_LIKELY (task->sync_point || (task->surface && task->decode_only))) { gboolean decode_only = task->decode_only; frame = gst_msdkdec_get_oldest_frame (decoder); l = g_list_find_custom (thiz->decoded_msdk_surfaces, task->surface, _find_msdk_surface); if (l) { surface = l->data; } else { GST_ERROR_OBJECT (thiz, "Couldn't find the cached MSDK surface"); return GST_FLOW_ERROR; } if (G_LIKELY (frame)) { if (G_LIKELY (surface->copy.buffer == NULL)) { frame->output_buffer = gst_buffer_ref (surface->buf); } else { gst_video_frame_copy (&surface->copy, &surface->data); frame->output_buffer = gst_buffer_ref (surface->copy.buffer); } } free_surface (thiz, surface); task->sync_point = NULL; task->surface = NULL; task->decode_only = FALSE; if (!frame) return GST_FLOW_FLUSHING; gst_video_codec_frame_unref (frame); if (decode_only) GST_VIDEO_CODEC_FRAME_SET_DECODE_ONLY (frame); flow = gst_video_decoder_finish_frame (decoder, frame); return flow; } return GST_FLOW_OK; }
static GstFlowReturn gst_vp9_dec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame) { GstVP9Dec *dec; GstFlowReturn ret = GST_FLOW_OK; vpx_codec_err_t status; vpx_codec_iter_t iter = NULL; vpx_image_t *img; long decoder_deadline = 0; GstClockTimeDiff deadline; GstMapInfo minfo; GST_DEBUG_OBJECT (decoder, "handle_frame"); dec = GST_VP9_DEC (decoder); if (!dec->decoder_inited) { ret = open_codec (dec, frame); if (ret == GST_FLOW_CUSTOM_SUCCESS_1) return GST_FLOW_OK; else if (ret != GST_FLOW_OK) return ret; } deadline = gst_video_decoder_get_max_decode_time (decoder, frame); if (deadline < 0) { decoder_deadline = 1; } else if (deadline == G_MAXINT64) { decoder_deadline = 0; } else { decoder_deadline = MAX (1, deadline / GST_MSECOND); } if (!gst_buffer_map (frame->input_buffer, &minfo, GST_MAP_READ)) { GST_ERROR_OBJECT (dec, "Failed to map input buffer"); return GST_FLOW_ERROR; } status = vpx_codec_decode (&dec->decoder, minfo.data, minfo.size, NULL, decoder_deadline); gst_buffer_unmap (frame->input_buffer, &minfo); if (status) { GST_VIDEO_DECODER_ERROR (decoder, 1, LIBRARY, ENCODE, ("Failed to decode frame"), ("%s", gst_vpx_error_name (status)), ret); return ret; } img = vpx_codec_get_frame (&dec->decoder, &iter); if (img) { GstVideoFormat fmt; switch (img->fmt) { case VPX_IMG_FMT_I420: fmt = GST_VIDEO_FORMAT_I420; break; case VPX_IMG_FMT_YV12: fmt = GST_VIDEO_FORMAT_YV12; break; case VPX_IMG_FMT_I422: fmt = GST_VIDEO_FORMAT_Y42B; break; case VPX_IMG_FMT_I444: fmt = GST_VIDEO_FORMAT_Y444; break; default: vpx_img_free (img); GST_ELEMENT_ERROR (decoder, LIBRARY, ENCODE, ("Failed to decode frame"), ("Unsupported color format %d", img->fmt)); return GST_FLOW_ERROR; break; } if (!dec->output_state || dec->output_state->info.finfo->format != fmt || dec->output_state->info.width != img->d_w || dec->output_state->info.height != img->d_h) { gboolean send_tags = !dec->output_state; if (dec->output_state) gst_video_codec_state_unref (dec->output_state); dec->output_state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (dec), fmt, img->d_w, img->d_h, dec->input_state); gst_video_decoder_negotiate (GST_VIDEO_DECODER (dec)); if (send_tags) gst_vp9_dec_send_tags (dec); } if (deadline < 0) { GST_LOG_OBJECT (dec, "Skipping late frame (%f s past deadline)", (double) -deadline / GST_SECOND); gst_video_decoder_drop_frame (decoder, frame); } else { ret = gst_video_decoder_allocate_output_frame (decoder, frame); if (ret == GST_FLOW_OK) { gst_vp9_dec_image_to_buffer (dec, img, frame->output_buffer); ret = gst_video_decoder_finish_frame (decoder, frame); } else { gst_video_decoder_drop_frame (decoder, frame); } } vpx_img_free (img); while ((img = vpx_codec_get_frame (&dec->decoder, &iter))) { GST_WARNING_OBJECT (decoder, "Multiple decoded frames... dropping"); vpx_img_free (img); } } else { /* Invisible frame */ GST_VIDEO_CODEC_FRAME_SET_DECODE_ONLY (frame); gst_video_decoder_finish_frame (decoder, frame); } return ret; }