GstVaapiDecoderStatus gst_vaapi_decoder_ffmpeg_decode(GstVaapiDecoder *decoder, GstBuffer *buffer) { GstVaapiDecoderFfmpeg * const ffdecoder = GST_VAAPI_DECODER_FFMPEG(decoder); GstVaapiDecoderFfmpegPrivate * const priv = ffdecoder->priv; GstClockTime inbuf_ts; guchar *outbuf; gint inbuf_ofs, inbuf_size, outbuf_size; gboolean got_frame; g_return_val_if_fail(priv->is_constructed, GST_VAAPI_DECODER_STATUS_ERROR_INIT_FAILED); if (!priv->is_opened) { priv->is_opened = gst_vaapi_decoder_ffmpeg_open(ffdecoder, buffer); if (!priv->is_opened) return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC; } inbuf_ofs = 0; inbuf_size = GST_BUFFER_SIZE(buffer); inbuf_ts = GST_BUFFER_TIMESTAMP(buffer); if (priv->pctx) { do { int parsed_size = av_parser_parse2( priv->pctx, priv->avctx, &outbuf, &outbuf_size, GST_BUFFER_DATA(buffer) + inbuf_ofs, inbuf_size, inbuf_ts, inbuf_ts ,0 ); got_frame = outbuf && outbuf_size > 0; if (parsed_size > 0) { inbuf_ofs += parsed_size; inbuf_size -= parsed_size; } } while (!got_frame && inbuf_size > 0); inbuf_ts = priv->pctx->pts; } else { outbuf = GST_BUFFER_DATA(buffer); outbuf_size = inbuf_size; got_frame = outbuf && outbuf_size > 0; inbuf_ofs = inbuf_size; inbuf_size = 0; } if (inbuf_size > 0 && !gst_vaapi_decoder_push_buffer_sub(decoder, buffer, inbuf_ofs, inbuf_size)) return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED; if (!got_frame && !GST_BUFFER_IS_EOS(buffer)) return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA; priv->in_timestamp = inbuf_ts; return decode_frame(ffdecoder, outbuf, outbuf_size); }
static GstVaapiDecoderStatus decode_step (GstVaapiDecoder * decoder) { GstVaapiParserState *const ps = &decoder->parser_state; GstVaapiDecoderStatus status; GstBuffer *buffer; gboolean got_frame; guint got_unit_size, input_size; status = gst_vaapi_decoder_check_status (decoder); if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) return status; /* Fill adapter with all buffers we have in the queue */ for (;;) { buffer = pop_buffer (decoder); if (!buffer) break; ps->at_eos = GST_BUFFER_IS_EOS (buffer); if (!ps->at_eos) gst_adapter_push (ps->input_adapter, buffer); } /* Parse and decode all decode units */ input_size = gst_adapter_available (ps->input_adapter); if (input_size == 0) { if (ps->at_eos) return GST_VAAPI_DECODER_STATUS_END_OF_STREAM; return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA; } do { if (!ps->current_frame) { ps->current_frame = g_slice_new0 (GstVideoCodecFrame); if (!ps->current_frame) return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED; ps->current_frame->ref_count = 1; ps->current_frame->system_frame_number = ps->current_frame_number++; } status = do_parse (decoder, ps->current_frame, ps->input_adapter, ps->at_eos, &got_unit_size, &got_frame); GST_DEBUG ("parse frame (status = %d)", status); if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) { if (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA && ps->at_eos) status = GST_VAAPI_DECODER_STATUS_END_OF_STREAM; break; } if (got_unit_size > 0) { buffer = gst_adapter_take_buffer (ps->input_adapter, got_unit_size); input_size -= got_unit_size; if (gst_adapter_available (ps->output_adapter) == 0) { ps->current_frame->pts = gst_adapter_prev_pts (ps->input_adapter, NULL); } gst_adapter_push (ps->output_adapter, buffer); } if (got_frame) { ps->current_frame->input_buffer = gst_adapter_take_buffer (ps->output_adapter, gst_adapter_available (ps->output_adapter)); status = do_decode (decoder, ps->current_frame); GST_DEBUG ("decode frame (status = %d)", status); gst_video_codec_frame_unref (ps->current_frame); ps->current_frame = NULL; break; } } while (input_size > 0); return status; }