mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-06 23:48:53 +00:00
Drop FFmpeg-based decoders.
GStreamer codecparsers-based decoders are the only supported decoders now. Though, FFmpeg decoders are still available in gstreamer-vaapi 0.3.x series.
This commit is contained in:
parent
7689569016
commit
7f47ac3bea
11 changed files with 5 additions and 944 deletions
6
NEWS
6
NEWS
|
@ -1,10 +1,10 @@
|
||||||
gst-vaapi NEWS -- summary of changes. 2012-07-DD
|
gst-vaapi NEWS -- summary of changes. 2012-08-DD
|
||||||
Copyright (C) 2010-2011 Splitted-Desktop Systems
|
Copyright (C) 2010-2011 Splitted-Desktop Systems
|
||||||
Copyright (C) 2011-2012 Intel Corporation
|
Copyright (C) 2011-2012 Intel Corporation
|
||||||
Copyright (C) 2011 Collabora
|
Copyright (C) 2011 Collabora
|
||||||
|
|
||||||
Version 0.3.8 - DD.Jul.2012
|
Version 0.4.0 - DD.Aug.2012
|
||||||
* Disable FFmpeg-based decoders by default
|
* Drop FFmpeg-based decoders
|
||||||
|
|
||||||
Version 0.3.7 - 26.Jun.2012
|
Version 0.3.7 - 26.Jun.2012
|
||||||
* Fix vaapidecode to report unsupported codec profiles
|
* Fix vaapidecode to report unsupported codec profiles
|
||||||
|
|
30
configure.ac
30
configure.ac
|
@ -113,11 +113,6 @@ AC_ARG_ENABLE(vaapisink-glx,
|
||||||
[enable OpenGL/X11 to vaapisink @<:@default=yes@:>@]),
|
[enable OpenGL/X11 to vaapisink @<:@default=yes@:>@]),
|
||||||
[], [enable_vaapisink_glx="no"])
|
[], [enable_vaapisink_glx="no"])
|
||||||
|
|
||||||
AC_ARG_ENABLE(ffmpeg,
|
|
||||||
AS_HELP_STRING([--enable-ffmpeg],
|
|
||||||
[enable bitstream parsing from FFmpeg @<:@default=no@:>@]),
|
|
||||||
[], [enable_ffmpeg="no"])
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(codecparsers,
|
AC_ARG_ENABLE(codecparsers,
|
||||||
AS_HELP_STRING([--enable-codecparsers],
|
AS_HELP_STRING([--enable-codecparsers],
|
||||||
[enable adhoc bitstream parsers from GStreamer @<:@default=yes@:>@]),
|
[enable adhoc bitstream parsers from GStreamer @<:@default=yes@:>@]),
|
||||||
|
@ -446,29 +441,9 @@ else
|
||||||
USE_VAAPISINK_GLX=0
|
USE_VAAPISINK_GLX=0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl Check for FFmpeg
|
if test "$enable_codecparsers" = "no"; then
|
||||||
USE_FFMPEG=0
|
AC_MSG_ERROR([Found no suitable GStreamer bitstream parsers])
|
||||||
if test "$enable_ffmpeg" = "yes"; then
|
|
||||||
PKG_CHECK_MODULES(LIBAVCODEC, [libavcodec],
|
|
||||||
[enable_ffmpeg="yes" USE_FFMPEG=1],
|
|
||||||
[enable_ffmpeg="no" USE_FFMPEG=0]
|
|
||||||
)
|
|
||||||
fi
|
fi
|
||||||
if test "$enable_ffmpeg" = "yes"; then
|
|
||||||
AC_CHECK_HEADERS([libavcodec/avcodec.h ffmpeg/avcodec.h])
|
|
||||||
AC_CHECK_HEADERS([libavcodec/vaapi.h ffmpeg/vaapi.h],
|
|
||||||
[break],
|
|
||||||
[enable_ffmpeg="no" USE_FFMPEG=0]
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$enable_ffmpeg:$enable_codecparsers" = "no:no"; then
|
|
||||||
AC_MSG_ERROR([Found neither suitable FFmpeg with VA-API support nor GStreamer bitstream parsers])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_DEFINE_UNQUOTED(USE_FFMPEG, $USE_FFMPEG,
|
|
||||||
[Defined to 1 if FFmpeg is used])
|
|
||||||
AM_CONDITIONAL(USE_FFMPEG, test $USE_FFMPEG -eq 1)
|
|
||||||
|
|
||||||
AC_DEFINE_UNQUOTED(USE_GLX, $USE_GLX,
|
AC_DEFINE_UNQUOTED(USE_GLX, $USE_GLX,
|
||||||
[Defined to 1 if GLX is enabled])
|
[Defined to 1 if GLX is enabled])
|
||||||
|
@ -543,6 +518,5 @@ echo VA-API version ................... : $VA_VERSION_STR
|
||||||
echo GLX support ...................... : $(yesno $USE_GLX)
|
echo GLX support ...................... : $(yesno $USE_GLX)
|
||||||
echo VA/GLX support ................... : $(yesno $USE_VAAPI_GLX)
|
echo VA/GLX support ................... : $(yesno $USE_VAAPI_GLX)
|
||||||
echo VaapiSink/GL ..................... : $(yesno $USE_VAAPISINK_GLX)
|
echo VaapiSink/GL ..................... : $(yesno $USE_VAAPISINK_GLX)
|
||||||
echo FFmpeg bitstream parsers ......... : $(yesno $USE_FFMPEG)
|
|
||||||
echo GStreamer bitstream parsers ...... : $(yesno $USE_CODEC_PARSERS)
|
echo GStreamer bitstream parsers ...... : $(yesno $USE_CODEC_PARSERS)
|
||||||
echo
|
echo
|
||||||
|
|
|
@ -472,22 +472,6 @@ GST_VAAPI_IS_DECODER_CLASS
|
||||||
GST_VAAPI_DECODER_GET_CLASS
|
GST_VAAPI_DECODER_GET_CLASS
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
|
||||||
<FILE>gstvaapidecoder_ffmpeg</FILE>
|
|
||||||
<TITLE>GstVaapiDecoderFfmpeg</TITLE>
|
|
||||||
GstVaapiDecoderFfmpeg
|
|
||||||
GstVaapiDecoderFfmpegClass
|
|
||||||
gst_vaapi_decoder_ffmpeg_new
|
|
||||||
<SUBSECTION Standard>
|
|
||||||
GST_VAAPI_DECODER_FFMPEG
|
|
||||||
GST_VAAPI_IS_DECODER_FFMPEG
|
|
||||||
GST_VAAPI_TYPE_DECODER_FFMPEG
|
|
||||||
gst_vaapi_decoder_ffmpeg_get_type
|
|
||||||
GST_VAAPI_DECODER_FFMPEG_CLASS
|
|
||||||
GST_VAAPI_IS_DECODER_FFMPEG_CLASS
|
|
||||||
GST_VAAPI_DECODER_FFMPEG_GET_CLASS
|
|
||||||
</SECTION>
|
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>gstvaapidecoder_mpeg2</FILE>
|
<FILE>gstvaapidecoder_mpeg2</FILE>
|
||||||
<TITLE>GstVaapiDecoderMpeg2</TITLE>
|
<TITLE>GstVaapiDecoderMpeg2</TITLE>
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
gst_vaapi_context_get_type
|
gst_vaapi_context_get_type
|
||||||
gst_vaapi_decoder_get_type
|
gst_vaapi_decoder_get_type
|
||||||
gst_vaapi_decoder_ffmpeg_get_type
|
|
||||||
gst_vaapi_display_get_type
|
gst_vaapi_display_get_type
|
||||||
gst_vaapi_image_get_type
|
gst_vaapi_image_get_type
|
||||||
gst_vaapi_image_pool_get_type
|
gst_vaapi_image_pool_get_type
|
||||||
|
|
|
@ -89,7 +89,6 @@ libgstvaapi_source_priv_h = \
|
||||||
gstvaapivideobuffer_priv.h \
|
gstvaapivideobuffer_priv.h \
|
||||||
gstvaapiworkarounds.h \
|
gstvaapiworkarounds.h \
|
||||||
sysdeps.h \
|
sysdeps.h \
|
||||||
$(libgst_vaapi_ffmpeg_source_priv_h) \
|
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
libgstvaapi_x11_source_c = \
|
libgstvaapi_x11_source_c = \
|
||||||
|
@ -138,13 +137,6 @@ libgstvaapi_glx_source_priv_h = \
|
||||||
gstvaapiutils_x11.h \
|
gstvaapiutils_x11.h \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
if USE_FFMPEG
|
|
||||||
libgstvaapi_source_c += gstvaapidecoder_ffmpeg.c
|
|
||||||
libgstvaapi_source_h += gstvaapidecoder_ffmpeg.h
|
|
||||||
libgstvaapi_cflags += $(LIBAVCODEC_CFLAGS)
|
|
||||||
libgstvaapi_libs += $(LIBAVCODEC_LIBS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
if USE_CODEC_PARSERS
|
if USE_CODEC_PARSERS
|
||||||
libgstvaapi_source_c += \
|
libgstvaapi_source_c += \
|
||||||
gstvaapicodec_objects.c \
|
gstvaapicodec_objects.c \
|
||||||
|
|
|
@ -1,696 +0,0 @@
|
||||||
/*
|
|
||||||
* gstvaapidecoder_ffmpeg.c - FFmpeg-based decoder
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010-2011 Splitted-Desktop Systems
|
|
||||||
* Copyright (C) 2011-2012 Intel Corporation
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free
|
|
||||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
||||||
* Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SECTION:gstvaapidecoder_ffmpeg
|
|
||||||
* @short_description: FFmpeg-based decoder
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "sysdeps.h"
|
|
||||||
#ifdef HAVE_LIBAVCODEC_AVCODEC_H
|
|
||||||
# include <libavcodec/avcodec.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_FFMPEG_AVCODEC_H
|
|
||||||
# include <ffmpeg/avcodec.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_LIBAVCODEC_VAAPI_H
|
|
||||||
# include <libavcodec/vaapi.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_FFMPEG_VAAPI_H
|
|
||||||
# include <ffmpeg/vaapi.h>
|
|
||||||
#endif
|
|
||||||
#include "gstvaapidecoder_ffmpeg.h"
|
|
||||||
#include "gstvaapidecoder_priv.h"
|
|
||||||
#include "gstvaapidisplay_priv.h"
|
|
||||||
#include "gstvaapiobject_priv.h"
|
|
||||||
|
|
||||||
#define DEBUG 1
|
|
||||||
#include "gstvaapidebug.h"
|
|
||||||
|
|
||||||
G_DEFINE_TYPE(GstVaapiDecoderFfmpeg,
|
|
||||||
gst_vaapi_decoder_ffmpeg,
|
|
||||||
GST_VAAPI_TYPE_DECODER);
|
|
||||||
|
|
||||||
#define GST_VAAPI_DECODER_FFMPEG_GET_PRIVATE(obj) \
|
|
||||||
(G_TYPE_INSTANCE_GET_PRIVATE((obj), \
|
|
||||||
GST_VAAPI_TYPE_DECODER_FFMPEG, \
|
|
||||||
GstVaapiDecoderFfmpegPrivate))
|
|
||||||
|
|
||||||
typedef struct _GstVaapiContextFfmpeg GstVaapiContextFfmpeg;
|
|
||||||
struct _GstVaapiContextFfmpeg {
|
|
||||||
struct vaapi_context base;
|
|
||||||
GstVaapiProfile profile;
|
|
||||||
GstVaapiEntrypoint entrypoint;
|
|
||||||
GstVaapiDecoderFfmpeg *decoder;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _GstVaapiDecoderFfmpegPrivate {
|
|
||||||
GstClockTime in_timestamp; /* timestamp from the demuxer */
|
|
||||||
AVFrame *frame;
|
|
||||||
AVCodecParserContext *pctx;
|
|
||||||
AVCodecContext *avctx;
|
|
||||||
GstVaapiContextFfmpeg *vactx;
|
|
||||||
guint is_constructed : 1;
|
|
||||||
guint is_opened : 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Converts codec to FFmpeg codec id */
|
|
||||||
static enum CodecID
|
|
||||||
get_codec_id_from_codec(GstVaapiCodec codec)
|
|
||||||
{
|
|
||||||
switch (codec) {
|
|
||||||
case GST_VAAPI_CODEC_MPEG1: return CODEC_ID_MPEG1VIDEO;
|
|
||||||
case GST_VAAPI_CODEC_MPEG2: return CODEC_ID_MPEG2VIDEO;
|
|
||||||
case GST_VAAPI_CODEC_MPEG4: return CODEC_ID_MPEG4;
|
|
||||||
case GST_VAAPI_CODEC_H263: return CODEC_ID_H263;
|
|
||||||
case GST_VAAPI_CODEC_H264: return CODEC_ID_H264;
|
|
||||||
case GST_VAAPI_CODEC_WMV3: return CODEC_ID_WMV3;
|
|
||||||
case GST_VAAPI_CODEC_VC1: return CODEC_ID_VC1;
|
|
||||||
}
|
|
||||||
return CODEC_ID_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Converts PixelFormat to entrypoint */
|
|
||||||
static GstVaapiEntrypoint
|
|
||||||
get_entrypoint(enum PixelFormat pix_fmt)
|
|
||||||
{
|
|
||||||
switch (pix_fmt) {
|
|
||||||
case PIX_FMT_VAAPI_VLD: return GST_VAAPI_ENTRYPOINT_VLD;
|
|
||||||
case PIX_FMT_VAAPI_IDCT: return GST_VAAPI_ENTRYPOINT_IDCT;
|
|
||||||
case PIX_FMT_VAAPI_MOCO: return GST_VAAPI_ENTRYPOINT_MOCO;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Finds a suitable profile from FFmpeg context */
|
|
||||||
static GstVaapiProfile
|
|
||||||
get_profile(AVCodecContext *avctx, GstVaapiEntrypoint entrypoint)
|
|
||||||
{
|
|
||||||
GstVaapiContextFfmpeg * const vactx = avctx->hwaccel_context;
|
|
||||||
GstVaapiDisplay *display;
|
|
||||||
GstVaapiProfile profiles[4];
|
|
||||||
guint i, n_profiles = 0;
|
|
||||||
|
|
||||||
#define ADD_PROFILE(profile) do { \
|
|
||||||
profiles[n_profiles++] = GST_VAAPI_PROFILE_##profile; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
switch (avctx->codec_id) {
|
|
||||||
case CODEC_ID_MPEG1VIDEO:
|
|
||||||
ADD_PROFILE(MPEG1);
|
|
||||||
break;
|
|
||||||
case CODEC_ID_MPEG2VIDEO:
|
|
||||||
ADD_PROFILE(MPEG2_MAIN);
|
|
||||||
ADD_PROFILE(MPEG2_SIMPLE);
|
|
||||||
break;
|
|
||||||
case CODEC_ID_H263:
|
|
||||||
ADD_PROFILE(H263_BASELINE);
|
|
||||||
/* fall-through */
|
|
||||||
case CODEC_ID_MPEG4:
|
|
||||||
ADD_PROFILE(MPEG4_MAIN);
|
|
||||||
ADD_PROFILE(MPEG4_ADVANCED_SIMPLE);
|
|
||||||
ADD_PROFILE(MPEG4_SIMPLE);
|
|
||||||
break;
|
|
||||||
case CODEC_ID_H264:
|
|
||||||
if (avctx->profile == 66) /* baseline */
|
|
||||||
ADD_PROFILE(H264_BASELINE);
|
|
||||||
else {
|
|
||||||
if (avctx->profile == 77) /* main */
|
|
||||||
ADD_PROFILE(H264_MAIN);
|
|
||||||
ADD_PROFILE(H264_HIGH);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CODEC_ID_WMV3:
|
|
||||||
if (avctx->profile == 0) /* simple */
|
|
||||||
ADD_PROFILE(VC1_SIMPLE);
|
|
||||||
ADD_PROFILE(VC1_MAIN);
|
|
||||||
break;
|
|
||||||
case CODEC_ID_VC1:
|
|
||||||
ADD_PROFILE(VC1_ADVANCED);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef ADD_PROFILE
|
|
||||||
|
|
||||||
display = GST_VAAPI_DECODER_DISPLAY(vactx->decoder);
|
|
||||||
if (!display)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (i = 0; i < n_profiles; i++)
|
|
||||||
if (gst_vaapi_display_has_decoder(display, profiles[i], entrypoint))
|
|
||||||
return profiles[i];
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Ensures VA context is correctly set up for the current FFmpeg context */
|
|
||||||
static GstVaapiContext *
|
|
||||||
get_context(AVCodecContext *avctx, AVFrame *pic)
|
|
||||||
{
|
|
||||||
GstVaapiContextFfmpeg * const vactx = avctx->hwaccel_context;
|
|
||||||
GstVaapiDecoder * const decoder = GST_VAAPI_DECODER(vactx->decoder);
|
|
||||||
GstVaapiDisplay *display;
|
|
||||||
GstVaapiContext *context;
|
|
||||||
gboolean success;
|
|
||||||
|
|
||||||
if (!avctx->coded_width || !avctx->coded_height)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
gst_vaapi_decoder_set_framerate(
|
|
||||||
decoder,
|
|
||||||
avctx->time_base.den / avctx->ticks_per_frame,
|
|
||||||
avctx->time_base.num
|
|
||||||
);
|
|
||||||
|
|
||||||
gst_vaapi_decoder_set_pixel_aspect_ratio(
|
|
||||||
decoder,
|
|
||||||
avctx->sample_aspect_ratio.num,
|
|
||||||
avctx->sample_aspect_ratio.den
|
|
||||||
);
|
|
||||||
|
|
||||||
gst_vaapi_decoder_set_interlaced(decoder, !!pic->interlaced_frame);
|
|
||||||
|
|
||||||
success = gst_vaapi_decoder_ensure_context(
|
|
||||||
decoder,
|
|
||||||
vactx->profile,
|
|
||||||
vactx->entrypoint,
|
|
||||||
avctx->coded_width,
|
|
||||||
avctx->coded_height
|
|
||||||
);
|
|
||||||
if (!success) {
|
|
||||||
GST_DEBUG("failed to reset VA context:");
|
|
||||||
GST_DEBUG(" profile 0x%08x", vactx->profile);
|
|
||||||
GST_DEBUG(" entrypoint %d", vactx->entrypoint);
|
|
||||||
GST_DEBUG(" surface size %dx%d", avctx->width, avctx->height);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
display = GST_VAAPI_DECODER_DISPLAY(decoder);
|
|
||||||
context = GST_VAAPI_DECODER_CONTEXT(decoder);
|
|
||||||
vactx->base.display = GST_VAAPI_DISPLAY_VADISPLAY(display);
|
|
||||||
vactx->base.context_id = GST_VAAPI_OBJECT_ID(context);
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Sets AVCodecContext.extradata with additional codec data */
|
|
||||||
static gboolean
|
|
||||||
set_codec_data(AVCodecContext *avctx, const guchar *buf, guint buf_size)
|
|
||||||
{
|
|
||||||
av_freep(&avctx->extradata);
|
|
||||||
avctx->extradata_size = 0;
|
|
||||||
if (!buf || buf_size < 1)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
avctx->extradata = av_malloc(buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
|
|
||||||
if (!avctx->extradata)
|
|
||||||
return FALSE;
|
|
||||||
avctx->extradata_size = buf_size;
|
|
||||||
memcpy(avctx->extradata, buf, buf_size);
|
|
||||||
memset(avctx->extradata + buf_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** AVCodecContext.get_format() implementation */
|
|
||||||
static enum PixelFormat
|
|
||||||
gst_vaapi_decoder_ffmpeg_get_format(AVCodecContext *avctx, const enum PixelFormat *fmt)
|
|
||||||
{
|
|
||||||
GstVaapiContextFfmpeg * const vactx = avctx->hwaccel_context;
|
|
||||||
GstVaapiProfile profile;
|
|
||||||
GstVaapiEntrypoint entrypoint;
|
|
||||||
guint i;
|
|
||||||
|
|
||||||
/* XXX: only VLD entrypoint is supported at this time */
|
|
||||||
for (i = 0; fmt[i] != PIX_FMT_NONE; i++) {
|
|
||||||
entrypoint = get_entrypoint(fmt[i]);
|
|
||||||
if (entrypoint != GST_VAAPI_ENTRYPOINT_VLD)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
profile = get_profile(avctx, entrypoint);
|
|
||||||
if (profile) {
|
|
||||||
vactx->profile = profile;
|
|
||||||
vactx->entrypoint = entrypoint;
|
|
||||||
return fmt[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return PIX_FMT_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** AVCodecContext.get_buffer() implementation */
|
|
||||||
static int
|
|
||||||
gst_vaapi_decoder_ffmpeg_get_buffer(AVCodecContext *avctx, AVFrame *pic)
|
|
||||||
{
|
|
||||||
GstVaapiContextFfmpeg * const vactx = avctx->hwaccel_context;
|
|
||||||
GstVaapiContext *context;
|
|
||||||
GstVaapiSurface *surface;
|
|
||||||
GstVaapiSurfaceProxy *proxy;
|
|
||||||
GstVaapiID surface_id;
|
|
||||||
|
|
||||||
context = get_context(avctx, pic);
|
|
||||||
if (!context)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
surface = gst_vaapi_context_get_surface(context);
|
|
||||||
if (!surface) {
|
|
||||||
GST_DEBUG("failed to get a free VA surface");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
proxy = gst_vaapi_surface_proxy_new(context, surface);
|
|
||||||
if (!proxy) {
|
|
||||||
GST_DEBUG("failed to create proxy surface");
|
|
||||||
gst_vaapi_context_put_surface(context, surface);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
surface_id = GST_VAAPI_OBJECT_ID(surface);
|
|
||||||
GST_DEBUG("surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(surface_id));
|
|
||||||
|
|
||||||
pic->type = FF_BUFFER_TYPE_USER;
|
|
||||||
pic->age = 1;
|
|
||||||
pic->data[0] = (uint8_t *)proxy;
|
|
||||||
pic->data[1] = NULL;
|
|
||||||
pic->data[2] = NULL;
|
|
||||||
pic->data[3] = (uint8_t *)(uintptr_t)surface_id;
|
|
||||||
pic->linesize[0] = 0;
|
|
||||||
pic->linesize[1] = 0;
|
|
||||||
pic->linesize[2] = 0;
|
|
||||||
pic->linesize[3] = 0;
|
|
||||||
pic->pts = vactx->decoder->priv->in_timestamp;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** AVCodecContext.reget_buffer() implementation */
|
|
||||||
static int
|
|
||||||
gst_vaapi_decoder_ffmpeg_reget_buffer(AVCodecContext *avctx, AVFrame *pic)
|
|
||||||
{
|
|
||||||
GST_DEBUG("UNIMPLEMENTED");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** AVCodecContext.release_buffer() implementation */
|
|
||||||
static void
|
|
||||||
gst_vaapi_decoder_ffmpeg_release_buffer(AVCodecContext *avctx, AVFrame *pic)
|
|
||||||
{
|
|
||||||
GstVaapiSurfaceProxy * const proxy = GST_VAAPI_SURFACE_PROXY(pic->data[0]);
|
|
||||||
GstVaapiID surface_id = GST_VAAPI_ID(GPOINTER_TO_UINT(pic->data[3]));
|
|
||||||
|
|
||||||
GST_DEBUG("surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(surface_id));
|
|
||||||
|
|
||||||
g_object_unref(proxy);
|
|
||||||
|
|
||||||
pic->data[0] = NULL;
|
|
||||||
pic->data[1] = NULL;
|
|
||||||
pic->data[2] = NULL;
|
|
||||||
pic->data[3] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_vaapi_decoder_ffmpeg_close(GstVaapiDecoderFfmpeg *ffdecoder)
|
|
||||||
{
|
|
||||||
GstVaapiDecoderFfmpegPrivate * const priv = ffdecoder->priv;
|
|
||||||
|
|
||||||
if (priv->avctx) {
|
|
||||||
if (priv->is_opened) {
|
|
||||||
avcodec_close(priv->avctx);
|
|
||||||
priv->is_opened = FALSE;
|
|
||||||
}
|
|
||||||
av_freep(&priv->avctx->extradata);
|
|
||||||
priv->avctx->extradata_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->pctx) {
|
|
||||||
av_parser_close(priv->pctx);
|
|
||||||
priv->pctx = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_vaapi_decoder_ffmpeg_destroy(GstVaapiDecoderFfmpeg *ffdecoder)
|
|
||||||
{
|
|
||||||
GstVaapiDecoderFfmpegPrivate * const priv = ffdecoder->priv;
|
|
||||||
|
|
||||||
gst_vaapi_decoder_ffmpeg_close(ffdecoder);
|
|
||||||
|
|
||||||
if (priv->vactx) {
|
|
||||||
g_free(priv->vactx);
|
|
||||||
priv->vactx = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
av_freep(&priv->avctx);
|
|
||||||
av_freep(&priv->frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_vaapi_decoder_ffmpeg_create(GstVaapiDecoderFfmpeg *ffdecoder)
|
|
||||||
{
|
|
||||||
GstVaapiDecoderFfmpegPrivate * const priv = ffdecoder->priv;
|
|
||||||
|
|
||||||
if (!GST_VAAPI_DECODER_CODEC(ffdecoder))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (!priv->frame) {
|
|
||||||
priv->frame = avcodec_alloc_frame();
|
|
||||||
if (!priv->frame)
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!priv->avctx) {
|
|
||||||
priv->avctx = avcodec_alloc_context();
|
|
||||||
if (!priv->avctx)
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!priv->vactx) {
|
|
||||||
priv->vactx = g_new(GstVaapiContextFfmpeg, 1);
|
|
||||||
if (!priv->vactx)
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
memset(&priv->vactx->base, 0, sizeof(priv->vactx->base));
|
|
||||||
priv->vactx->decoder = ffdecoder;
|
|
||||||
|
|
||||||
priv->avctx->hwaccel_context = priv->vactx;
|
|
||||||
priv->avctx->get_format = gst_vaapi_decoder_ffmpeg_get_format;
|
|
||||||
priv->avctx->get_buffer = gst_vaapi_decoder_ffmpeg_get_buffer;
|
|
||||||
priv->avctx->reget_buffer = gst_vaapi_decoder_ffmpeg_reget_buffer;
|
|
||||||
priv->avctx->release_buffer = gst_vaapi_decoder_ffmpeg_release_buffer;
|
|
||||||
priv->avctx->thread_count = 1;
|
|
||||||
priv->avctx->draw_horiz_band = NULL;
|
|
||||||
priv->avctx->slice_flags = SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GstVaapiDecoderStatus
|
|
||||||
render_frame(GstVaapiDecoderFfmpeg *decoder, AVFrame *frame)
|
|
||||||
{
|
|
||||||
GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
|
|
||||||
GstVaapiSurfaceProxy *proxy;
|
|
||||||
|
|
||||||
proxy = GST_VAAPI_SURFACE_PROXY(frame->data[0]);
|
|
||||||
if (!proxy)
|
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_INVALID_SURFACE;
|
|
||||||
|
|
||||||
gst_vaapi_surface_proxy_set_timestamp(proxy, frame->pts);
|
|
||||||
gst_vaapi_surface_proxy_set_interlaced(proxy, !!frame->interlaced_frame);
|
|
||||||
gst_vaapi_surface_proxy_set_tff(proxy, frame->top_field_first);
|
|
||||||
gst_vaapi_decoder_push_surface_proxy(base_decoder, g_object_ref(proxy));
|
|
||||||
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GstVaapiDecoderStatus
|
|
||||||
decode_frame(GstVaapiDecoderFfmpeg *ffdecoder, guchar *buf, guint buf_size)
|
|
||||||
{
|
|
||||||
GstVaapiDecoderFfmpegPrivate * const priv = ffdecoder->priv;
|
|
||||||
GstVaapiDisplay * const display = GST_VAAPI_DECODER_DISPLAY(ffdecoder);
|
|
||||||
int bytes_read, got_picture = 0;
|
|
||||||
AVPacket pkt;
|
|
||||||
|
|
||||||
av_init_packet(&pkt);
|
|
||||||
pkt.data = buf;
|
|
||||||
pkt.size = buf_size;
|
|
||||||
|
|
||||||
GST_VAAPI_DISPLAY_LOCK(display);
|
|
||||||
bytes_read = avcodec_decode_video2(
|
|
||||||
priv->avctx,
|
|
||||||
priv->frame,
|
|
||||||
&got_picture,
|
|
||||||
&pkt
|
|
||||||
);
|
|
||||||
GST_VAAPI_DISPLAY_UNLOCK(display);
|
|
||||||
if (!got_picture)
|
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
|
|
||||||
if (bytes_read < 0)
|
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
|
|
||||||
|
|
||||||
return render_frame(ffdecoder, priv->frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
GstVaapiDecoderStatus
|
|
||||||
gst_vaapi_decoder_ffmpeg_decode(GstVaapiDecoder *decoder, GstBuffer *buffer)
|
|
||||||
{
|
|
||||||
GstVaapiDecoderFfmpeg * const ffdecoder = GST_VAAPI_DECODER_FFMPEG(decoder);
|
|
||||||
GstVaapiDecoderFfmpegPrivate * const priv = ffdecoder->priv;
|
|
||||||
GstClockTime inbuf_ts;
|
|
||||||
guchar *outbuf;
|
|
||||||
gint inbuf_ofs, inbuf_size, outbuf_size;
|
|
||||||
gboolean got_frame;
|
|
||||||
|
|
||||||
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_ffmpeg_open(ffdecoder, buffer);
|
|
||||||
if (!priv->is_opened)
|
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
|
|
||||||
}
|
|
||||||
|
|
||||||
inbuf_ofs = 0;
|
|
||||||
inbuf_size = GST_BUFFER_SIZE(buffer);
|
|
||||||
inbuf_ts = GST_BUFFER_TIMESTAMP(buffer);
|
|
||||||
|
|
||||||
if (priv->pctx) {
|
|
||||||
do {
|
|
||||||
int parsed_size;
|
|
||||||
parsed_size = av_parser_parse2(
|
|
||||||
priv->pctx,
|
|
||||||
priv->avctx,
|
|
||||||
&outbuf, &outbuf_size,
|
|
||||||
GST_BUFFER_DATA(buffer) + inbuf_ofs, inbuf_size,
|
|
||||||
inbuf_ts, inbuf_ts,
|
|
||||||
AV_NOPTS_VALUE
|
|
||||||
);
|
|
||||||
got_frame = outbuf && outbuf_size > 0;
|
|
||||||
|
|
||||||
if (parsed_size > 0) {
|
|
||||||
inbuf_ofs += parsed_size;
|
|
||||||
inbuf_size -= parsed_size;
|
|
||||||
}
|
|
||||||
} while (!got_frame && inbuf_size > 0);
|
|
||||||
inbuf_ts = priv->pctx->pts;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
outbuf = GST_BUFFER_DATA(buffer);
|
|
||||||
outbuf_size = inbuf_size;
|
|
||||||
got_frame = outbuf && outbuf_size > 0;
|
|
||||||
inbuf_ofs = inbuf_size;
|
|
||||||
inbuf_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inbuf_size > 0 &&
|
|
||||||
!gst_vaapi_decoder_push_buffer_sub(decoder, buffer,
|
|
||||||
inbuf_ofs, inbuf_size))
|
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
|
|
||||||
|
|
||||||
if (!got_frame && !GST_BUFFER_IS_EOS(buffer))
|
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
|
|
||||||
|
|
||||||
priv->in_timestamp = inbuf_ts;
|
|
||||||
return decode_frame(ffdecoder, outbuf, outbuf_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_vaapi_decoder_ffmpeg_finalize(GObject *object)
|
|
||||||
{
|
|
||||||
GstVaapiDecoderFfmpeg * const ffdecoder = GST_VAAPI_DECODER_FFMPEG(object);
|
|
||||||
|
|
||||||
gst_vaapi_decoder_ffmpeg_destroy(ffdecoder);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS(gst_vaapi_decoder_ffmpeg_parent_class)->finalize(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_vaapi_decoder_ffmpeg_constructed(GObject *object)
|
|
||||||
{
|
|
||||||
GstVaapiDecoderFfmpeg * const ffdecoder = GST_VAAPI_DECODER_FFMPEG(object);
|
|
||||||
GstVaapiDecoderFfmpegPrivate * const priv = ffdecoder->priv;
|
|
||||||
GObjectClass *parent_class;
|
|
||||||
|
|
||||||
parent_class = G_OBJECT_CLASS(gst_vaapi_decoder_ffmpeg_parent_class);
|
|
||||||
if (parent_class->constructed)
|
|
||||||
parent_class->constructed(object);
|
|
||||||
|
|
||||||
priv->is_constructed = gst_vaapi_decoder_ffmpeg_create(ffdecoder);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_vaapi_decoder_ffmpeg_class_init(GstVaapiDecoderFfmpegClass *klass)
|
|
||||||
{
|
|
||||||
GObjectClass * const object_class = G_OBJECT_CLASS(klass);
|
|
||||||
GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);
|
|
||||||
|
|
||||||
g_type_class_add_private(klass, sizeof(GstVaapiDecoderFfmpegPrivate));
|
|
||||||
|
|
||||||
object_class->finalize = gst_vaapi_decoder_ffmpeg_finalize;
|
|
||||||
object_class->constructed = gst_vaapi_decoder_ffmpeg_constructed;
|
|
||||||
|
|
||||||
decoder_class->decode = gst_vaapi_decoder_ffmpeg_decode;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gpointer
|
|
||||||
gst_vaapi_decoder_ffmpeg_init_once_cb(gpointer user_data)
|
|
||||||
{
|
|
||||||
avcodec_register_all();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
gst_vaapi_decoder_ffmpeg_init_once(void)
|
|
||||||
{
|
|
||||||
static GOnce once = G_ONCE_INIT;
|
|
||||||
|
|
||||||
g_once(&once, gst_vaapi_decoder_ffmpeg_init_once_cb, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_vaapi_decoder_ffmpeg_init(GstVaapiDecoderFfmpeg *decoder)
|
|
||||||
{
|
|
||||||
GstVaapiDecoderFfmpegPrivate *priv;
|
|
||||||
|
|
||||||
gst_vaapi_decoder_ffmpeg_init_once();
|
|
||||||
|
|
||||||
priv = GST_VAAPI_DECODER_FFMPEG_GET_PRIVATE(decoder);
|
|
||||||
decoder->priv = priv;
|
|
||||||
priv->frame = NULL;
|
|
||||||
priv->pctx = NULL;
|
|
||||||
priv->avctx = NULL;
|
|
||||||
priv->vactx = NULL;
|
|
||||||
priv->is_constructed = FALSE;
|
|
||||||
priv->is_opened = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* gst_vaapi_decoder_ffmpeg_new:
|
|
||||||
* @display: a #GstVaapiDisplay
|
|
||||||
* @caps: a #GstCaps holding codec information
|
|
||||||
*
|
|
||||||
* Creates a new #GstVaapiDecoder based on FFmpeg where the codec is
|
|
||||||
* determined from @caps. The @caps can hold extra information like
|
|
||||||
* codec-data and pictured coded size.
|
|
||||||
*
|
|
||||||
* Return value: the newly allocated #GstVaapiDecoder object
|
|
||||||
*/
|
|
||||||
GstVaapiDecoder *
|
|
||||||
gst_vaapi_decoder_ffmpeg_new(GstVaapiDisplay *display, GstCaps *caps)
|
|
||||||
{
|
|
||||||
GstVaapiDecoderFfmpeg *ffdecoder;
|
|
||||||
|
|
||||||
g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
|
|
||||||
g_return_val_if_fail(GST_IS_CAPS(caps), NULL);
|
|
||||||
|
|
||||||
ffdecoder = g_object_new(
|
|
||||||
GST_VAAPI_TYPE_DECODER_FFMPEG,
|
|
||||||
"display", display,
|
|
||||||
"caps", caps,
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
if (!ffdecoder->priv->is_constructed) {
|
|
||||||
g_object_unref(ffdecoder);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return GST_VAAPI_DECODER_CAST(ffdecoder);
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
/*
|
|
||||||
* gstvaapidecoder_ffmpeg.h - FFmpeg-based decoder
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010-2011 Splitted-Desktop Systems
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free
|
|
||||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
||||||
* Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GST_VAAPI_DECODER_FFMPEG_H
|
|
||||||
#define GST_VAAPI_DECODER_FFMPEG_H
|
|
||||||
|
|
||||||
#include <gst/vaapi/gstvaapidecoder.h>
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
#define GST_VAAPI_TYPE_DECODER_FFMPEG \
|
|
||||||
(gst_vaapi_decoder_ffmpeg_get_type())
|
|
||||||
|
|
||||||
#define GST_VAAPI_DECODER_FFMPEG(obj) \
|
|
||||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), \
|
|
||||||
GST_VAAPI_TYPE_DECODER_FFMPEG, \
|
|
||||||
GstVaapiDecoderFfmpeg))
|
|
||||||
|
|
||||||
#define GST_VAAPI_DECODER_FFMPEG_CLASS(klass) \
|
|
||||||
(G_TYPE_CHECK_CLASS_CAST((klass), \
|
|
||||||
GST_VAAPI_TYPE_DECODER_FFMPEG, \
|
|
||||||
GstVaapiDecoderFfmpegClass))
|
|
||||||
|
|
||||||
#define GST_VAAPI_IS_DECODER_FFMPEG(obj) \
|
|
||||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_DECODER_FFMPEG))
|
|
||||||
|
|
||||||
#define GST_VAAPI_IS_DECODER_FFMPEG_CLASS(klass) \
|
|
||||||
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_DECODER_FFMPEG))
|
|
||||||
|
|
||||||
#define GST_VAAPI_DECODER_FFMPEG_GET_CLASS(obj) \
|
|
||||||
(G_TYPE_INSTANCE_GET_CLASS((obj), \
|
|
||||||
GST_VAAPI_TYPE_DECODER_FFMPEG, \
|
|
||||||
GstVaapiDecoderFfmpegClass))
|
|
||||||
|
|
||||||
typedef struct _GstVaapiDecoderFfmpeg GstVaapiDecoderFfmpeg;
|
|
||||||
typedef struct _GstVaapiDecoderFfmpegPrivate GstVaapiDecoderFfmpegPrivate;
|
|
||||||
typedef struct _GstVaapiDecoderFfmpegClass GstVaapiDecoderFfmpegClass;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GstVaapiDecoderFfmpeg:
|
|
||||||
*
|
|
||||||
* A decoder based on FFmpeg.
|
|
||||||
*/
|
|
||||||
struct _GstVaapiDecoderFfmpeg {
|
|
||||||
/*< private >*/
|
|
||||||
GstVaapiDecoder parent_instance;
|
|
||||||
|
|
||||||
GstVaapiDecoderFfmpegPrivate *priv;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GstVaapiDecoderFfmpegClass:
|
|
||||||
*
|
|
||||||
* A decoder class based on FFmpeg.
|
|
||||||
*/
|
|
||||||
struct _GstVaapiDecoderFfmpegClass {
|
|
||||||
/*< private >*/
|
|
||||||
GstVaapiDecoderClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
GType
|
|
||||||
gst_vaapi_decoder_ffmpeg_get_type(void) G_GNUC_CONST;
|
|
||||||
|
|
||||||
GstVaapiDecoder *
|
|
||||||
gst_vaapi_decoder_ffmpeg_new(GstVaapiDisplay *display, GstCaps *caps);
|
|
||||||
|
|
||||||
G_END_DECLS
|
|
||||||
|
|
||||||
#endif /* GST_VAAPI_DECODER_FFMPEG_H */
|
|
|
@ -44,9 +44,6 @@
|
||||||
#include "gstvaapidecode.h"
|
#include "gstvaapidecode.h"
|
||||||
#include "gstvaapipluginutil.h"
|
#include "gstvaapipluginutil.h"
|
||||||
|
|
||||||
#if USE_FFMPEG
|
|
||||||
# include <gst/vaapi/gstvaapidecoder_ffmpeg.h>
|
|
||||||
#endif
|
|
||||||
#if USE_CODEC_PARSERS
|
#if USE_CODEC_PARSERS
|
||||||
# include <gst/vaapi/gstvaapidecoder_h264.h>
|
# include <gst/vaapi/gstvaapidecoder_h264.h>
|
||||||
# include <gst/vaapi/gstvaapidecoder_jpeg.h>
|
# include <gst/vaapi/gstvaapidecoder_jpeg.h>
|
||||||
|
@ -55,10 +52,6 @@
|
||||||
# include <gst/vaapi/gstvaapidecoder_vc1.h>
|
# include <gst/vaapi/gstvaapidecoder_vc1.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Favor codecparsers-based decoders for 0.3.x series */
|
|
||||||
#define USE_FFMPEG_DEFAULT \
|
|
||||||
(USE_FFMPEG && !USE_CODEC_PARSERS)
|
|
||||||
|
|
||||||
#define GST_PLUGIN_NAME "vaapidecode"
|
#define GST_PLUGIN_NAME "vaapidecode"
|
||||||
#define GST_PLUGIN_DESC "A VA-API based video decoder"
|
#define GST_PLUGIN_DESC "A VA-API based video decoder"
|
||||||
|
|
||||||
|
@ -120,12 +113,6 @@ G_DEFINE_TYPE_WITH_CODE(
|
||||||
G_IMPLEMENT_INTERFACE(GST_TYPE_VIDEO_CONTEXT,
|
G_IMPLEMENT_INTERFACE(GST_TYPE_VIDEO_CONTEXT,
|
||||||
gst_video_context_interface_init));
|
gst_video_context_interface_init));
|
||||||
|
|
||||||
enum {
|
|
||||||
PROP_0,
|
|
||||||
|
|
||||||
PROP_USE_FFMPEG,
|
|
||||||
};
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_vaapidecode_update_src_caps(GstVaapiDecode *decode, GstCaps *caps);
|
gst_vaapidecode_update_src_caps(GstVaapiDecode *decode, GstCaps *caps);
|
||||||
|
|
||||||
|
@ -325,12 +312,6 @@ gst_vaapidecode_create(GstVaapiDecode *decode, GstCaps *caps)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
dpy = decode->display;
|
dpy = decode->display;
|
||||||
if (decode->use_ffmpeg) {
|
|
||||||
#if USE_FFMPEG
|
|
||||||
decode->decoder = gst_vaapi_decoder_ffmpeg_new(dpy, caps);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
#if USE_CODEC_PARSERS
|
#if USE_CODEC_PARSERS
|
||||||
structure = gst_caps_get_structure(caps, 0);
|
structure = gst_caps_get_structure(caps, 0);
|
||||||
if (!structure)
|
if (!structure)
|
||||||
|
@ -356,7 +337,6 @@ gst_vaapidecode_create(GstVaapiDecode *decode, GstCaps *caps)
|
||||||
decode->decoder = gst_vaapi_decoder_jpeg_new(dpy, caps);
|
decode->decoder = gst_vaapi_decoder_jpeg_new(dpy, caps);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
if (!decode->decoder)
|
if (!decode->decoder)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -474,46 +454,6 @@ gst_vaapidecode_finalize(GObject *object)
|
||||||
G_OBJECT_CLASS(gst_vaapidecode_parent_class)->finalize(object);
|
G_OBJECT_CLASS(gst_vaapidecode_parent_class)->finalize(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gst_vaapidecode_set_property(
|
|
||||||
GObject *object,
|
|
||||||
guint prop_id,
|
|
||||||
const GValue *value,
|
|
||||||
GParamSpec *pspec
|
|
||||||
)
|
|
||||||
{
|
|
||||||
GstVaapiDecode * const decode = GST_VAAPIDECODE(object);
|
|
||||||
|
|
||||||
switch (prop_id) {
|
|
||||||
case PROP_USE_FFMPEG:
|
|
||||||
decode->use_ffmpeg = g_value_get_boolean(value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_vaapidecode_get_property(
|
|
||||||
GObject *object,
|
|
||||||
guint prop_id,
|
|
||||||
GValue *value,
|
|
||||||
GParamSpec *pspec
|
|
||||||
)
|
|
||||||
{
|
|
||||||
GstVaapiDecode * const decode = GST_VAAPIDECODE(object);
|
|
||||||
|
|
||||||
switch (prop_id) {
|
|
||||||
case PROP_USE_FFMPEG:
|
|
||||||
g_value_set_boolean(value, decode->use_ffmpeg);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static GstStateChangeReturn
|
static GstStateChangeReturn
|
||||||
gst_vaapidecode_change_state(GstElement *element, GstStateChange transition)
|
gst_vaapidecode_change_state(GstElement *element, GstStateChange transition)
|
||||||
{
|
{
|
||||||
|
@ -563,8 +503,6 @@ gst_vaapidecode_class_init(GstVaapiDecodeClass *klass)
|
||||||
GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC);
|
GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC);
|
||||||
|
|
||||||
object_class->finalize = gst_vaapidecode_finalize;
|
object_class->finalize = gst_vaapidecode_finalize;
|
||||||
object_class->set_property = gst_vaapidecode_set_property;
|
|
||||||
object_class->get_property = gst_vaapidecode_get_property;
|
|
||||||
|
|
||||||
element_class->change_state = gst_vaapidecode_change_state;
|
element_class->change_state = gst_vaapidecode_change_state;
|
||||||
|
|
||||||
|
@ -585,17 +523,6 @@ gst_vaapidecode_class_init(GstVaapiDecodeClass *klass)
|
||||||
pad_template = gst_static_pad_template_get(&gst_vaapidecode_src_factory);
|
pad_template = gst_static_pad_template_get(&gst_vaapidecode_src_factory);
|
||||||
gst_element_class_add_pad_template(element_class, pad_template);
|
gst_element_class_add_pad_template(element_class, pad_template);
|
||||||
gst_object_unref(pad_template);
|
gst_object_unref(pad_template);
|
||||||
|
|
||||||
#if USE_FFMPEG
|
|
||||||
g_object_class_install_property
|
|
||||||
(object_class,
|
|
||||||
PROP_USE_FFMPEG,
|
|
||||||
g_param_spec_boolean("use-ffmpeg",
|
|
||||||
"Use FFmpeg/VAAPI for decoding",
|
|
||||||
"Uses FFmpeg/VAAPI for decoding",
|
|
||||||
USE_FFMPEG_DEFAULT,
|
|
||||||
G_PARAM_READWRITE));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -781,7 +708,6 @@ gst_vaapidecode_init(GstVaapiDecode *decode)
|
||||||
decode->decoder_caps = NULL;
|
decode->decoder_caps = NULL;
|
||||||
decode->allowed_caps = NULL;
|
decode->allowed_caps = NULL;
|
||||||
decode->delayed_new_seg = NULL;
|
decode->delayed_new_seg = NULL;
|
||||||
decode->use_ffmpeg = USE_FFMPEG_DEFAULT;
|
|
||||||
decode->is_ready = FALSE;
|
decode->is_ready = FALSE;
|
||||||
|
|
||||||
/* Pad through which data comes in to the element */
|
/* Pad through which data comes in to the element */
|
||||||
|
|
|
@ -72,7 +72,6 @@ struct _GstVaapiDecode {
|
||||||
GstCaps *decoder_caps;
|
GstCaps *decoder_caps;
|
||||||
GstCaps *allowed_caps;
|
GstCaps *allowed_caps;
|
||||||
GstEvent *delayed_new_seg;
|
GstEvent *delayed_new_seg;
|
||||||
unsigned int use_ffmpeg : 1;
|
|
||||||
unsigned int is_ready : 1;
|
unsigned int is_ready : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -31,9 +31,6 @@
|
||||||
#include "test-h264.h"
|
#include "test-h264.h"
|
||||||
#include "test-vc1.h"
|
#include "test-vc1.h"
|
||||||
|
|
||||||
#if USE_FFMPEG
|
|
||||||
# include <gst/vaapi/gstvaapidecoder_ffmpeg.h>
|
|
||||||
#endif
|
|
||||||
#if USE_CODEC_PARSERS
|
#if USE_CODEC_PARSERS
|
||||||
# include <gst/vaapi/gstvaapidecoder_h264.h>
|
# include <gst/vaapi/gstvaapidecoder_h264.h>
|
||||||
# include <gst/vaapi/gstvaapidecoder_jpeg.h>
|
# include <gst/vaapi/gstvaapidecoder_jpeg.h>
|
||||||
|
@ -79,21 +76,12 @@ static inline void pause(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static gchar *g_codec_str;
|
static gchar *g_codec_str;
|
||||||
static gboolean g_use_ffmpeg = FALSE;
|
|
||||||
|
|
||||||
static GOptionEntry g_options[] = {
|
static GOptionEntry g_options[] = {
|
||||||
{ "codec", 'c',
|
{ "codec", 'c',
|
||||||
0,
|
0,
|
||||||
G_OPTION_ARG_STRING, &g_codec_str,
|
G_OPTION_ARG_STRING, &g_codec_str,
|
||||||
"codec to test", NULL },
|
"codec to test", NULL },
|
||||||
{ "ffmpeg", 0,
|
|
||||||
0,
|
|
||||||
G_OPTION_ARG_NONE, &g_use_ffmpeg,
|
|
||||||
"use ffmpeg", NULL },
|
|
||||||
{ "codecparsers", 0,
|
|
||||||
G_OPTION_FLAG_REVERSE,
|
|
||||||
G_OPTION_ARG_NONE, &g_use_ffmpeg,
|
|
||||||
"use codec parsers", NULL },
|
|
||||||
{ NULL, }
|
{ NULL, }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -159,14 +147,6 @@ main(int argc, char *argv[])
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
if (g_use_ffmpeg) {
|
|
||||||
#if USE_FFMPEG
|
|
||||||
decoder = gst_vaapi_decoder_ffmpeg_new(display, decoder_caps);
|
|
||||||
#else
|
|
||||||
g_error("FFmpeg-based decoders are not supported");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
#if USE_CODEC_PARSERS
|
#if USE_CODEC_PARSERS
|
||||||
switch (gst_vaapi_profile_get_codec(info.profile)) {
|
switch (gst_vaapi_profile_get_codec(info.profile)) {
|
||||||
case GST_VAAPI_CODEC_H264:
|
case GST_VAAPI_CODEC_H264:
|
||||||
|
@ -187,10 +167,7 @@ main(int argc, char *argv[])
|
||||||
decoder = NULL;
|
decoder = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
g_error("codecparsers-based decoders are not supported");
|
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
if (!decoder)
|
if (!decoder)
|
||||||
g_error("could not create decoder");
|
g_error("could not create decoder");
|
||||||
gst_caps_unref(decoder_caps);
|
gst_caps_unref(decoder_caps);
|
||||||
|
|
|
@ -29,9 +29,6 @@
|
||||||
#include "test-mpeg2.h"
|
#include "test-mpeg2.h"
|
||||||
#include "test-subpicture-data.h"
|
#include "test-subpicture-data.h"
|
||||||
|
|
||||||
#if USE_FFMPEG
|
|
||||||
# include <gst/vaapi/gstvaapidecoder_ffmpeg.h>
|
|
||||||
#endif
|
|
||||||
#if USE_CODEC_PARSERS
|
#if USE_CODEC_PARSERS
|
||||||
# include <gst/vaapi/gstvaapidecoder_mpeg2.h>
|
# include <gst/vaapi/gstvaapidecoder_mpeg2.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -154,10 +151,6 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
#if USE_CODEC_PARSERS
|
#if USE_CODEC_PARSERS
|
||||||
decoder = gst_vaapi_decoder_mpeg2_new(display, decoder_caps);
|
decoder = gst_vaapi_decoder_mpeg2_new(display, decoder_caps);
|
||||||
#endif
|
|
||||||
#if USE_FFMPEG
|
|
||||||
if (!decoder)
|
|
||||||
decoder = gst_vaapi_decoder_ffmpeg_new(display, decoder_caps);
|
|
||||||
#endif
|
#endif
|
||||||
if (!decoder)
|
if (!decoder)
|
||||||
g_error("could not create video decoder");
|
g_error("could not create video decoder");
|
||||||
|
|
Loading…
Reference in a new issue