diff options
author | Sebastian Dröge <slomo@circular-chaos.org> | 2013-07-14 12:53:31 +0200 |
---|---|---|
committer | Sebastian Dröge <slomo@circular-chaos.org> | 2013-07-14 12:53:31 +0200 |
commit | 506fe9d1810310128adfeb65a9cffd014450ac11 (patch) | |
tree | 63b597f6602b0587b4efcc97df3d1e005a90a5ed /ext/libav/gstavviddec.c | |
parent | aa9289484c3502e9e3f6df9dda964ffe2510092d (diff) |
Imported Upstream version 1.1.2upstream/1.1.2
Diffstat (limited to 'ext/libav/gstavviddec.c')
-rw-r--r-- | ext/libav/gstavviddec.c | 204 |
1 files changed, 76 insertions, 128 deletions
diff --git a/ext/libav/gstavviddec.c b/ext/libav/gstavviddec.c index 7675a71..dc472e4 100644 --- a/ext/libav/gstavviddec.c +++ b/ext/libav/gstavviddec.c @@ -13,8 +13,8 @@ * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H @@ -35,78 +35,17 @@ #include "gstav.h" #include "gstavcodecmap.h" #include "gstavutils.h" +#include "gstavviddec.h" GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE); -typedef struct _GstFFMpegVidDec GstFFMpegVidDec; - #define MAX_TS_MASK 0xff -struct _GstFFMpegVidDec -{ - GstVideoDecoder parent; - - GstVideoCodecState *input_state; - GstVideoCodecState *output_state; - - /* decoding */ - AVCodecContext *context; - AVFrame *picture; - gboolean opened; - - /* current context */ - enum PixelFormat ctx_pix_fmt; - gint ctx_width; - gint ctx_height; - gint ctx_par_n; - gint ctx_par_d; - gint ctx_ticks; - gint ctx_time_d; - gint ctx_time_n; - gint ctx_interlaced; - - guint8 *padded; - guint padded_size; - - gboolean current_dr; /* if direct rendering is enabled */ - - /* some properties */ - enum AVDiscard skip_frame; - gint lowres; - gboolean direct_rendering; - gboolean debug_mv; - int max_threads; - - gboolean is_realvideo; - - GstCaps *last_caps; -}; - -typedef struct _GstFFMpegVidDecClass GstFFMpegVidDecClass; - -struct _GstFFMpegVidDecClass -{ - GstVideoDecoderClass parent_class; - - AVCodec *in_plugin; -}; - -#define GST_TYPE_FFMPEGDEC \ - (gst_ffmpegviddec_get_type()) -#define GST_FFMPEGDEC(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FFMPEGDEC,GstFFMpegVidDec)) -#define GST_FFMPEGVIDDEC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FFMPEGDEC,GstFFMpegVidDecClass)) -#define GST_IS_FFMPEGDEC(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FFMPEGDEC)) -#define GST_IS_FFMPEGVIDDEC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FFMPEGDEC)) - #define DEFAULT_LOWRES 0 #define DEFAULT_SKIPFRAME 0 #define DEFAULT_DIRECT_RENDERING TRUE #define DEFAULT_DEBUG_MV FALSE -#define DEFAULT_MAX_THREADS 1 +#define DEFAULT_MAX_THREADS 0 enum { @@ -234,7 +173,12 @@ gst_ffmpegviddec_base_init (GstFFMpegVidDecClass * klass) GST_DEBUG ("Couldn't get sink caps for decoder '%s'", in_plugin->name); sinkcaps = gst_caps_new_empty_simple ("unknown/unknown"); } - srccaps = gst_caps_new_empty_simple ("video/x-raw"); + srccaps = gst_ffmpeg_codectype_to_video_caps (NULL, + in_plugin->id, FALSE, in_plugin); + if (!srccaps) { + GST_DEBUG ("Couldn't get source caps for decoder '%s'", in_plugin->name); + srccaps = gst_caps_from_string ("video/x-raw"); + } /* pad templates */ sinktempl = gst_pad_template_new ("sink", GST_PAD_SINK, @@ -301,8 +245,11 @@ gst_ffmpegviddec_class_init (GstFFMpegVidDecClass * klass) static void gst_ffmpegviddec_init (GstFFMpegVidDec * ffmpegdec) { + GstFFMpegVidDecClass *klass = + (GstFFMpegVidDecClass *) G_OBJECT_GET_CLASS (ffmpegdec); + /* some ffmpeg data */ - ffmpegdec->context = avcodec_alloc_context (); + ffmpegdec->context = avcodec_alloc_context3 (klass->in_plugin); ffmpegdec->picture = avcodec_alloc_frame (); ffmpegdec->opened = FALSE; ffmpegdec->skip_frame = ffmpegdec->lowres = 0; @@ -321,10 +268,7 @@ gst_ffmpegviddec_finalize (GObject * object) ffmpegdec->context = NULL; } - if (ffmpegdec->picture != NULL) { - av_free (ffmpegdec->picture); - ffmpegdec->picture = NULL; - } + avcodec_free_frame (&ffmpegdec->picture); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -334,9 +278,6 @@ gst_ffmpegviddec_finalize (GObject * object) static void gst_ffmpegviddec_close (GstFFMpegVidDec * ffmpegdec) { - if (!ffmpegdec->opened) - return; - GST_LOG_OBJECT (ffmpegdec, "closing ffmpeg codec"); gst_caps_replace (&ffmpegdec->last_caps, NULL); @@ -345,10 +286,7 @@ gst_ffmpegviddec_close (GstFFMpegVidDec * ffmpegdec) gst_ffmpeg_avcodec_close (ffmpegdec->context); ffmpegdec->opened = FALSE; - if (ffmpegdec->context->palctrl) { - av_free (ffmpegdec->context->palctrl); - ffmpegdec->context->palctrl = NULL; - } + gst_buffer_replace (&ffmpegdec->palette, NULL); if (ffmpegdec->context->extradata) { av_free (ffmpegdec->context->extradata); @@ -374,10 +312,10 @@ gst_ffmpegviddec_open (GstFFMpegVidDec * ffmpegdec) oclass->in_plugin->name, oclass->in_plugin->id); switch (oclass->in_plugin->id) { - case CODEC_ID_RV10: - case CODEC_ID_RV30: - case CODEC_ID_RV20: - case CODEC_ID_RV40: + case AV_CODEC_ID_RV10: + case AV_CODEC_ID_RV30: + case AV_CODEC_ID_RV20: + case AV_CODEC_ID_RV40: ffmpegdec->is_realvideo = TRUE; break; default: @@ -397,6 +335,25 @@ could_not_open: } } +static void +gst_ffmpegviddec_get_palette (GstFFMpegVidDec * ffmpegdec, + GstVideoCodecState * state) +{ + GstStructure *str = gst_caps_get_structure (state->caps, 0); + const GValue *palette_v; + GstBuffer *palette; + + /* do we have a palette? */ + if ((palette_v = gst_structure_get_value (str, "palette_data"))) { + palette = gst_value_get_buffer (palette_v); + GST_DEBUG ("got palette data %p", palette); + if (gst_buffer_get_size (palette) >= AVPALETTE_SIZE) { + gst_buffer_replace (&ffmpegdec->palette, palette); + } + } +} + + static gboolean gst_ffmpegviddec_set_format (GstVideoDecoder * decoder, GstVideoCodecState * state) @@ -418,8 +375,8 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder, GST_OBJECT_LOCK (ffmpegdec); /* stupid check for VC1 */ - if ((oclass->in_plugin->id == CODEC_ID_WMV3) || - (oclass->in_plugin->id == CODEC_ID_VC1)) + if ((oclass->in_plugin->id == AV_CODEC_ID_WMV3) || + (oclass->in_plugin->id == AV_CODEC_ID_VC1)) oclass->in_plugin->id = gst_ffmpeg_caps_to_codecid (state->caps, NULL); /* close old session */ @@ -428,9 +385,6 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder, gst_ffmpegviddec_drain (ffmpegdec); GST_OBJECT_LOCK (ffmpegdec); gst_ffmpegviddec_close (ffmpegdec); - - /* and reset the defaults that were set when a context is created */ - avcodec_get_context_defaults (ffmpegdec->context); } gst_caps_replace (&ffmpegdec->last_caps, state->caps); @@ -441,6 +395,12 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder, ffmpegdec->context->release_buffer = gst_ffmpegviddec_release_buffer; ffmpegdec->context->draw_horiz_band = NULL; + /* reset coded_width/_height to prevent it being reused from last time when + * the codec is opened again, causing a mismatch and possible + * segfault/corruption. (Common scenario when renegotiating caps) */ + ffmpegdec->context->coded_width = 0; + ffmpegdec->context->coded_height = 0; + GST_LOG_OBJECT (ffmpegdec, "size %dx%d", ffmpegdec->context->width, ffmpegdec->context->height); @@ -452,6 +412,8 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder, GST_LOG_OBJECT (ffmpegdec, "size after %dx%d", ffmpegdec->context->width, ffmpegdec->context->height); + gst_ffmpegviddec_get_palette (ffmpegdec, state); + if (!ffmpegdec->context->time_base.den || !ffmpegdec->context->time_base.num) { GST_DEBUG_OBJECT (ffmpegdec, "forcing 25/1 framerate"); ffmpegdec->context->time_base.num = 1; @@ -460,7 +422,7 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder, /* workaround encoder bugs */ ffmpegdec->context->workaround_bugs |= FF_BUG_AUTODETECT; - ffmpegdec->context->error_recognition = 1; + ffmpegdec->context->err_recognition = 1; /* for slow cpus */ ffmpegdec->context->lowres = ffmpegdec->lowres; @@ -471,30 +433,16 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder, ffmpegdec->context->debug_mv = ffmpegdec->debug_mv; { - const gchar *env = g_getenv ("GST_AVVIDDEC_MAX_THREADS"); - int max_threads = ffmpegdec->max_threads; GstQuery *query; gboolean is_live; - if (env != NULL) { - if (g_str_equal (env, "auto")) - max_threads = 0; - else - max_threads = MAX (atoi (env), 0); - - if (max_threads != 1) { - GST_WARNING_OBJECT (ffmpegdec, "max threads forced to %d, this might " - "lead to decoding errors or artefacts", max_threads); - } - } - - if (max_threads == 0) { + if (ffmpegdec->max_threads == 0) { if (!(oclass->in_plugin->capabilities & CODEC_CAP_AUTO_THREADS)) ffmpegdec->context->thread_count = gst_ffmpeg_auto_max_threads (); else ffmpegdec->context->thread_count = 0; } else - ffmpegdec->context->thread_count = max_threads; + ffmpegdec->context->thread_count = ffmpegdec->max_threads; query = gst_query_new_latency (); is_live = FALSE; @@ -505,11 +453,10 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder, } gst_query_unref (query); - /* Slice based threading is broken in libav 0.8 */ if (is_live) - ffmpegdec->context->thread_type = 0; /* FF_THREAD_SLICE */ + ffmpegdec->context->thread_type = FF_THREAD_SLICE; else - ffmpegdec->context->thread_type = /* FF_THREAD_SLICE | */ FF_THREAD_FRAME; + ffmpegdec->context->thread_type = FF_THREAD_SLICE | FF_THREAD_FRAME; } /* open codec - we don't select an output pix_fmt yet, @@ -683,6 +630,7 @@ fallback: duplicate_frame: { GST_WARNING_OBJECT (ffmpegdec, "already alloc'ed output buffer for frame"); + gst_video_codec_frame_unref (frame); return -1; } no_frame: @@ -1155,12 +1103,12 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec, /* now decode the frame */ gst_avpacket_init (&packet, data, size); - if (ffmpegdec->context->palctrl) { + if (ffmpegdec->palette) { guint8 *pal; pal = av_packet_new_side_data (&packet, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE); - memcpy (pal, ffmpegdec->context->palctrl->palette, AVPALETTE_SIZE); + gst_buffer_extract (ffmpegdec->palette, 0, pal, AVPALETTE_SIZE); GST_DEBUG_OBJECT (ffmpegdec, "copy pal %p %p", &packet, pal); } @@ -1358,10 +1306,9 @@ gst_ffmpegviddec_handle_frame (GstVideoDecoder * decoder, gboolean do_padding; GST_LOG_OBJECT (ffmpegdec, - "Received new data of size %u, dts %" GST_TIME_FORMAT ", pts:%" - GST_TIME_FORMAT ", dur:%" GST_TIME_FORMAT, - gst_buffer_get_size (frame->input_buffer), - GST_TIME_ARGS (frame->dts), + "Received new data of size %" G_GSIZE_FORMAT ", dts %" GST_TIME_FORMAT + ", pts:%" GST_TIME_FORMAT ", dur:%" GST_TIME_FORMAT, + gst_buffer_get_size (frame->input_buffer), GST_TIME_ARGS (frame->dts), GST_TIME_ARGS (frame->pts), GST_TIME_ARGS (frame->duration)); if (!gst_buffer_map (frame->input_buffer, &minfo, GST_MAP_READ)) { @@ -1723,16 +1670,17 @@ gst_ffmpegviddec_register (GstPlugin * plugin) gchar *plugin_name; /* only video decoders */ - if (!in_plugin->decode || in_plugin->type != AVMEDIA_TYPE_VIDEO) + if (!av_codec_is_decoder (in_plugin) + || in_plugin->type != AVMEDIA_TYPE_VIDEO) goto next; /* no quasi-codecs, please */ - if (in_plugin->id == CODEC_ID_RAWVIDEO || - in_plugin->id == CODEC_ID_V210 || - in_plugin->id == CODEC_ID_V210X || - in_plugin->id == CODEC_ID_R210 || - (in_plugin->id >= CODEC_ID_PCM_S16LE && - in_plugin->id <= CODEC_ID_PCM_BLURAY)) { + if (in_plugin->id == AV_CODEC_ID_RAWVIDEO || + in_plugin->id == AV_CODEC_ID_V210 || + in_plugin->id == AV_CODEC_ID_V210X || + in_plugin->id == AV_CODEC_ID_R210 || + (in_plugin->id >= AV_CODEC_ID_PCM_S16LE && + in_plugin->id <= AV_CODEC_ID_PCM_BLURAY)) { goto next; } @@ -1803,20 +1751,20 @@ gst_ffmpegviddec_register (GstPlugin * plugin) * msmpeg4v3 same, as it outperforms divxdec for divx3 playback. * VC1/WMV3 are not working and thus unpreferred for now. */ switch (in_plugin->id) { - case CODEC_ID_MPEG4: - case CODEC_ID_MSMPEG4V3: - case CODEC_ID_H264: - case CODEC_ID_RV10: - case CODEC_ID_RV20: - case CODEC_ID_RV30: - case CODEC_ID_RV40: + case AV_CODEC_ID_MPEG4: + case AV_CODEC_ID_MSMPEG4V3: + case AV_CODEC_ID_H264: + case AV_CODEC_ID_RV10: + case AV_CODEC_ID_RV20: + case AV_CODEC_ID_RV30: + case AV_CODEC_ID_RV40: rank = GST_RANK_PRIMARY; break; /* DVVIDEO: we have a good dv decoder, fast on both ppc as well as x86. * They say libdv's quality is better though. leave as secondary. * note: if you change this, see the code in gstdv.c in good/ext/dv. */ - case CODEC_ID_DVVIDEO: + case AV_CODEC_ID_DVVIDEO: rank = GST_RANK_SECONDARY; break; default: |