mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-10 03:19:40 +00:00
mpeg2: add codec specific decoder unit.
Introduce new GstVaapiDecoderUnitMpeg2 object, which holds the standard GstMpegVideoPacket and additional parsed header info. Besides, we now parse as early as in the _parse() function so that to avoid un-necessary creation of sub-buffers in _decode() for video packets that are not slices.
This commit is contained in:
parent
63a7e42484
commit
549b5a9389
1 changed files with 239 additions and 127 deletions
|
@ -61,7 +61,10 @@ G_DEFINE_TYPE(GstVaapiDecoderMpeg2,
|
||||||
} \
|
} \
|
||||||
} G_STMT_END
|
} G_STMT_END
|
||||||
|
|
||||||
/* PTS Generator */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
/* --- PTS Generator --- */
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
typedef struct _PTSGenerator PTSGenerator;
|
typedef struct _PTSGenerator PTSGenerator;
|
||||||
struct _PTSGenerator {
|
struct _PTSGenerator {
|
||||||
GstClockTime gop_pts; // Current GOP PTS
|
GstClockTime gop_pts; // Current GOP PTS
|
||||||
|
@ -164,6 +167,48 @@ pts_eval(PTSGenerator *tsg, GstClockTime pic_pts, guint pic_tsn)
|
||||||
return pts;
|
return pts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
/* --- MPEG-2 Decoder Units --- */
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
typedef struct _GstVaapiDecoderUnitMpeg2 GstVaapiDecoderUnitMpeg2;
|
||||||
|
struct _GstVaapiDecoderUnitMpeg2 {
|
||||||
|
GstVaapiDecoderUnit base;
|
||||||
|
GstMpegVideoPacket packet;
|
||||||
|
guint8 extension_type; /* for Extension packets */
|
||||||
|
union {
|
||||||
|
GstMpegVideoSequenceHdr seq_hdr;
|
||||||
|
GstMpegVideoSequenceExt seq_ext;
|
||||||
|
GstMpegVideoGop gop;
|
||||||
|
GstMpegVideoQuantMatrixExt quant_matrix;
|
||||||
|
GstMpegVideoPictureHdr pic_hdr;
|
||||||
|
GstMpegVideoPictureExt pic_ext;
|
||||||
|
} data;
|
||||||
|
};
|
||||||
|
|
||||||
|
static GstVaapiDecoderUnitMpeg2 *
|
||||||
|
gst_vaapi_decoder_unit_mpeg2_new(guint size)
|
||||||
|
{
|
||||||
|
GstVaapiDecoderUnitMpeg2 *unit;
|
||||||
|
|
||||||
|
static const GstVaapiMiniObjectClass GstVaapiDecoderUnitMpeg2Class = {
|
||||||
|
sizeof(GstVaapiDecoderUnitMpeg2),
|
||||||
|
(GDestroyNotify)gst_vaapi_decoder_unit_finalize
|
||||||
|
};
|
||||||
|
|
||||||
|
unit = (GstVaapiDecoderUnitMpeg2 *)
|
||||||
|
gst_vaapi_mini_object_new(&GstVaapiDecoderUnitMpeg2Class);
|
||||||
|
if (!unit)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
gst_vaapi_decoder_unit_init(&unit->base, size);
|
||||||
|
return unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
/* --- MPEG-2 Decoder --- */
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
struct _GstVaapiDecoderMpeg2Private {
|
struct _GstVaapiDecoderMpeg2Private {
|
||||||
GstVaapiProfile profile;
|
GstVaapiProfile profile;
|
||||||
GstVaapiProfile hw_profile;
|
GstVaapiProfile hw_profile;
|
||||||
|
@ -492,16 +537,26 @@ decode_current_picture(GstVaapiDecoderMpeg2 *decoder)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstVaapiDecoderStatus
|
static GstVaapiDecoderStatus
|
||||||
decode_sequence(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
|
parse_sequence(GstVaapiDecoderUnitMpeg2 *unit)
|
||||||
|
{
|
||||||
|
GstMpegVideoPacket * const packet = &unit->packet;
|
||||||
|
|
||||||
|
if (!gst_mpeg_video_parse_sequence_header(&unit->data.seq_hdr,
|
||||||
|
packet->data, packet->size, packet->offset)) {
|
||||||
|
GST_ERROR("failed to parse sequence header");
|
||||||
|
return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
|
||||||
|
}
|
||||||
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstVaapiDecoderStatus
|
||||||
|
decode_sequence(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnitMpeg2 *unit)
|
||||||
{
|
{
|
||||||
GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
|
GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
|
||||||
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
||||||
GstMpegVideoSequenceHdr * const seq_hdr = &priv->seq_hdr;
|
GstMpegVideoSequenceHdr * const seq_hdr = &priv->seq_hdr;
|
||||||
|
|
||||||
if (!gst_mpeg_video_parse_sequence_header(seq_hdr, buf, buf_size, 4)) {
|
*seq_hdr = unit->data.seq_hdr;
|
||||||
GST_ERROR("failed to parse sequence header");
|
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
|
|
||||||
}
|
|
||||||
|
|
||||||
priv->fps_n = seq_hdr->fps_n;
|
priv->fps_n = seq_hdr->fps_n;
|
||||||
priv->fps_d = seq_hdr->fps_d;
|
priv->fps_d = seq_hdr->fps_d;
|
||||||
|
@ -522,7 +577,21 @@ decode_sequence(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstVaapiDecoderStatus
|
static GstVaapiDecoderStatus
|
||||||
decode_sequence_ext(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
|
parse_sequence_ext(GstVaapiDecoderUnitMpeg2 *unit)
|
||||||
|
{
|
||||||
|
GstMpegVideoPacket * const packet = &unit->packet;
|
||||||
|
|
||||||
|
if (!gst_mpeg_video_parse_sequence_extension(&unit->data.seq_ext,
|
||||||
|
packet->data, packet->size, packet->offset)) {
|
||||||
|
GST_ERROR("failed to parse sequence-extension");
|
||||||
|
return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
|
||||||
|
}
|
||||||
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstVaapiDecoderStatus
|
||||||
|
decode_sequence_ext(GstVaapiDecoderMpeg2 *decoder,
|
||||||
|
GstVaapiDecoderUnitMpeg2 *unit)
|
||||||
{
|
{
|
||||||
GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
|
GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
|
||||||
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
||||||
|
@ -531,10 +600,8 @@ decode_sequence_ext(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
|
||||||
GstVaapiProfile profile;
|
GstVaapiProfile profile;
|
||||||
guint width, height;
|
guint width, height;
|
||||||
|
|
||||||
if (!gst_mpeg_video_parse_sequence_extension(seq_ext, buf, buf_size, 4)) {
|
*seq_ext = unit->data.seq_ext;
|
||||||
GST_ERROR("failed to parse sequence-extension");
|
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
|
|
||||||
}
|
|
||||||
priv->has_seq_ext = TRUE;
|
priv->has_seq_ext = TRUE;
|
||||||
priv->progressive_sequence = seq_ext->progressive;
|
priv->progressive_sequence = seq_ext->progressive;
|
||||||
gst_vaapi_decoder_set_interlaced(base_decoder, !priv->progressive_sequence);
|
gst_vaapi_decoder_set_interlaced(base_decoder, !priv->progressive_sequence);
|
||||||
|
@ -595,40 +662,58 @@ decode_sequence_end(GstVaapiDecoderMpeg2 *decoder)
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
|
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
|
||||||
|
|
||||||
gst_vaapi_dpb_flush(priv->dpb);
|
gst_vaapi_dpb_flush(priv->dpb);
|
||||||
return GST_VAAPI_DECODER_STATUS_END_OF_STREAM;
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstVaapiDecoderStatus
|
static GstVaapiDecoderStatus
|
||||||
decode_quant_matrix_ext(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
|
parse_quant_matrix_ext(GstVaapiDecoderUnitMpeg2 *unit)
|
||||||
{
|
{
|
||||||
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
GstMpegVideoPacket * const packet = &unit->packet;
|
||||||
GstMpegVideoQuantMatrixExt * const quant_matrix_ext = &priv->quant_matrix_ext;
|
|
||||||
|
|
||||||
if (!gst_mpeg_video_parse_quant_matrix_extension(quant_matrix_ext, buf, buf_size, 4)) {
|
if (!gst_mpeg_video_parse_quant_matrix_extension(&unit->data.quant_matrix,
|
||||||
|
packet->data, packet->size, packet->offset)) {
|
||||||
GST_ERROR("failed to parse quant-matrix-extension");
|
GST_ERROR("failed to parse quant-matrix-extension");
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
|
return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
|
||||||
}
|
}
|
||||||
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstVaapiDecoderStatus
|
||||||
|
decode_quant_matrix_ext(GstVaapiDecoderMpeg2 *decoder,
|
||||||
|
GstVaapiDecoderUnitMpeg2 *unit)
|
||||||
|
{
|
||||||
|
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
||||||
|
|
||||||
|
priv->quant_matrix_ext = unit->data.quant_matrix;
|
||||||
priv->has_quant_matrix_ext = TRUE;
|
priv->has_quant_matrix_ext = TRUE;
|
||||||
priv->quant_matrix_changed = TRUE;
|
priv->quant_matrix_changed = TRUE;
|
||||||
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstVaapiDecoderStatus
|
static GstVaapiDecoderStatus
|
||||||
decode_gop(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
|
parse_gop(GstVaapiDecoderUnitMpeg2 *unit)
|
||||||
{
|
{
|
||||||
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
GstMpegVideoPacket * const packet = &unit->packet;
|
||||||
GstMpegVideoGop gop;
|
|
||||||
|
|
||||||
if (!gst_mpeg_video_parse_gop(&gop, buf, buf_size, 4)) {
|
if (!gst_mpeg_video_parse_gop(&unit->data.gop,
|
||||||
|
packet->data, packet->size, packet->offset)) {
|
||||||
GST_ERROR("failed to parse GOP");
|
GST_ERROR("failed to parse GOP");
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
|
return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
|
||||||
}
|
}
|
||||||
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
priv->closed_gop = gop.closed_gop;
|
static GstVaapiDecoderStatus
|
||||||
priv->broken_link = gop.broken_link;
|
decode_gop(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnitMpeg2 *unit)
|
||||||
|
{
|
||||||
|
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
||||||
|
GstMpegVideoGop * const gop = &unit->data.gop;
|
||||||
|
|
||||||
|
priv->closed_gop = gop->closed_gop;
|
||||||
|
priv->broken_link = gop->broken_link;
|
||||||
|
|
||||||
GST_DEBUG("GOP %02u:%02u:%02u:%02u (closed_gop %d, broken_link %d)",
|
GST_DEBUG("GOP %02u:%02u:%02u:%02u (closed_gop %d, broken_link %d)",
|
||||||
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_sync(&priv->tsg, GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts);
|
pts_sync(&priv->tsg, GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts);
|
||||||
|
@ -636,13 +721,28 @@ decode_gop(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstVaapiDecoderStatus
|
static GstVaapiDecoderStatus
|
||||||
decode_picture(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
|
parse_picture(GstVaapiDecoderUnitMpeg2 *unit)
|
||||||
|
{
|
||||||
|
GstMpegVideoPacket * const packet = &unit->packet;
|
||||||
|
|
||||||
|
if (!gst_mpeg_video_parse_picture_header(&unit->data.pic_hdr,
|
||||||
|
packet->data, packet->size, packet->offset)) {
|
||||||
|
GST_ERROR("failed to parse picture header");
|
||||||
|
return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
|
||||||
|
}
|
||||||
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstVaapiDecoderStatus
|
||||||
|
decode_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnitMpeg2 *unit)
|
||||||
{
|
{
|
||||||
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
||||||
GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr;
|
GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr;
|
||||||
GstVaapiPicture *picture;
|
GstVaapiPicture *picture;
|
||||||
GstVaapiDecoderStatus status;
|
GstVaapiDecoderStatus status;
|
||||||
|
|
||||||
|
*pic_hdr = unit->data.pic_hdr;
|
||||||
|
|
||||||
status = ensure_context(decoder);
|
status = ensure_context(decoder);
|
||||||
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
|
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
|
||||||
GST_ERROR("failed to reset context");
|
GST_ERROR("failed to reset context");
|
||||||
|
@ -677,10 +777,6 @@ decode_picture(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gst_mpeg_video_parse_picture_header(pic_hdr, buf, buf_size, 4)) {
|
|
||||||
GST_ERROR("failed to parse picture header");
|
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
|
|
||||||
}
|
|
||||||
priv->has_pic_ext = FALSE;
|
priv->has_pic_ext = FALSE;
|
||||||
|
|
||||||
switch (pic_hdr->pic_type) {
|
switch (pic_hdr->pic_type) {
|
||||||
|
@ -704,20 +800,32 @@ decode_picture(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
|
||||||
picture->pts = pts_eval(&priv->tsg,
|
picture->pts = pts_eval(&priv->tsg,
|
||||||
GST_VAAPI_DECODER_CODEC_FRAME(decoder)->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 GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstVaapiDecoderStatus
|
static GstVaapiDecoderStatus
|
||||||
decode_picture_ext(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
|
parse_picture_ext(GstVaapiDecoderUnitMpeg2 *unit)
|
||||||
|
{
|
||||||
|
GstMpegVideoPacket * const packet = &unit->packet;
|
||||||
|
|
||||||
|
if (!gst_mpeg_video_parse_picture_extension(&unit->data.pic_ext,
|
||||||
|
packet->data, packet->size, packet->offset)) {
|
||||||
|
GST_ERROR("failed to parse picture-extension");
|
||||||
|
return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
|
||||||
|
}
|
||||||
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstVaapiDecoderStatus
|
||||||
|
decode_picture_ext(GstVaapiDecoderMpeg2 *decoder,
|
||||||
|
GstVaapiDecoderUnitMpeg2 *unit)
|
||||||
{
|
{
|
||||||
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
||||||
GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext;
|
GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext;
|
||||||
GstVaapiPicture * const picture = priv->current_picture;
|
GstVaapiPicture * const picture = priv->current_picture;
|
||||||
|
|
||||||
if (!gst_mpeg_video_parse_picture_extension(pic_ext, buf, buf_size, 4)) {
|
*pic_ext = unit->data.pic_ext;
|
||||||
GST_ERROR("failed to parse picture-extension");
|
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
|
|
||||||
}
|
|
||||||
priv->has_pic_ext = TRUE;
|
priv->has_pic_ext = TRUE;
|
||||||
|
|
||||||
if (priv->progressive_sequence && !pic_ext->progressive_frame) {
|
if (priv->progressive_sequence && !pic_ext->progressive_frame) {
|
||||||
|
@ -855,17 +963,14 @@ fill_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstVaapiDecoderStatus
|
static GstVaapiDecoderStatus
|
||||||
decode_slice(
|
decode_slice(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnitMpeg2 *unit)
|
||||||
GstVaapiDecoderMpeg2 *decoder,
|
|
||||||
int slice_no,
|
|
||||||
guchar *buf,
|
|
||||||
guint buf_size
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
||||||
GstVaapiPicture * const picture = priv->current_picture;
|
GstVaapiPicture * const picture = priv->current_picture;
|
||||||
GstVaapiSlice *slice;
|
GstVaapiSlice *slice;
|
||||||
VASliceParameterBufferMPEG2 *slice_param;
|
VASliceParameterBufferMPEG2 *slice_param;
|
||||||
|
GstMpegVideoPacket * const packet = &unit->packet;
|
||||||
|
const gint slice_no = packet->type - GST_MPEG_VIDEO_PACKET_SLICE_MIN;
|
||||||
GstBitReader br;
|
GstBitReader br;
|
||||||
gint mb_x, mb_y, mb_inc;
|
gint mb_x, mb_y, mb_inc;
|
||||||
guint macroblock_offset;
|
guint macroblock_offset;
|
||||||
|
@ -874,12 +979,24 @@ decode_slice(
|
||||||
guint8 intra_slice = 0;
|
guint8 intra_slice = 0;
|
||||||
guint8 extra_bit_slice, junk8;
|
guint8 extra_bit_slice, junk8;
|
||||||
|
|
||||||
GST_DEBUG("slice %d @ %p, %u bytes)", slice_no, buf, buf_size);
|
GST_DEBUG("slice %d (%u bytes)", slice_no, packet->size);
|
||||||
|
|
||||||
|
if (!picture)
|
||||||
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
|
|
||||||
if (picture->slices->len == 0 && !fill_picture(decoder, picture))
|
if (picture->slices->len == 0 && !fill_picture(decoder, picture))
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
|
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
|
||||||
|
|
||||||
slice = GST_VAAPI_SLICE_NEW(MPEG2, decoder, buf, buf_size);
|
unit->base.buffer = gst_buffer_create_sub(
|
||||||
|
GST_VAAPI_DECODER_CODEC_FRAME(decoder)->input_buffer,
|
||||||
|
unit->base.offset, unit->base.size);
|
||||||
|
if (!unit->base.buffer) {
|
||||||
|
GST_ERROR("failed to allocate slice data");
|
||||||
|
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
slice = GST_VAAPI_SLICE_NEW(MPEG2, decoder,
|
||||||
|
GST_BUFFER_DATA(unit->base.buffer), packet->size);
|
||||||
if (!slice) {
|
if (!slice) {
|
||||||
GST_ERROR("failed to allocate slice");
|
GST_ERROR("failed to allocate slice");
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
|
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
|
||||||
|
@ -887,7 +1004,7 @@ decode_slice(
|
||||||
gst_vaapi_picture_add_slice(picture, slice);
|
gst_vaapi_picture_add_slice(picture, slice);
|
||||||
|
|
||||||
/* Parse slice */
|
/* Parse slice */
|
||||||
gst_bit_reader_init(&br, buf, buf_size);
|
gst_bit_reader_init(&br, GST_BUFFER_DATA(unit->base.buffer), packet->size);
|
||||||
SKIP(&br, 32); /* slice_start_code */
|
SKIP(&br, 32); /* slice_start_code */
|
||||||
if (priv->height > 2800)
|
if (priv->height > 2800)
|
||||||
READ_UINT8(&br, slice_vertical_position_extension, 3);
|
READ_UINT8(&br, slice_vertical_position_extension, 3);
|
||||||
|
@ -942,73 +1059,55 @@ scan_for_start_code(GstAdapter *adapter, guint ofs, guint size, guint32 *scp)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstVaapiDecoderStatus
|
static GstVaapiDecoderStatus
|
||||||
decode_packet(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
|
decode_unit(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnitMpeg2 *unit)
|
||||||
{
|
{
|
||||||
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
||||||
|
const GstMpegVideoPacketTypeCode type = unit->packet.type;
|
||||||
GstVaapiDecoderStatus status;
|
GstVaapiDecoderStatus status;
|
||||||
guchar type;
|
|
||||||
|
|
||||||
/* The packet defined by buf and buf_size contains the start code */
|
|
||||||
type = buf[3];
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case GST_MPEG_VIDEO_PACKET_PICTURE:
|
case GST_MPEG_VIDEO_PACKET_PICTURE:
|
||||||
if (!priv->width || !priv->height)
|
if (!priv->width || !priv->height)
|
||||||
goto unknown_picture_size;
|
goto unknown_picture_size;
|
||||||
status = decode_picture(decoder, buf, buf_size);
|
status = decode_picture(decoder, unit);
|
||||||
break;
|
break;
|
||||||
case GST_MPEG_VIDEO_PACKET_SEQUENCE:
|
case GST_MPEG_VIDEO_PACKET_SEQUENCE:
|
||||||
status = decode_sequence(decoder, buf, buf_size);
|
status = decode_sequence(decoder, unit);
|
||||||
break;
|
break;
|
||||||
case GST_MPEG_VIDEO_PACKET_EXTENSION: {
|
case GST_MPEG_VIDEO_PACKET_EXTENSION:
|
||||||
const guchar id = buf[4] >> 4;
|
switch (unit->extension_type) {
|
||||||
switch (id) {
|
|
||||||
case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
|
case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
|
||||||
status = decode_sequence_ext(decoder, buf, buf_size);
|
status = decode_sequence_ext(decoder, unit);
|
||||||
break;
|
break;
|
||||||
case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
|
case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
|
||||||
status = decode_quant_matrix_ext(decoder, buf, buf_size);
|
status = decode_quant_matrix_ext(decoder, unit);
|
||||||
break;
|
break;
|
||||||
case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
|
case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
|
||||||
if (!priv->width || !priv->height)
|
if (!priv->width || !priv->height)
|
||||||
goto unknown_picture_size;
|
goto unknown_picture_size;
|
||||||
status = decode_picture_ext(decoder, buf, buf_size);
|
status = decode_picture_ext(decoder, unit);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// Ignore unknown start-code extensions
|
// Ignore unknown start-code extensions
|
||||||
GST_WARNING("unsupported start code extension (0x%02x)", id);
|
GST_WARNING("unsupported packet extension type 0x%02x",
|
||||||
|
unit->extension_type);
|
||||||
status = GST_VAAPI_DECODER_STATUS_SUCCESS;
|
status = GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
|
case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
|
||||||
status = decode_sequence_end(decoder);
|
status = decode_sequence_end(decoder);
|
||||||
break;
|
break;
|
||||||
case GST_MPEG_VIDEO_PACKET_GOP:
|
case GST_MPEG_VIDEO_PACKET_GOP:
|
||||||
status = decode_gop(decoder, buf, buf_size);
|
status = decode_gop(decoder, unit);
|
||||||
break;
|
|
||||||
case GST_MPEG_VIDEO_PACKET_USER_DATA:
|
|
||||||
// Ignore user-data packets
|
|
||||||
status = GST_VAAPI_DECODER_STATUS_SUCCESS;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
|
if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
|
||||||
type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
|
type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
|
||||||
if (!priv->current_picture)
|
status = decode_slice(decoder, unit);
|
||||||
goto undefined_picture;
|
|
||||||
status = decode_slice(
|
|
||||||
decoder,
|
|
||||||
type - GST_MPEG_VIDEO_PACKET_SLICE_MIN,
|
|
||||||
buf, buf_size
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (type >= 0xb9 && type <= 0xff) {
|
GST_WARNING("unsupported packet type 0x%02x", type);
|
||||||
// Ignore system start codes (PES headers)
|
|
||||||
status = GST_VAAPI_DECODER_STATUS_SUCCESS;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
GST_WARNING("unsupported start code (0x%02x)", type);
|
|
||||||
status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
|
status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1019,28 +1118,6 @@ unknown_picture_size:
|
||||||
// i.e. missing sequence headers, or not parsed correctly
|
// i.e. missing sequence headers, or not parsed correctly
|
||||||
GST_WARNING("failed to parse picture of unknown size");
|
GST_WARNING("failed to parse picture of unknown size");
|
||||||
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
|
|
||||||
undefined_picture:
|
|
||||||
// Ignore packet while picture is undefined
|
|
||||||
// i.e. missing picture headers, or not parsed correctly
|
|
||||||
GST_WARNING("failed to parse slice with undefined picture");
|
|
||||||
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GstVaapiDecoderStatus
|
|
||||||
decode_buffer(GstVaapiDecoderMpeg2 *decoder, GstBuffer *buffer)
|
|
||||||
{
|
|
||||||
GstVaapiDecoderStatus status;
|
|
||||||
guchar *buf;
|
|
||||||
guint buf_size;
|
|
||||||
|
|
||||||
buf = GST_BUFFER_DATA(buffer);
|
|
||||||
buf_size = GST_BUFFER_SIZE(buffer);
|
|
||||||
|
|
||||||
status = decode_packet(decoder, buf, buf_size);
|
|
||||||
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
|
||||||
return status;
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstVaapiDecoderStatus
|
static GstVaapiDecoderStatus
|
||||||
|
@ -1065,11 +1142,12 @@ gst_vaapi_decoder_mpeg2_parse(GstVaapiDecoder *base_decoder,
|
||||||
{
|
{
|
||||||
GstVaapiDecoderMpeg2 * const decoder =
|
GstVaapiDecoderMpeg2 * const decoder =
|
||||||
GST_VAAPI_DECODER_MPEG2(base_decoder);
|
GST_VAAPI_DECODER_MPEG2(base_decoder);
|
||||||
GstVaapiDecoderUnit *unit = NULL;
|
GstVaapiDecoderUnitMpeg2 *unit;
|
||||||
GstVaapiDecoderStatus status;
|
GstVaapiDecoderStatus status;
|
||||||
|
GstMpegVideoPacket *packet;
|
||||||
|
const guchar *buf;
|
||||||
guint32 start_code;
|
guint32 start_code;
|
||||||
guint8 pkt_type, ext_type;
|
guint size, buf_size, flags;
|
||||||
guint size, buf_size, flags = 0;
|
|
||||||
gint ofs;
|
gint ofs;
|
||||||
|
|
||||||
status = ensure_decoder(decoder);
|
status = ensure_decoder(decoder);
|
||||||
|
@ -1096,13 +1174,62 @@ gst_vaapi_decoder_mpeg2_parse(GstVaapiDecoder *base_decoder,
|
||||||
}
|
}
|
||||||
buf_size = ofs;
|
buf_size = ofs;
|
||||||
|
|
||||||
unit = gst_vaapi_decoder_unit_new(buf_size);
|
buf = gst_adapter_peek(adapter, buf_size);
|
||||||
|
if (!buf)
|
||||||
|
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
|
||||||
|
|
||||||
|
unit = gst_vaapi_decoder_unit_mpeg2_new(buf_size);
|
||||||
if (!unit)
|
if (!unit)
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
|
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
|
||||||
|
|
||||||
|
packet = &unit->packet;
|
||||||
|
packet->data = buf;
|
||||||
|
packet->size = buf_size;
|
||||||
|
packet->offset = 4;
|
||||||
|
packet->type = start_code & 0xff;
|
||||||
|
|
||||||
|
/* Parse data */
|
||||||
|
switch (packet->type) {
|
||||||
|
case GST_MPEG_VIDEO_PACKET_SEQUENCE:
|
||||||
|
status = parse_sequence(unit);
|
||||||
|
break;
|
||||||
|
case GST_MPEG_VIDEO_PACKET_GOP:
|
||||||
|
status = parse_gop(unit);
|
||||||
|
break;
|
||||||
|
case GST_MPEG_VIDEO_PACKET_PICTURE:
|
||||||
|
status = parse_picture(unit);
|
||||||
|
break;
|
||||||
|
case GST_MPEG_VIDEO_PACKET_EXTENSION:
|
||||||
|
if (G_UNLIKELY(buf_size < 5)) {
|
||||||
|
status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
unit->extension_type = buf[4] >> 4;
|
||||||
|
switch (unit->extension_type) {
|
||||||
|
case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
|
||||||
|
status = parse_sequence_ext(unit);
|
||||||
|
break;
|
||||||
|
case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
|
||||||
|
status = parse_quant_matrix_ext(unit);
|
||||||
|
break;
|
||||||
|
case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
|
||||||
|
status = parse_picture_ext(unit);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
status = GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
status = GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
/* Check for start of new picture */
|
/* Check for start of new picture */
|
||||||
pkt_type = start_code & 0xff;
|
flags = 0;
|
||||||
switch (pkt_type) {
|
switch (packet->type) {
|
||||||
case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
|
case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
|
||||||
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
|
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
|
||||||
flags |= GST_VAAPI_DECODER_UNIT_FLAG_STREAM_END;
|
flags |= GST_VAAPI_DECODER_UNIT_FLAG_STREAM_END;
|
||||||
|
@ -1115,25 +1242,20 @@ gst_vaapi_decoder_mpeg2_parse(GstVaapiDecoder *base_decoder,
|
||||||
case GST_MPEG_VIDEO_PACKET_PICTURE:
|
case GST_MPEG_VIDEO_PACKET_PICTURE:
|
||||||
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
|
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
|
||||||
break;
|
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:
|
default:
|
||||||
if (pkt_type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
|
if (packet->type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
|
||||||
pkt_type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX)
|
packet->type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX)
|
||||||
flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
|
flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
|
||||||
|
|
||||||
|
// Ignore system start codes (PES headers)
|
||||||
|
else if (packet->type >= 0xb9 && packet->type <= 0xff)
|
||||||
|
flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
GST_VAAPI_DECODER_UNIT_FLAG_SET(unit, flags);
|
GST_VAAPI_DECODER_UNIT_FLAG_SET(unit, flags);
|
||||||
|
|
||||||
*unit_ptr = unit;
|
unit->packet.data = NULL;
|
||||||
|
*unit_ptr = &unit->base;
|
||||||
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1148,17 +1270,7 @@ gst_vaapi_decoder_mpeg2_decode(GstVaapiDecoder *base_decoder,
|
||||||
status = ensure_decoder(decoder);
|
status = ensure_decoder(decoder);
|
||||||
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
||||||
return status;
|
return status;
|
||||||
|
return decode_unit(decoder, (GstVaapiDecoderUnitMpeg2 *)unit);
|
||||||
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
|
||||||
|
|
Loading…
Reference in a new issue