jpeg: update to match latest parser API.

This commit is contained in:
Gwenole Beauchesne 2012-07-17 13:43:32 +02:00
parent 8f93bbc937
commit 1139908487

View file

@ -62,26 +62,14 @@ struct _GstVaapiDecoderJpegPrivate {
guint is_constructed : 1; guint is_constructed : 1;
}; };
typedef struct _GstJpegScanSegment GstJpegScanSegment;
static GstVaapiDecoderStatus struct _GstJpegScanSegment {
get_status(GstJpegParserResult result) guint header_offset;
{ guint header_size;
GstVaapiDecoderStatus status; guint data_offset;
guint data_size;
switch (result) { guint is_valid : 1;
case GST_JPEG_PARSER_OK: };
status = GST_VAAPI_DECODER_STATUS_SUCCESS;
break;
case GST_JPEG_PARSER_BROKEN_DATA:
case GST_JPEG_PARSER_NO_SCAN_FOUND:
status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
break;
default:
status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
break;
}
return status;
}
static void static void
gst_vaapi_decoder_jpeg_close(GstVaapiDecoderJpeg *decoder) gst_vaapi_decoder_jpeg_close(GstVaapiDecoderJpeg *decoder)
@ -161,21 +149,21 @@ ensure_context(GstVaapiDecoderJpeg *decoder)
return GST_VAAPI_DECODER_STATUS_SUCCESS; return GST_VAAPI_DECODER_STATUS_SUCCESS;
} }
static inline GstVaapiDecoderStatus static gboolean
decode_current_picture(GstVaapiDecoderJpeg *decoder) decode_current_picture(GstVaapiDecoderJpeg *decoder)
{ {
GstVaapiDecoderJpegPrivate * const priv = decoder->priv; GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
GstVaapiPicture * const picture = priv->current_picture; GstVaapiPicture * const picture = priv->current_picture;
GstVaapiDecoderStatus status = GST_VAAPI_DECODER_STATUS_SUCCESS; gboolean success = TRUE;
if (picture) { if (picture) {
if (!gst_vaapi_picture_decode(picture)) if (!gst_vaapi_picture_decode(picture))
status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; success = FALSE;
else if (!gst_vaapi_picture_output(picture)) else if (!gst_vaapi_picture_output(picture))
status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; success = FALSE;
gst_vaapi_picture_replace(&priv->current_picture, NULL); gst_vaapi_picture_replace(&priv->current_picture, NULL);
} }
return status; return success;
} }
static gboolean static gboolean
@ -327,32 +315,26 @@ decode_picture(
) )
{ {
GstVaapiDecoderJpegPrivate * const priv = decoder->priv; GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
GstVaapiPicture *picture = NULL; GstJpegFrameHdr * const frame_hdr = &priv->frame_hdr;
GstJpegFrameHdr *jpeg_frame_hdr = &priv->frame_hdr; GstVaapiPicture *picture;
GstVaapiDecoderStatus status = GST_VAAPI_DECODER_STATUS_SUCCESS; GstVaapiDecoderStatus status;
GstJpegParserResult result;
/* parse jpeg */
memset(jpeg_frame_hdr, 0, sizeof(GstJpegFrameHdr));
switch (profile) { switch (profile) {
case GST_JPEG_MARKER_SOF_MIN: case GST_JPEG_MARKER_SOF_MIN:
jpeg_frame_hdr->profile = GST_JPEG_MARKER_SOF_MIN; priv->profile = GST_VAAPI_PROFILE_JPEG_BASELINE;
priv->profile = GST_VAAPI_PROFILE_JPEG_BASELINE; break;
break; default:
default: GST_ERROR("unsupported profile %d", profile);
GST_WARNING("Jpeg profile was not supported."); return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
} }
result = gst_jpeg_parse_frame_hdr(jpeg_frame_hdr, buf, buf_size, 0); memset(frame_hdr, 0, sizeof(*frame_hdr));
if (result != GST_JPEG_PARSER_OK) { if (!gst_jpeg_parse_frame_hdr(frame_hdr, buf, buf_size, 0)) {
GST_ERROR("failed to parse image"); GST_ERROR("failed to parse image");
return get_status(result); return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
} }
priv->height = frame_hdr->height;
/* set info to va parameters in current picture*/ priv->width = frame_hdr->width;
priv->height = jpeg_frame_hdr->height;
priv->width = jpeg_frame_hdr->width;
status = ensure_context(decoder); status = ensure_context(decoder);
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) { if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
@ -360,9 +342,8 @@ decode_picture(
return status; return status;
} }
if (priv->current_picture && if (priv->current_picture && !decode_current_picture(decoder))
(status = decode_current_picture(decoder)) != GST_VAAPI_DECODER_STATUS_SUCCESS) return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
return status;
picture = GST_VAAPI_PICTURE_NEW(JPEG, decoder); picture = GST_VAAPI_PICTURE_NEW(JPEG, decoder);
if (!picture) { if (!picture) {
@ -372,12 +353,12 @@ decode_picture(
gst_vaapi_picture_replace(&priv->current_picture, picture); gst_vaapi_picture_replace(&priv->current_picture, picture);
gst_vaapi_picture_unref(picture); gst_vaapi_picture_unref(picture);
if (!fill_picture(decoder, picture, jpeg_frame_hdr)) if (!fill_picture(decoder, picture, frame_hdr))
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
/* Update presentation time */ /* Update presentation time */
picture->pts = pts; picture->pts = pts;
return status; return GST_VAAPI_DECODER_STATUS_SUCCESS;
} }
static GstVaapiDecoderStatus static GstVaapiDecoderStatus
@ -388,15 +369,10 @@ decode_huffman_table(
) )
{ {
GstVaapiDecoderJpegPrivate * const priv = decoder->priv; GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
GstJpegParserResult result;
result = gst_jpeg_parse_huffman_table( if (!gst_jpeg_parse_huffman_table(&priv->huf_tables, buf, buf_size, 0)) {
&priv->huf_tables,
buf, buf_size, 0
);
if (result != GST_JPEG_PARSER_OK) {
GST_DEBUG("failed to parse Huffman table"); GST_DEBUG("failed to parse Huffman table");
return get_status(result); return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
} }
priv->has_huf_table = TRUE; priv->has_huf_table = TRUE;
return GST_VAAPI_DECODER_STATUS_SUCCESS; return GST_VAAPI_DECODER_STATUS_SUCCESS;
@ -410,12 +386,10 @@ decode_quant_table(
) )
{ {
GstVaapiDecoderJpegPrivate * const priv = decoder->priv; GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
GstJpegParserResult result;
result = gst_jpeg_parse_quant_table(&priv->quant_tables, buf, buf_size, 0); if (!gst_jpeg_parse_quant_table(&priv->quant_tables, buf, buf_size, 0)) {
if (result != GST_JPEG_PARSER_OK) {
GST_DEBUG("failed to parse quantization table"); GST_DEBUG("failed to parse quantization table");
return get_status(result); return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
} }
priv->has_quant_table = TRUE; priv->has_quant_table = TRUE;
return GST_VAAPI_DECODER_STATUS_SUCCESS; return GST_VAAPI_DECODER_STATUS_SUCCESS;
@ -429,15 +403,10 @@ decode_restart_interval(
) )
{ {
GstVaapiDecoderJpegPrivate * const priv = decoder->priv; GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
GstJpegParserResult result;
result = gst_jpeg_parse_restart_interval( if (!gst_jpeg_parse_restart_interval(&priv->mcu_restart, buf, buf_size, 0)) {
&priv->mcu_restart,
buf, buf_size, 0
);
if (result != GST_JPEG_PARSER_OK) {
GST_DEBUG("failed to parse restart interval"); GST_DEBUG("failed to parse restart interval");
return get_status(result); return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
} }
return GST_VAAPI_DECODER_STATUS_SUCCESS; return GST_VAAPI_DECODER_STATUS_SUCCESS;
} }
@ -452,7 +421,6 @@ decode_scan(
{ {
GstVaapiDecoderJpegPrivate * const priv = decoder->priv; GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
GstVaapiPicture *picture = priv->current_picture; GstVaapiPicture *picture = priv->current_picture;
GstJpegParserResult result = GST_JPEG_PARSER_OK;
VASliceParameterBufferJPEG *slice_param; VASliceParameterBufferJPEG *slice_param;
GstVaapiSlice *gst_slice; GstVaapiSlice *gst_slice;
guint total_h_samples, total_v_samples; guint total_h_samples, total_v_samples;
@ -460,25 +428,24 @@ decode_scan(
guint i; guint i;
if (!picture) { if (!picture) {
GST_ERROR ("There is no VAPicture before decoding scan."); GST_ERROR("There is no VAPicture before decoding scan.");
return GST_VAAPI_DECODER_STATUS_ERROR_INVALID_SURFACE; return GST_VAAPI_DECODER_STATUS_ERROR_INVALID_SURFACE;
} }
if (!fill_quantization_table(decoder, picture)) { if (!fill_quantization_table(decoder, picture)) {
GST_ERROR("Failed to fill in quantization table"); GST_ERROR("failed to fill in quantization table");
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
} }
if (!fill_huffman_table(decoder, picture)) { if (!fill_huffman_table(decoder, picture)) {
GST_ERROR("Failed to fill in huffman table"); GST_ERROR("failed to fill in huffman table");
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
} }
memset(&scan_hdr, 0, sizeof(scan_hdr)); memset(&scan_hdr, 0, sizeof(scan_hdr));
result = gst_jpeg_parse_scan_hdr(&scan_hdr, scan_header, scan_header_size, 0); if (!gst_jpeg_parse_scan_hdr(&scan_hdr, scan_header, scan_header_size, 0)) {
if (result != GST_JPEG_PARSER_OK) {
GST_DEBUG("Jpeg parsed scan failed."); GST_DEBUG("Jpeg parsed scan failed.");
return get_status(result); return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
} }
gst_slice = GST_VAAPI_SLICE_NEW(JPEG, decoder, scan_data, scan_data_size); gst_slice = GST_VAAPI_SLICE_NEW(JPEG, decoder, scan_data, scan_data_size);
@ -523,71 +490,116 @@ decode_buffer(GstVaapiDecoderJpeg *decoder, GstBuffer *buffer)
{ {
GstVaapiDecoderJpegPrivate * const priv = decoder->priv; GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
GstVaapiDecoderStatus status = GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA; GstVaapiDecoderStatus status = GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
GstJpegMarkerSegment seg;
GstJpegScanSegment scan_seg;
GstClockTime pts; GstClockTime pts;
guchar *buf; guchar *buf;
guint buf_size; guint buf_size, ofs;
GList *seg_list = NULL; gboolean append_ecs;
gboolean scan_found = FALSE;
GstJpegTypeOffsetSize *seg;
buf = GST_BUFFER_DATA(buffer); buf = GST_BUFFER_DATA(buffer);
buf_size = GST_BUFFER_SIZE(buffer); buf_size = GST_BUFFER_SIZE(buffer);
if (!buf && buf_size == 0) if (!buf && buf_size == 0)
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA; return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
memset(&scan_seg, 0, sizeof(scan_seg));
pts = GST_BUFFER_TIMESTAMP(buffer); pts = GST_BUFFER_TIMESTAMP(buffer);
g_assert(GST_CLOCK_TIME_IS_VALID(pts)); ofs = 0;
while (gst_jpeg_parse(&seg, buf, buf_size, ofs)) {
if (seg.size < 0) {
GST_DEBUG("buffer to short for parsing");
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
}
ofs += seg.size;
priv->has_quant_table = FALSE; /* Decode scan, if complete */
priv->has_huf_table = FALSE; if (seg.marker == GST_JPEG_MARKER_EOI && scan_seg.header_size > 0) {
priv->mcu_restart = 0; scan_seg.data_size = seg.offset - scan_seg.data_offset;
scan_seg.is_valid = TRUE;
}
if (scan_seg.is_valid) {
status = decode_scan(
decoder,
buf + scan_seg.header_offset,
scan_seg.header_size,
buf + scan_seg.data_offset,
scan_seg.data_size
);
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
break;
memset(&scan_seg, 0, sizeof(scan_seg));
}
seg_list = gst_jpeg_parse(buf, buf_size, 0); append_ecs = TRUE;
for (; seg_list && !scan_found; seg_list = seg_list->next) { switch (seg.marker) {
seg = seg_list->data; case GST_JPEG_MARKER_SOI:
g_assert(seg); priv->has_quant_table = FALSE;
switch (seg->type) { priv->has_huf_table = FALSE;
case GST_JPEG_MARKER_DHT: priv->mcu_restart = 0;
status = decode_huffman_table(decoder, buf + seg->offset, seg->size); status = GST_VAAPI_DECODER_STATUS_SUCCESS;
break; break;
case GST_JPEG_MARKER_DAC: case GST_JPEG_MARKER_EOI:
GST_ERROR("unsupported arithmetic decoding"); status = decode_current_picture(decoder);
status = GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE; break;
case GST_JPEG_MARKER_DHT:
status = decode_huffman_table(decoder, buf + seg.offset, seg.size);
break; break;
case GST_JPEG_MARKER_DQT: case GST_JPEG_MARKER_DQT:
status = decode_quant_table(decoder, buf + seg->offset, seg->size); status = decode_quant_table(decoder, buf + seg.offset, seg.size);
break; break;
case GST_JPEG_MARKER_DRI: case GST_JPEG_MARKER_DRI:
status = decode_restart_interval(decoder, buf + seg->offset, seg->size); status = decode_restart_interval(decoder, buf + seg.offset, seg.size);
break; break;
case GST_JPEG_MARKER_SOS: { case GST_JPEG_MARKER_DAC:
GstJpegScanOffsetSize * const scan = (GstJpegScanOffsetSize *)seg; GST_ERROR("unsupported arithmetic coding mode");
status = decode_scan( status = GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
decoder, buf + scan->header.offset, scan->header.size, break;
buf + scan->data_offset, scan->data_size case GST_JPEG_MARKER_SOS:
); scan_seg.header_offset = seg.offset;
scan_found = TRUE; scan_seg.header_size = seg.size;
scan_seg.data_offset = seg.offset + seg.size;
scan_seg.data_size = 0;
append_ecs = FALSE;
break; break;
}
default: default:
if (seg->type >= GST_JPEG_MARKER_SOF_MIN && /* Restart marker */
seg->type <= GST_JPEG_MARKER_SOF_MAX) if (seg.marker >= GST_JPEG_MARKER_RST_MIN &&
status = decode_picture(decoder, seg->type, buf + seg->offset, seg->size, pts); seg.marker <= GST_JPEG_MARKER_RST_MAX) {
else { append_ecs = FALSE;
GST_WARNING("unsupported marker (0x%02x)", seg->type); break;
status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
} }
/* Frame header */
if (seg.marker >= GST_JPEG_MARKER_SOF_MIN &&
seg.marker <= GST_JPEG_MARKER_SOF_MAX) {
status = decode_picture(
decoder,
seg.marker,
buf + seg.offset, seg.size,
pts
);
break;
}
/* Application segments */
if (seg.marker >= GST_JPEG_MARKER_APP_MIN &&
seg.marker <= GST_JPEG_MARKER_APP_MAX) {
status = GST_VAAPI_DECODER_STATUS_SUCCESS;
break;
}
GST_WARNING("unsupported marker (0x%02x)", seg.marker);
status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
break; break;
} }
}
/* clean seg_list */ /* Append entropy coded segments */
g_list_free_full(seg_list, g_free); if (append_ecs)
scan_seg.data_size = seg.offset - scan_seg.data_offset;
if (status == GST_VAAPI_DECODER_STATUS_SUCCESS) { if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
if (scan_found) break;
return decode_current_picture(decoder);
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
} }
return status; return status;
} }