Exemplo n.º 1
0
GstVaapiDecoderStatus
gst_vaapi_decoder_vc1_decode(GstVaapiDecoder *base, GstBuffer *buffer)
{
    GstVaapiDecoderVC1 * const decoder = GST_VAAPI_DECODER_VC1(base);
    GstVaapiDecoderVC1Private * const priv = decoder->priv;
    GstVaapiDecoderStatus status;
    GstBuffer *codec_data;

    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_vc1_open(decoder, buffer);
        if (!priv->is_opened)
            return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;

        codec_data = GST_VAAPI_DECODER_CODEC_DATA(decoder);
        if (codec_data) {
            status = decode_codec_data(decoder, codec_data);
            if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
                return status;
        }
    }
    return decode_buffer(decoder, buffer);
}
Exemplo n.º 2
0
GstVaapiDecoderStatus
gst_vaapi_decoder_decode_codec_data (GstVaapiDecoder * decoder)
{
  GstVaapiDecoderClass *const klass = GST_VAAPI_DECODER_GET_CLASS (decoder);
  GstBuffer *const codec_data = GST_VAAPI_DECODER_CODEC_DATA (decoder);
  GstVaapiDecoderStatus status;
  GstMapInfo map_info;
  const guchar *buf;
  guint buf_size;

  if (!codec_data)
    return GST_VAAPI_DECODER_STATUS_SUCCESS;

  /* FIXME: add a meaningful error code? */
  if (!klass->decode_codec_data)
    return GST_VAAPI_DECODER_STATUS_SUCCESS;

  if (!gst_buffer_map (codec_data, &map_info, GST_MAP_READ)) {
    GST_ERROR ("failed to map buffer");
    return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
  }

  buf = map_info.data;
  buf_size = map_info.size;
  if (G_LIKELY (buf && buf_size > 0))
    status = klass->decode_codec_data (decoder, buf, buf_size);
  else
    status = GST_VAAPI_DECODER_STATUS_SUCCESS;
  gst_buffer_unmap (codec_data, &map_info);
  return status;
}
Exemplo n.º 3
0
static GstVaapiDecoderStatus
decode_buffer(GstVaapiDecoderVC1 *decoder, GstBuffer *buffer)
{
    GstVaapiDecoderVC1Private * const priv = decoder->priv;
    GstVaapiDecoderStatus status;
    GstVC1ParserResult result;
    GstVC1BDU ebdu;
    GstBuffer *codec_data;
    guchar *buf;
    guint buf_size, ofs;

    buf      = GST_BUFFER_DATA(buffer);
    buf_size = GST_BUFFER_SIZE(buffer);
    if (!buf && buf_size == 0)
        return decode_sequence_end(decoder);

    gst_buffer_ref(buffer);
    gst_adapter_push(priv->adapter, buffer);

    /* Assume demuxer sends out plain frames if codec-data */
    codec_data = GST_VAAPI_DECODER_CODEC_DATA(decoder);
    if (codec_data && codec_data != buffer) {
        ebdu.type      = GST_VC1_FRAME;
        ebdu.size      = buf_size;
        ebdu.sc_offset = 0;
        ebdu.offset    = 0;
        ebdu.data      = buf;
        status = decode_ebdu(decoder, &ebdu);

        if (gst_adapter_available(priv->adapter) >= buf_size)
            gst_adapter_flush(priv->adapter, buf_size);
        return status;
    }

    if (priv->sub_buffer) {
        buffer = gst_buffer_merge(priv->sub_buffer, buffer);
        if (!buffer)
            return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
        gst_buffer_unref(priv->sub_buffer);
        priv->sub_buffer = NULL;
    }

    buf      = GST_BUFFER_DATA(buffer);
    buf_size = GST_BUFFER_SIZE(buffer);
    ofs      = 0;
    do {
        result = gst_vc1_identify_next_bdu(
            buf + ofs,
            buf_size - ofs,
            &ebdu
        );
        status = get_status(result);

        if (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA) {
            priv->sub_buffer = gst_buffer_create_sub(buffer, ofs, buf_size - ofs);
            break;
        }
        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
            break;

        ofs += ebdu.offset + ebdu.size;
        if (gst_adapter_available(priv->adapter) >= ebdu.offset)
            gst_adapter_flush(priv->adapter, ebdu.offset);

        status = decode_ebdu(decoder, &ebdu);
        if (gst_adapter_available(priv->adapter) >= ebdu.size)
            gst_adapter_flush(priv->adapter, ebdu.size);
    } while (status == GST_VAAPI_DECODER_STATUS_SUCCESS);
    return status;
}
static gboolean
gst_vaapi_decoder_ffmpeg_open(GstVaapiDecoderFfmpeg *ffdecoder, GstBuffer *buffer)
{
    GstVaapiDecoderFfmpegPrivate * const priv = ffdecoder->priv;
    GstVaapiDisplay * const display = GST_VAAPI_DECODER_DISPLAY(ffdecoder);
    GstBuffer * const codec_data = GST_VAAPI_DECODER_CODEC_DATA(ffdecoder);
    GstVaapiCodec codec = GST_VAAPI_DECODER_CODEC(ffdecoder);
    enum CodecID codec_id;
    AVCodec *ffcodec;
    gboolean try_parser, need_parser;
    int ret;

    gst_vaapi_decoder_ffmpeg_close(ffdecoder);

    if (codec_data) {
        const guchar *data = GST_BUFFER_DATA(codec_data);
        const guint   size = GST_BUFFER_SIZE(codec_data);
        if (!set_codec_data(priv->avctx, data, size))
            return FALSE;
    }

    codec_id = get_codec_id_from_codec(codec);
    if (codec_id == CODEC_ID_NONE)
        return FALSE;

    ffcodec = avcodec_find_decoder(codec_id);
    if (!ffcodec)
        return FALSE;

    switch (codec_id) {
    case CODEC_ID_H264:
        /* For AVC1 formats, sequence headers are in extradata and
           input encoded buffers represent the whole NAL unit */
        try_parser  = priv->avctx->extradata_size == 0;
        need_parser = try_parser;
        break;
    case CODEC_ID_WMV3:
        /* There is no WMV3 parser in FFmpeg */
        try_parser  = FALSE;
        need_parser = FALSE;
        break;
    case CODEC_ID_VC1:
        /* For VC-1, sequence headers ae in extradata and input encoded
           buffers represent the whole slice */
        try_parser  = priv->avctx->extradata_size == 0;
        need_parser = FALSE;
        break;
    default:
        try_parser  = TRUE;
        need_parser = TRUE;
        break;
    }

    if (try_parser) {
        priv->pctx = av_parser_init(codec_id);
        if (!priv->pctx && need_parser)
            return FALSE;
    }

    /* XXX: av_find_stream_info() does this and some codecs really
       want hard an extradata buffer for initialization (e.g. VC-1) */
    if (!priv->avctx->extradata && priv->pctx && priv->pctx->parser->split) {
        const guchar *buf = GST_BUFFER_DATA(buffer);
        guint buf_size = GST_BUFFER_SIZE(buffer);
        buf_size = priv->pctx->parser->split(priv->avctx, buf, buf_size);
        if (buf_size > 0 && !set_codec_data(priv->avctx, buf, buf_size))
            return FALSE;
    }

    if (priv->pctx && !need_parser) {
        av_parser_close(priv->pctx);
        priv->pctx = NULL;
    }

    /* Use size information from the demuxer, whenever available */
    priv->avctx->coded_width  = GST_VAAPI_DECODER_WIDTH(ffdecoder);
    priv->avctx->coded_height = GST_VAAPI_DECODER_HEIGHT(ffdecoder);

    GST_VAAPI_DISPLAY_LOCK(display);
    ret = avcodec_open(priv->avctx, ffcodec);
    GST_VAAPI_DISPLAY_UNLOCK(display);
    if (ret < 0)
        return FALSE;
    return TRUE;
}