mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-30 13:41:48 +00:00
mpeg2: initial port to new GstVaapiDecoder API.
This commit is contained in:
parent
e7e5c74a6e
commit
50090d6138
1 changed files with 115 additions and 75 deletions
|
@ -178,7 +178,6 @@ struct _GstVaapiDecoderMpeg2Private {
|
||||||
GstMpegVideoQuantMatrixExt quant_matrix_ext;
|
GstMpegVideoQuantMatrixExt quant_matrix_ext;
|
||||||
GstVaapiPicture *current_picture;
|
GstVaapiPicture *current_picture;
|
||||||
GstVaapiDpb *dpb;
|
GstVaapiDpb *dpb;
|
||||||
GstAdapter *adapter;
|
|
||||||
PTSGenerator tsg;
|
PTSGenerator tsg;
|
||||||
guint is_constructed : 1;
|
guint is_constructed : 1;
|
||||||
guint is_opened : 1;
|
guint is_opened : 1;
|
||||||
|
@ -284,25 +283,15 @@ gst_vaapi_decoder_mpeg2_close(GstVaapiDecoderMpeg2 *decoder)
|
||||||
gst_vaapi_dpb_unref(priv->dpb);
|
gst_vaapi_dpb_unref(priv->dpb);
|
||||||
priv->dpb = NULL;
|
priv->dpb = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->adapter) {
|
|
||||||
gst_adapter_clear(priv->adapter);
|
|
||||||
g_object_unref(priv->adapter);
|
|
||||||
priv->adapter = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_vaapi_decoder_mpeg2_open(GstVaapiDecoderMpeg2 *decoder, GstBuffer *buffer)
|
gst_vaapi_decoder_mpeg2_open(GstVaapiDecoderMpeg2 *decoder)
|
||||||
{
|
{
|
||||||
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
||||||
|
|
||||||
gst_vaapi_decoder_mpeg2_close(decoder);
|
gst_vaapi_decoder_mpeg2_close(decoder);
|
||||||
|
|
||||||
priv->adapter = gst_adapter_new();
|
|
||||||
if (!priv->adapter)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
priv->dpb = gst_vaapi_dpb_mpeg2_new();
|
priv->dpb = gst_vaapi_dpb_mpeg2_new();
|
||||||
if (!priv->dpb)
|
if (!priv->dpb)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -629,7 +618,6 @@ decode_gop(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
|
||||||
{
|
{
|
||||||
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
||||||
GstMpegVideoGop gop;
|
GstMpegVideoGop gop;
|
||||||
GstClockTime pts;
|
|
||||||
|
|
||||||
if (!gst_mpeg_video_parse_gop(&gop, buf, buf_size, 4)) {
|
if (!gst_mpeg_video_parse_gop(&gop, buf, buf_size, 4)) {
|
||||||
GST_ERROR("failed to parse GOP");
|
GST_ERROR("failed to parse GOP");
|
||||||
|
@ -643,8 +631,7 @@ decode_gop(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
|
||||||
gop.hour, gop.minute, gop.second, gop.frame,
|
gop.hour, gop.minute, gop.second, gop.frame,
|
||||||
priv->closed_gop, priv->broken_link);
|
priv->closed_gop, priv->broken_link);
|
||||||
|
|
||||||
pts = gst_adapter_prev_timestamp(priv->adapter, NULL);
|
pts_sync(&priv->tsg, GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts);
|
||||||
pts_sync(&priv->tsg, pts);
|
|
||||||
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -655,7 +642,6 @@ decode_picture(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
|
||||||
GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr;
|
GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr;
|
||||||
GstVaapiPicture *picture;
|
GstVaapiPicture *picture;
|
||||||
GstVaapiDecoderStatus status;
|
GstVaapiDecoderStatus status;
|
||||||
GstClockTime pts;
|
|
||||||
|
|
||||||
status = ensure_context(decoder);
|
status = ensure_context(decoder);
|
||||||
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
|
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
|
||||||
|
@ -715,8 +701,8 @@ decode_picture(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update presentation time */
|
/* Update presentation time */
|
||||||
pts = gst_adapter_prev_timestamp(priv->adapter, NULL);
|
picture->pts = pts_eval(&priv->tsg,
|
||||||
picture->pts = pts_eval(&priv->tsg, pts, pic_hdr->tsn);
|
GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts, pic_hdr->tsn);
|
||||||
picture->poc = pts_get_poc(&priv->tsg);
|
picture->poc = pts_get_poc(&priv->tsg);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -1044,81 +1030,135 @@ undefined_picture:
|
||||||
static GstVaapiDecoderStatus
|
static GstVaapiDecoderStatus
|
||||||
decode_buffer(GstVaapiDecoderMpeg2 *decoder, GstBuffer *buffer)
|
decode_buffer(GstVaapiDecoderMpeg2 *decoder, GstBuffer *buffer)
|
||||||
{
|
{
|
||||||
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
|
||||||
GstVaapiDecoderStatus status;
|
GstVaapiDecoderStatus status;
|
||||||
gboolean is_eos;
|
|
||||||
guchar *buf;
|
guchar *buf;
|
||||||
guint buf_size, size;
|
guint buf_size;
|
||||||
guint32 start_code;
|
|
||||||
gint ofs;
|
|
||||||
|
|
||||||
buf = GST_BUFFER_DATA(buffer);
|
buf = GST_BUFFER_DATA(buffer);
|
||||||
buf_size = GST_BUFFER_SIZE(buffer);
|
buf_size = GST_BUFFER_SIZE(buffer);
|
||||||
is_eos = GST_BUFFER_IS_EOS(buffer);
|
|
||||||
if (buf && buf_size > 0)
|
|
||||||
gst_adapter_push(priv->adapter, gst_buffer_ref(buffer));
|
|
||||||
|
|
||||||
size = gst_adapter_available(priv->adapter);
|
status = decode_packet(decoder, buf, buf_size);
|
||||||
do {
|
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
||||||
if (size == 0) {
|
return status;
|
||||||
status = GST_VAAPI_DECODER_STATUS_SUCCESS;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
|
|
||||||
if (size < 4)
|
|
||||||
break;
|
|
||||||
ofs = scan_for_start_code(priv->adapter, 0, size, &start_code);
|
|
||||||
if (ofs < 0)
|
|
||||||
break;
|
|
||||||
gst_adapter_flush(priv->adapter, ofs);
|
|
||||||
size -= ofs;
|
|
||||||
|
|
||||||
status = gst_vaapi_decoder_check_status(GST_VAAPI_DECODER(decoder));
|
|
||||||
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
|
||||||
break;
|
|
||||||
|
|
||||||
status = GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
|
|
||||||
if (size < 8)
|
|
||||||
break;
|
|
||||||
ofs = scan_for_start_code(priv->adapter, 4, size - 4, NULL);
|
|
||||||
if (ofs < 0) {
|
|
||||||
// Assume the whole packet is present if end-of-stream
|
|
||||||
if (!is_eos)
|
|
||||||
break;
|
|
||||||
ofs = size;
|
|
||||||
}
|
|
||||||
buffer = gst_adapter_take_buffer(priv->adapter, ofs);
|
|
||||||
size -= ofs;
|
|
||||||
|
|
||||||
buf = GST_BUFFER_DATA(buffer);
|
|
||||||
buf_size = GST_BUFFER_SIZE(buffer);
|
|
||||||
status = decode_packet(decoder, buf, buf_size);
|
|
||||||
|
|
||||||
gst_buffer_unref(buffer);
|
|
||||||
} while (status == GST_VAAPI_DECODER_STATUS_SUCCESS);
|
|
||||||
|
|
||||||
if (is_eos && (status == GST_VAAPI_DECODER_STATUS_SUCCESS ||
|
|
||||||
status == GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA))
|
|
||||||
status = decode_sequence_end(decoder);
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
GstVaapiDecoderStatus
|
static GstVaapiDecoderStatus
|
||||||
gst_vaapi_decoder_mpeg2_decode(GstVaapiDecoder *base, GstBuffer *buffer)
|
ensure_decoder(GstVaapiDecoderMpeg2 *decoder)
|
||||||
{
|
{
|
||||||
GstVaapiDecoderMpeg2 * const decoder = GST_VAAPI_DECODER_MPEG2(base);
|
|
||||||
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
||||||
|
|
||||||
g_return_val_if_fail(priv->is_constructed,
|
g_return_val_if_fail(priv->is_constructed,
|
||||||
GST_VAAPI_DECODER_STATUS_ERROR_INIT_FAILED);
|
GST_VAAPI_DECODER_STATUS_ERROR_INIT_FAILED);
|
||||||
|
|
||||||
if (!priv->is_opened) {
|
if (!priv->is_opened) {
|
||||||
priv->is_opened = gst_vaapi_decoder_mpeg2_open(decoder, buffer);
|
priv->is_opened = gst_vaapi_decoder_mpeg2_open(decoder);
|
||||||
if (!priv->is_opened)
|
if (!priv->is_opened)
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
|
return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
|
||||||
}
|
}
|
||||||
return decode_buffer(decoder, buffer);
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstVaapiDecoderStatus
|
||||||
|
gst_vaapi_decoder_mpeg2_parse(GstVaapiDecoder *base_decoder,
|
||||||
|
GstAdapter *adapter, gboolean at_eos, GstVaapiDecoderUnit **unit_ptr)
|
||||||
|
{
|
||||||
|
GstVaapiDecoderMpeg2 * const decoder =
|
||||||
|
GST_VAAPI_DECODER_MPEG2(base_decoder);
|
||||||
|
GstVaapiDecoderUnit *unit = NULL;
|
||||||
|
GstVaapiDecoderStatus status;
|
||||||
|
guint32 start_code;
|
||||||
|
guint8 pkt_type, ext_type;
|
||||||
|
guint size, buf_size, flags = 0;
|
||||||
|
gint ofs;
|
||||||
|
|
||||||
|
status = ensure_decoder(decoder);
|
||||||
|
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
size = gst_adapter_available(adapter);
|
||||||
|
if (size < 4)
|
||||||
|
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
|
||||||
|
|
||||||
|
ofs = scan_for_start_code(adapter, 0, size, &start_code);
|
||||||
|
if (ofs < 0)
|
||||||
|
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
|
||||||
|
gst_adapter_flush(adapter, ofs);
|
||||||
|
size -= ofs;
|
||||||
|
|
||||||
|
ofs = G_UNLIKELY(size < 8) ? -1 :
|
||||||
|
scan_for_start_code(adapter, 4, size - 4, NULL);
|
||||||
|
if (ofs < 0) {
|
||||||
|
// Assume the whole packet is present if end-of-stream
|
||||||
|
if (!at_eos)
|
||||||
|
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
|
||||||
|
ofs = size;
|
||||||
|
}
|
||||||
|
buf_size = ofs;
|
||||||
|
|
||||||
|
unit = gst_vaapi_decoder_unit_new(buf_size);
|
||||||
|
if (!unit)
|
||||||
|
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
|
||||||
|
|
||||||
|
/* Check for start of new picture */
|
||||||
|
pkt_type = start_code & 0xff;
|
||||||
|
switch (pkt_type) {
|
||||||
|
case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
|
||||||
|
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
|
||||||
|
flags |= GST_VAAPI_DECODER_UNIT_FLAG_STREAM_END;
|
||||||
|
break;
|
||||||
|
case GST_MPEG_VIDEO_PACKET_USER_DATA:
|
||||||
|
flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
|
||||||
|
/* fall-through */
|
||||||
|
case GST_MPEG_VIDEO_PACKET_SEQUENCE:
|
||||||
|
case GST_MPEG_VIDEO_PACKET_GOP:
|
||||||
|
case GST_MPEG_VIDEO_PACKET_PICTURE:
|
||||||
|
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
|
||||||
|
break;
|
||||||
|
case GST_MPEG_VIDEO_PACKET_EXTENSION:
|
||||||
|
if (buf_size < 5)
|
||||||
|
break;
|
||||||
|
gst_adapter_copy(adapter, &ext_type, 4, 1);
|
||||||
|
switch (ext_type) {
|
||||||
|
case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
|
||||||
|
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (pkt_type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
|
||||||
|
pkt_type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX)
|
||||||
|
flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
GST_VAAPI_DECODER_UNIT_FLAG_SET(unit, flags);
|
||||||
|
|
||||||
|
*unit_ptr = unit;
|
||||||
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstVaapiDecoderStatus
|
||||||
|
gst_vaapi_decoder_mpeg2_decode(GstVaapiDecoder *base_decoder,
|
||||||
|
GstVaapiDecoderUnit *unit)
|
||||||
|
{
|
||||||
|
GstVaapiDecoderMpeg2 * const decoder =
|
||||||
|
GST_VAAPI_DECODER_MPEG2(base_decoder);
|
||||||
|
GstVaapiDecoderStatus status;
|
||||||
|
|
||||||
|
status = ensure_decoder(decoder);
|
||||||
|
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
unit->buffer = gst_buffer_create_sub(
|
||||||
|
GST_VAAPI_DECODER_CODEC_FRAME(decoder)->input_buffer,
|
||||||
|
unit->offset, unit->size);
|
||||||
|
if (!unit->buffer)
|
||||||
|
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
|
||||||
|
|
||||||
|
status = decode_buffer(decoder, unit->buffer);
|
||||||
|
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
||||||
|
return status;
|
||||||
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1156,6 +1196,7 @@ gst_vaapi_decoder_mpeg2_class_init(GstVaapiDecoderMpeg2Class *klass)
|
||||||
object_class->finalize = gst_vaapi_decoder_mpeg2_finalize;
|
object_class->finalize = gst_vaapi_decoder_mpeg2_finalize;
|
||||||
object_class->constructed = gst_vaapi_decoder_mpeg2_constructed;
|
object_class->constructed = gst_vaapi_decoder_mpeg2_constructed;
|
||||||
|
|
||||||
|
decoder_class->parse = gst_vaapi_decoder_mpeg2_parse;
|
||||||
decoder_class->decode = gst_vaapi_decoder_mpeg2_decode;
|
decoder_class->decode = gst_vaapi_decoder_mpeg2_decode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1173,7 +1214,6 @@ gst_vaapi_decoder_mpeg2_init(GstVaapiDecoderMpeg2 *decoder)
|
||||||
priv->hw_profile = GST_VAAPI_PROFILE_UNKNOWN;
|
priv->hw_profile = GST_VAAPI_PROFILE_UNKNOWN;
|
||||||
priv->profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
|
priv->profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
|
||||||
priv->current_picture = NULL;
|
priv->current_picture = NULL;
|
||||||
priv->adapter = NULL;
|
|
||||||
priv->is_constructed = FALSE;
|
priv->is_constructed = FALSE;
|
||||||
priv->is_opened = FALSE;
|
priv->is_opened = FALSE;
|
||||||
priv->has_seq_ext = FALSE;
|
priv->has_seq_ext = FALSE;
|
||||||
|
|
Loading…
Reference in a new issue