static GstVaapiDecoderStatus gst_vaapi_decoder_jpeg_decode (GstVaapiDecoder * base_decoder, GstVaapiDecoderUnit * unit) { GstVaapiDecoderJpeg *const decoder = GST_VAAPI_DECODER_JPEG_CAST (base_decoder); GstVaapiDecoderStatus status; GstJpegSegment seg; GstBuffer *const buffer = GST_VAAPI_DECODER_CODEC_FRAME (decoder)->input_buffer; GstMapInfo map_info; status = ensure_decoder (decoder); if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) return status; if (!gst_buffer_map (buffer, &map_info, GST_MAP_READ)) { GST_ERROR ("failed to map buffer"); return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; } seg.marker = unit_get_marker_code (unit); seg.data = map_info.data; seg.offset = unit->offset; seg.size = unit->size; status = decode_segment (decoder, &seg); gst_buffer_unmap (buffer, &map_info); if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) return status; return GST_VAAPI_DECODER_STATUS_SUCCESS; }
static GstVaapiDecoderStatus gst_vaapi_decoder_jpeg_end_frame (GstVaapiDecoder * base_decoder) { GstVaapiDecoderJpeg *const decoder = GST_VAAPI_DECODER_JPEG_CAST (base_decoder); return decode_current_picture (decoder); }
static void gst_vaapi_decoder_jpeg_destroy (GstVaapiDecoder * base_decoder) { GstVaapiDecoderJpeg *const decoder = GST_VAAPI_DECODER_JPEG_CAST (base_decoder); gst_vaapi_decoder_jpeg_close (decoder); }
static gboolean gst_vaapi_decoder_jpeg_create(GstVaapiDecoder *base_decoder) { GstVaapiDecoderJpeg * const decoder = GST_VAAPI_DECODER_JPEG_CAST(base_decoder); GstVaapiDecoderJpegPrivate * const priv = &decoder->priv; priv->profile = GST_VAAPI_PROFILE_JPEG_BASELINE; priv->profile_changed = TRUE; 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 gst_vaapi_decoder_jpeg_parse (GstVaapiDecoder * base_decoder, GstAdapter * adapter, gboolean at_eos, GstVaapiDecoderUnit * unit) { GstVaapiDecoderJpeg *const decoder = GST_VAAPI_DECODER_JPEG_CAST (base_decoder); GstVaapiDecoderJpegPrivate *const priv = &decoder->priv; GstVaapiParserState *const ps = GST_VAAPI_PARSER_STATE (base_decoder); GstVaapiDecoderStatus status; GstJpegMarker marker; GstJpegSegment seg; const guchar *buf; guint buf_size, flags; gint ofs1, ofs2; status = ensure_decoder (decoder); if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) return status; /* Expect at least 2 bytes for the marker */ buf_size = gst_adapter_available (adapter); if (buf_size < 2) return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA; buf = gst_adapter_map (adapter, buf_size); if (!buf) return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA; ofs1 = ps->input_offset1 - 2; if (ofs1 < 0) ofs1 = 0; for (;;) { // Skip any garbage until we reach SOI, if needed if (!gst_jpeg_parse (&seg, buf, buf_size, ofs1)) { gst_adapter_unmap (adapter); ps->input_offset1 = buf_size; return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA; } ofs1 = seg.offset; marker = seg.marker; if (!VALID_STATE (parser, GOT_SOI) && marker != GST_JPEG_MARKER_SOI) continue; if (marker == GST_JPEG_MARKER_SOS) { ofs2 = ps->input_offset2 - 2; if (ofs2 < ofs1 + seg.size) ofs2 = ofs1 + seg.size; // Parse the whole scan + ECSs, including RSTi for (;;) { if (!gst_jpeg_parse (&seg, buf, buf_size, ofs2)) { gst_adapter_unmap (adapter); ps->input_offset1 = ofs1; ps->input_offset2 = buf_size; return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA; } if (is_scan_complete (seg.marker)) break; ofs2 = seg.offset + seg.size; } ofs2 = seg.offset - 2; } else { // Check that the whole segment is actually available (in buffer) ofs2 = ofs1 + seg.size; if (ofs2 > buf_size) { gst_adapter_unmap (adapter); ps->input_offset1 = ofs1; return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA; } } break; } gst_adapter_unmap (adapter); unit->size = ofs2 - ofs1; unit_set_marker_code (unit, marker); gst_adapter_flush (adapter, ofs1); ps->input_offset1 = 2; ps->input_offset2 = 2; flags = 0; switch (marker) { case GST_JPEG_MARKER_SOI: flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START; priv->parser_state |= GST_JPEG_VIDEO_STATE_GOT_SOI; break; case GST_JPEG_MARKER_EOI: flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END; priv->parser_state = 0; break; case GST_JPEG_MARKER_SOS: flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE; priv->parser_state |= GST_JPEG_VIDEO_STATE_GOT_SOS; break; case GST_JPEG_MARKER_DAC: case GST_JPEG_MARKER_DHT: case GST_JPEG_MARKER_DQT: if (priv->parser_state & GST_JPEG_VIDEO_STATE_GOT_SOF) flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE; break; case GST_JPEG_MARKER_DRI: if (priv->parser_state & GST_JPEG_VIDEO_STATE_GOT_SOS) flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE; break; case GST_JPEG_MARKER_DNL: flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE; break; case GST_JPEG_MARKER_COM: flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP; break; default: /* SOFn segments */ if (marker >= GST_JPEG_MARKER_SOF_MIN && marker <= GST_JPEG_MARKER_SOF_MAX) priv->parser_state |= GST_JPEG_VIDEO_STATE_GOT_SOF; /* Application segments */ else if (marker >= GST_JPEG_MARKER_APP_MIN && marker <= GST_JPEG_MARKER_APP_MAX) flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP; /* Reserved */ else if (marker >= 0x02 && marker <= 0xbf) flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP; break; } GST_VAAPI_DECODER_UNIT_FLAG_SET (unit, flags); return GST_VAAPI_DECODER_STATUS_SUCCESS; }