aboutsummaryrefslogtreecommitdiff
path: root/ext/libav/gstavviddec.c
diff options
context:
space:
mode:
authorSebastian Dröge <slomo@circular-chaos.org>2013-07-14 12:53:31 +0200
committerSebastian Dröge <slomo@circular-chaos.org>2013-07-14 12:53:31 +0200
commit506fe9d1810310128adfeb65a9cffd014450ac11 (patch)
tree63b597f6602b0587b4efcc97df3d1e005a90a5ed /ext/libav/gstavviddec.c
parentaa9289484c3502e9e3f6df9dda964ffe2510092d (diff)
Imported Upstream version 1.1.2upstream/1.1.2
Diffstat (limited to 'ext/libav/gstavviddec.c')
-rw-r--r--ext/libav/gstavviddec.c204
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: