diff options
author | Sebastian Dröge <sebastian@centricular.com> | 2013-12-27 11:04:01 +0100 |
---|---|---|
committer | Sebastian Dröge <sebastian@centricular.com> | 2013-12-27 11:04:01 +0100 |
commit | 4d912e229cc8d946e85ea967063619dd78a83ede (patch) | |
tree | b7f9d3b2308dd2892c921cf1dad50127788684c4 | |
parent | 6f5ff9b84f6e3ad68f3e777622282d5db6ccc0e0 (diff) |
Imported Upstream version 1.2.2upstream/1.2.2
-rw-r--r-- | ChangeLog | 75 | ||||
-rw-r--r-- | NEWS | 2 | ||||
-rwxr-xr-x | configure | 36 | ||||
-rw-r--r-- | configure.ac | 6 | ||||
-rw-r--r-- | ext/libav/gstavaudenc.c | 26 | ||||
-rw-r--r-- | ext/libav/gstavaudenc.h | 1 | ||||
-rw-r--r-- | ext/libav/gstavcodecmap.c | 24 | ||||
-rw-r--r-- | ext/libav/gstavcodecmap.h | 42 | ||||
-rw-r--r-- | ext/libav/gstavviddec.c | 82 | ||||
-rw-r--r-- | ext/libav/gstavvidenc.c | 24 | ||||
-rw-r--r-- | ext/libav/gstavvidenc.h | 1 | ||||
-rw-r--r-- | gst-libav.doap | 10 | ||||
-rw-r--r-- | gst-libav.spec | 2 |
13 files changed, 291 insertions, 40 deletions
@@ -1,9 +1,80 @@ +=== release 1.2.2 === + +2013-12-26 Sebastian Dröge <slomo@coaxion.net> + + * configure.ac: + releasing 1.2.2 + +2013-12-07 11:35:09 +0100 Mark Nauwelaerts <mnauw@users.sourceforge.net> + + * ext/libav/gstavviddec.c: + avviddec: improve buffer handling and semantics + ... so as to focus on providing *a* buffer rather than one (too) tied + to a frame, in particular allowing multiple allocations related to a frame. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=697806 + +2013-11-26 20:57:37 +0100 Mark Nauwelaerts <mnauw@users.sourceforge.net> + + * ext/libav/gstavviddec.c: + avviddec: discard unused input frames + ... to avoid these piling up in list of pending frames. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=693772 + +2013-11-26 20:55:43 +0100 Mark Nauwelaerts <mnauw@users.sourceforge.net> + + * ext/libav/gstavviddec.c: + avviddec: really release frame at proper time + ... by also removing it from the pending list of frames, + where it may still be in if it has never been submitted to _finish. + This could happen if is a decode-only frame, or in skipped decoding + situation, ... + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=693772 + +2013-12-07 12:10:13 +0100 Mark Nauwelaerts <mnauw@users.sourceforge.net> + + * ext/libav/gstavvidenc.c: + avvidenc: plug input_state leak + +2013-12-02 20:21:34 +0100 Mark Nauwelaerts <mnauw@users.sourceforge.net> + + * ext/libav/gstavviddec.c: + avviddec: only use upstream framerate if really specified + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=704161 + +2013-10-26 09:34:30 +0100 Tim-Philipp Müller <tim@centricular.com> + + * ext/libav/gstavaudenc.c: + avaudenc: post better error message if experimental codecs don't work + https://bugzilla.gnome.org/show_bug.cgi?id=691617 + +2013-10-26 09:09:28 +0100 Tim-Philipp Müller <tim@centricular.com> + + * ext/libav/gstavcodecmap.c: + codecmap: use TRUE for boolean fields in caps + +2013-10-14 14:50:57 -0600 Greg Rutz <greg@gsr-tek.com> + + * ext/libav/gstavaudenc.c: + * ext/libav/gstavaudenc.h: + * ext/libav/gstavcodecmap.c: + * ext/libav/gstavcodecmap.h: + * ext/libav/gstavvidenc.c: + * ext/libav/gstavvidenc.h: + avenc: Add compliance property + Add a new property to GstFFMpegVidEnc and GstFFMpegAudEnc to supply + the "strict compliance" value to AVCodecContext + https://bugzilla.gnome.org/show_bug.cgi?id=691617 + === release 1.2.1 === -2013-11-09 Sebastian Dröge <slomo@coaxion.net> +2013-11-09 16:02:14 +0100 Sebastian Dröge <sebastian@centricular.com> + * ChangeLog: + * NEWS: + * RELEASE: * configure.ac: - releasing 1.2.1 + * gst-libav.doap: + Release 1.2.1 2013-11-04 23:20:17 +0000 Tim-Philipp Müller <tim@centricular.com> @@ -1,2 +1,2 @@ -This is GStreamer Libav Plugins 1.2.1 +This is GStreamer Libav Plugins 1.2.2 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for GStreamer libav 1.2.1. +# Generated by GNU Autoconf 2.69 for GStreamer libav 1.2.2. # # Report bugs to <http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer>. # @@ -591,8 +591,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='GStreamer libav' PACKAGE_TARNAME='gst-libav' -PACKAGE_VERSION='1.2.1' -PACKAGE_STRING='GStreamer libav 1.2.1' +PACKAGE_VERSION='1.2.2' +PACKAGE_STRING='GStreamer libav 1.2.2' PACKAGE_BUGREPORT='http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer' PACKAGE_URL='' @@ -1519,7 +1519,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures GStreamer libav 1.2.1 to adapt to many kinds of systems. +\`configure' configures GStreamer libav 1.2.2 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1590,7 +1590,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of GStreamer libav 1.2.1:";; + short | recursive ) echo "Configuration of GStreamer libav 1.2.2:";; esac cat <<\_ACEOF @@ -1759,7 +1759,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -GStreamer libav configure 1.2.1 +GStreamer libav configure 1.2.2 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2174,7 +2174,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by GStreamer libav $as_me 1.2.1, which was +It was created by GStreamer libav $as_me 1.2.2, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3152,7 +3152,7 @@ fi # Define the identity of the package. PACKAGE='gst-libav' - VERSION='1.2.1' + VERSION='1.2.2' cat >>confdefs.h <<_ACEOF @@ -3362,9 +3362,9 @@ END fi - PACKAGE_VERSION_MAJOR=$(echo 1.2.1 | cut -d'.' -f1) - PACKAGE_VERSION_MINOR=$(echo 1.2.1 | cut -d'.' -f2) - PACKAGE_VERSION_MICRO=$(echo 1.2.1 | cut -d'.' -f3) + PACKAGE_VERSION_MAJOR=$(echo 1.2.2 | cut -d'.' -f1) + PACKAGE_VERSION_MINOR=$(echo 1.2.2 | cut -d'.' -f2) + PACKAGE_VERSION_MICRO=$(echo 1.2.2 | cut -d'.' -f3) @@ -3375,7 +3375,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking nano version" >&5 $as_echo_n "checking nano version... " >&6; } - NANO=$(echo 1.2.1 | cut -d'.' -f4) + NANO=$(echo 1.2.2 | cut -d'.' -f4) if test x"$NANO" = x || test "x$NANO" = "x0" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: 0 (release)" >&5 @@ -8021,10 +8021,10 @@ fi done - GST_CURRENT=201 + GST_CURRENT=202 GST_REVISION=0 - GST_AGE=201 - GST_LIBVERSION=201:0:201 + GST_AGE=202 + GST_LIBVERSION=202:0:202 @@ -12350,7 +12350,7 @@ CC="$lt_save_CC" GST_REQ=1.2.0 -GST_PBREQ=1.2.0 +GST_PBREQ=1.2.2 ORC_REQ=0.4.16 @@ -18233,7 +18233,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by GStreamer libav $as_me 1.2.1, which was +This file was extended by GStreamer libav $as_me 1.2.2, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -18299,7 +18299,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -GStreamer libav config.status 1.2.1 +GStreamer libav config.status 1.2.2 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index eb3e481..c1066ee 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ(2.62) dnl initialize autoconf dnl when going to/from release please set the nano (fourth number) right ! dnl releases only do Wall, cvs and prerelease does Werror too -AC_INIT(GStreamer libav, 1.2.1, +AC_INIT(GStreamer libav, 1.2.2, http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer, gst-libav) @@ -42,11 +42,11 @@ GST_API_VERSION=1.0 AC_SUBST(GST_API_VERSION) AG_GST_LIBTOOL_PREPARE -AS_LIBTOOL(GST, 201, 0, 201) +AS_LIBTOOL(GST, 202, 0, 202) dnl *** required versions of GStreamer stuff *** GST_REQ=1.2.0 -GST_PBREQ=1.2.0 +GST_PBREQ=1.2.2 ORC_REQ=0.4.16 ORC_CHECK([$ORC_REQ]) diff --git a/ext/libav/gstavaudenc.c b/ext/libav/gstavaudenc.c index ee758fa..83a2eee 100644 --- a/ext/libav/gstavaudenc.c +++ b/ext/libav/gstavaudenc.c @@ -52,6 +52,7 @@ enum PROP_0, PROP_BIT_RATE, PROP_RTP_PAYLOAD_SIZE, + PROP_COMPLIANCE, }; /* A number of function prototypes are given so we can refer to them later. */ @@ -151,6 +152,11 @@ gst_ffmpegaudenc_class_init (GstFFMpegAudEncClass * klass) g_param_spec_int ("bitrate", "Bit Rate", "Target Audio Bitrate", 0, G_MAXINT, DEFAULT_AUDIO_BITRATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_COMPLIANCE, + g_param_spec_enum ("compliance", "Compliance", + "Adherence of the encoder to the specifications", + GST_TYPE_FFMPEG_COMPLIANCE, FFMPEG_DEFAULT_COMPLIANCE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); gobject_class->finalize = gst_ffmpegaudenc_finalize; @@ -174,6 +180,8 @@ gst_ffmpegaudenc_init (GstFFMpegAudEnc * ffmpegaudenc) ffmpegaudenc->context = avcodec_alloc_context3 (klass->in_plugin); ffmpegaudenc->opened = FALSE; + ffmpegaudenc->compliance = FFMPEG_DEFAULT_COMPLIANCE; + gst_audio_encoder_set_drainable (GST_AUDIO_ENCODER (ffmpegaudenc), TRUE); } @@ -265,7 +273,7 @@ gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info) } /* if we set it in _getcaps we should set it also in _link */ - ffmpegaudenc->context->strict_std_compliance = -1; + ffmpegaudenc->context->strict_std_compliance = ffmpegaudenc->compliance; /* user defined properties */ if (ffmpegaudenc->bitrate > 0) { @@ -316,6 +324,16 @@ gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info) if (avcodec_get_context_defaults3 (ffmpegaudenc->context, oclass->in_plugin) < 0) GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults"); + + if ((oclass->in_plugin->capabilities & CODEC_CAP_EXPERIMENTAL) && + ffmpegaudenc->compliance != GST_FFMPEG_EXPERIMENTAL) { + GST_ELEMENT_ERROR (ffmpegaudenc, LIBRARY, SETTINGS, + ("Codec is experimental, but settings don't allow encoders to " + "produce output of experimental quality"), + ("This codec may not create output that is conformant to the specs " + "or of good quality. If you must use it anyway, set the " + "compliance property to experimental")); + } return FALSE; } @@ -641,6 +659,9 @@ gst_ffmpegaudenc_set_property (GObject * object, case PROP_RTP_PAYLOAD_SIZE: ffmpegaudenc->rtp_payload_size = g_value_get_int (value); break; + case PROP_COMPLIANCE: + ffmpegaudenc->compliance = g_value_get_enum (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -665,6 +686,9 @@ gst_ffmpegaudenc_get_property (GObject * object, case PROP_RTP_PAYLOAD_SIZE: g_value_set_int (value, ffmpegaudenc->rtp_payload_size); break; + case PROP_COMPLIANCE: + g_value_set_enum (value, ffmpegaudenc->compliance); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/ext/libav/gstavaudenc.h b/ext/libav/gstavaudenc.h index b01184f..bce0900 100644 --- a/ext/libav/gstavaudenc.h +++ b/ext/libav/gstavaudenc.h @@ -42,6 +42,7 @@ struct _GstFFMpegAudEnc /* cache */ gint bitrate; gint rtp_payload_size; + gint compliance; /* other settings are copied over straight, * include a context here, rather than copy-and-past it from avcodec.h */ diff --git a/ext/libav/gstavcodecmap.c b/ext/libav/gstavcodecmap.c index c247d01..a5be63e 100644 --- a/ext/libav/gstavcodecmap.c +++ b/ext/libav/gstavcodecmap.c @@ -66,6 +66,28 @@ static const struct AV_CH_STEREO_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT} }; +GType +gst_ffmpeg_compliance_get_type (void) +{ + static GType ffmpeg_compliance_type = 0; + static const GEnumValue compliance_types[] = { + {GST_FFMPEG_VERY_STRICT, "Strictly conform to older spec", + "verystrict"}, + {GST_FFMPEG_STRICT, "Strictly conform to current spec", "strict"}, + {GST_FFMPEG_NORMAL, "Normal behavior", "normal"}, + {GST_FFMPEG_UNOFFICIAL, "Allow unofficial extensions", "unofficial"}, + {GST_FFMPEG_EXPERIMENTAL, "Allow nonstandardized experimental things", + "experimental"}, + {0, NULL, NULL} + }; + + if (!ffmpeg_compliance_type) { + ffmpeg_compliance_type = + g_enum_register_static ("GstFFMpegCompliance", compliance_types); + } + return ffmpeg_compliance_type; +} + static guint64 gst_ffmpeg_channel_positions_to_layout (GstAudioChannelPosition * pos, gint channels) @@ -931,7 +953,7 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, case AV_CODEC_ID_LJPEG: caps = gst_ff_vid_caps_new (context, NULL, codec_id, encode, "image/jpeg", - "parsed", G_TYPE_BOOLEAN, 1, NULL); + "parsed", G_TYPE_BOOLEAN, TRUE, NULL); break; case AV_CODEC_ID_SP5X: diff --git a/ext/libav/gstavcodecmap.h b/ext/libav/gstavcodecmap.h index 01ce9b1..f392f96 100644 --- a/ext/libav/gstavcodecmap.h +++ b/ext/libav/gstavcodecmap.h @@ -25,6 +25,48 @@ #include <gst/audio/audio.h> #include <gst/video/video.h> +/** + * GstFFMpegCompliance: + * @GST_FFMPEG_VERY_STRICT: Strictly conform to an older + * more strict version of the spec or reference software + * @GST_FFMPEG_STRICT: Strictly conform to all the things + * in the spec no matter what consequences. + * @GST_FFMPEG_NORMAL: + * @GST_FFMPEG_UNOFFICIAL: Allow unofficial extensions + * @GST_FFMPEG_EXPERIMENTAL: Allow nonstandardized + * experimental things. + * + * This setting instructs libav on how strictly it should follow the + * associated standard. + * + * From avcodec.h: + * Setting this to STRICT or higher means the encoder and decoder will + * generally do stupid things, whereas setting it to unofficial or lower + * will mean the encoder might produce output that is not supported by all + * spec-compliant decoders. Decoders don't differentiate between normal, + * unofficial and experimental (that is, they always try to decode things + * when they can) unless they are explicitly asked to behave stupidly + * (=strictly conform to the specs) + */ +typedef enum { + GST_FFMPEG_VERY_STRICT = FF_COMPLIANCE_VERY_STRICT, + GST_FFMPEG_STRICT = FF_COMPLIANCE_STRICT, + GST_FFMPEG_NORMAL = FF_COMPLIANCE_NORMAL, + GST_FFMPEG_UNOFFICIAL = FF_COMPLIANCE_UNOFFICIAL, + GST_FFMPEG_EXPERIMENTAL = FF_COMPLIANCE_EXPERIMENTAL, +} GstFFMpegCompliance; + +/* + * _compliance_get_type () Returns an enum type that can be + * used as a property to indicate desired FFMpeg adherence to + * an associated specification + */ + +GType +gst_ffmpeg_compliance_get_type (void); +#define GST_TYPE_FFMPEG_COMPLIANCE (gst_ffmpeg_compliance_get_type ()) +#define FFMPEG_DEFAULT_COMPLIANCE GST_FFMPEG_NORMAL + /* * _codecid_to_caps () gets the GstCaps that belongs to * a certain CodecID for a pad with compressed data. diff --git a/ext/libav/gstavviddec.c b/ext/libav/gstavviddec.c index 0635767..3453231 100644 --- a/ext/libav/gstavviddec.c +++ b/ext/libav/gstavviddec.c @@ -525,6 +525,7 @@ typedef struct GstVideoCodecFrame *frame; gboolean mapped; GstVideoFrame vframe; + GstBuffer *buffer; } GstFFMpegVidDecVideoFrame; static GstFFMpegVidDecVideoFrame * @@ -539,11 +540,13 @@ gst_ffmpegviddec_video_frame_new (GstVideoCodecFrame * frame) } static void -gst_ffmpegviddec_video_frame_free (GstFFMpegVidDecVideoFrame * frame) +gst_ffmpegviddec_video_frame_free (GstFFMpegVidDec * ffmpegdec, + GstFFMpegVidDecVideoFrame * frame) { if (frame->mapped) gst_video_frame_unmap (&frame->vframe); - gst_video_codec_frame_unref (frame->frame); + gst_video_decoder_release_frame (GST_VIDEO_DECODER (ffmpegdec), frame->frame); + gst_buffer_replace (&frame->buffer, NULL); g_slice_free (GstFFMpegVidDecVideoFrame, frame); } @@ -567,6 +570,8 @@ gst_ffmpegviddec_get_buffer (AVCodecContext * context, AVFrame * picture) * picture back from ffmpeg we can use this to correctly timestamp the output * buffer */ picture->reordered_opaque = context->reordered_opaque; + GST_DEBUG_OBJECT (ffmpegdec, "opaque value SN %d", + (gint32) picture->reordered_opaque); frame = gst_video_decoder_get_frame (GST_VIDEO_DECODER (ffmpegdec), @@ -574,6 +579,11 @@ gst_ffmpegviddec_get_buffer (AVCodecContext * context, AVFrame * picture) if (G_UNLIKELY (frame == NULL)) goto no_frame; + /* now it has a buffer allocated, so it is real and will also + * be _released */ + GST_VIDEO_CODEC_FRAME_FLAG_UNSET (frame, + GST_VIDEO_CODEC_FRAME_FLAG_DECODE_ONLY); + if (G_UNLIKELY (frame->output_buffer != NULL)) goto duplicate_frame; @@ -597,9 +607,16 @@ gst_ffmpegviddec_get_buffer (AVCodecContext * context, AVFrame * picture) if (ret != GST_FLOW_OK) goto alloc_failed; + /* piggy-backed alloc'ed on the frame, + * and there was much rejoicing and we are grateful. + * Now take away buffer from frame, we will give it back later when decoded. + * This allows multiple request for a buffer per frame; unusual but possible. */ + gst_buffer_replace (&dframe->buffer, frame->output_buffer); + gst_buffer_replace (&frame->output_buffer, NULL); + /* Fill avpicture */ info = &ffmpegdec->output_state->info; - if (!gst_video_frame_map (&dframe->vframe, info, dframe->frame->output_buffer, + if (!gst_video_frame_map (&dframe->vframe, info, dframe->buffer, GST_MAP_READWRITE)) goto invalid_frame; dframe->mapped = TRUE; @@ -627,7 +644,7 @@ gst_ffmpegviddec_get_buffer (AVCodecContext * context, AVFrame * picture) } gst_video_frame_unmap (&dframe->vframe); dframe->mapped = FALSE; - gst_buffer_replace (&frame->output_buffer, NULL); + gst_buffer_replace (&dframe->buffer, NULL); ffmpegdec->current_dr = FALSE; goto no_dr; @@ -644,7 +661,7 @@ gst_ffmpegviddec_get_buffer (AVCodecContext * context, AVFrame * picture) * the opaque data. */ picture->type = FF_BUFFER_TYPE_USER; - GST_LOG_OBJECT (ffmpegdec, "returned frame %p", frame->output_buffer); + GST_LOG_OBJECT (ffmpegdec, "returned frame %p", dframe->buffer); return 0; @@ -669,8 +686,7 @@ invalid_frame: { /* alloc default buffer when we can't get one from downstream */ GST_LOG_OBJECT (ffmpegdec, "failed to map frame, fallback alloc"); - gst_buffer_unref (frame->output_buffer); - frame->output_buffer = NULL; + gst_buffer_replace (&dframe->buffer, NULL); goto fallback; } fallback: @@ -696,6 +712,8 @@ no_frame: } } +/* this should havesame effect as _get_buffer wrt opaque metadata, + * but preserving current content, if any */ static int gst_ffmpegviddec_reget_buffer (AVCodecContext * context, AVFrame * picture) { @@ -756,7 +774,7 @@ gst_ffmpegviddec_release_buffer (AVCodecContext * context, AVFrame * picture) ffmpegdec = (GstFFMpegVidDec *) context->opaque; frame = (GstFFMpegVidDecVideoFrame *) picture->opaque; - GST_DEBUG_OBJECT (ffmpegdec, "release frame %d", + GST_DEBUG_OBJECT (ffmpegdec, "release frame SN %d", frame->frame->system_frame_number); /* check if it was our buffer */ @@ -768,7 +786,7 @@ gst_ffmpegviddec_release_buffer (AVCodecContext * context, AVFrame * picture) /* we remove the opaque data now */ picture->opaque = NULL; - gst_ffmpegviddec_video_frame_free (frame); + gst_ffmpegviddec_video_frame_free (ffmpegdec, frame); /* zero out the reference in ffmpeg */ for (i = 0; i < 4; i++) { @@ -920,7 +938,8 @@ gst_ffmpegviddec_negotiate (GstFFMpegVidDec * ffmpegdec, out_info->interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE; /* try to find a good framerate */ - if (in_info->fps_d) { + if ((in_info->fps_d && in_info->fps_n) || + GST_VIDEO_INFO_FLAG_IS_SET (in_info, GST_VIDEO_FLAG_VARIABLE_FPS)) { /* take framerate from input when it was specified (#313970) */ fps_n = in_info->fps_n; fps_d = in_info->fps_d; @@ -1205,6 +1224,10 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec, out_dframe = ffmpegdec->picture->opaque; out_frame = gst_video_codec_frame_ref (out_dframe->frame); + /* also give back a buffer allocated by the frame, if any */ + gst_buffer_replace (&out_frame->output_buffer, out_dframe->buffer); + gst_buffer_replace (&out_dframe->buffer, NULL); + GST_DEBUG_OBJECT (ffmpegdec, "pts %" G_GUINT64_FORMAT " duration %" G_GUINT64_FORMAT, out_frame->pts, out_frame->duration); @@ -1251,6 +1274,41 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec, GST_VIDEO_BUFFER_FLAG_INTERLACED); } + /* cleaning time */ + /* so we decoded this frame, frames preceding it in decoding order + * that still do not have a buffer allocated seem rather useless, + * and can be discarded, due to e.g. misparsed bogus frame + * or non-keyframe in skipped decoding, ... + * In any case, not likely to be seen again, so discard those, + * before they pile up and/or mess with timestamping */ + { + GList *l, *ol; + GstVideoDecoder *dec = GST_VIDEO_DECODER (ffmpegdec); + gboolean old = TRUE; + + ol = l = gst_video_decoder_get_frames (dec); + while (l) { + GstVideoCodecFrame *tmp = l->data; + + if (tmp == frame) + old = FALSE; + + if (old && GST_VIDEO_CODEC_FRAME_IS_DECODE_ONLY (tmp)) { + GST_LOG_OBJECT (dec, + "discarding ghost frame %p (#%d) PTS:%" GST_TIME_FORMAT " DTS:%" + GST_TIME_FORMAT, tmp, tmp->system_frame_number, + GST_TIME_ARGS (tmp->pts), GST_TIME_ARGS (tmp->dts)); + /* drop extra ref and remove from frame list */ + gst_video_decoder_release_frame (dec, tmp); + } else { + /* drop extra ref we got */ + gst_video_codec_frame_unref (tmp); + } + l = l->next; + } + g_list_free (ol); + } + *ret = gst_video_decoder_finish_frame (GST_VIDEO_DECODER (ffmpegdec), out_frame); @@ -1386,6 +1444,10 @@ gst_ffmpegviddec_handle_frame (GstVideoDecoder * decoder, return GST_FLOW_ERROR; } + /* treat frame as void until a buffer is requested for it */ + GST_VIDEO_CODEC_FRAME_FLAG_SET (frame, + GST_VIDEO_CODEC_FRAME_FLAG_DECODE_ONLY); + bdata = minfo.data; bsize = minfo.size; diff --git a/ext/libav/gstavvidenc.c b/ext/libav/gstavvidenc.c index 83e052c..6f32627 100644 --- a/ext/libav/gstavvidenc.c +++ b/ext/libav/gstavvidenc.c @@ -62,7 +62,8 @@ enum PROP_ME_METHOD, PROP_BUFSIZE, PROP_RTP_PAYLOAD_SIZE, - PROP_CFG_BASE + PROP_CFG_BASE, + PROP_COMPLIANCE, }; #define GST_TYPE_ME_METHOD (gst_ffmpegvidenc_me_method_get_type()) @@ -206,8 +207,14 @@ gst_ffmpegvidenc_class_init (GstFFMpegVidEncClass * klass) "RTP Payload Size", "Target GOB length", 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_COMPLIANCE, + g_param_spec_enum ("compliance", "Compliance", + "Adherence of the encoder to the specifications", + GST_TYPE_FFMPEG_COMPLIANCE, FFMPEG_DEFAULT_COMPLIANCE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /* register additional properties, possibly dependent on the exact CODEC */ - gst_ffmpeg_cfg_install_property (klass, PROP_CFG_BASE); + gst_ffmpeg_cfg_install_property (klass, PROP_COMPLIANCE); venc_class->start = gst_ffmpegvidenc_start; venc_class->stop = gst_ffmpegvidenc_stop; @@ -239,6 +246,7 @@ gst_ffmpegvidenc_init (GstFFMpegVidEnc * ffmpegenc) ffmpegenc->buffer_size = 512 * 1024; ffmpegenc->gop_size = DEFAULT_VIDEO_GOP_SIZE; ffmpegenc->rtp_payload_size = 0; + ffmpegenc->compliance = FFMPEG_DEFAULT_COMPLIANCE; ffmpegenc->lmin = 2; ffmpegenc->lmax = 31; @@ -301,7 +309,7 @@ gst_ffmpegvidenc_set_format (GstVideoEncoder * encoder, } /* if we set it in _getcaps we should set it also in _link */ - ffmpegenc->context->strict_std_compliance = -1; + ffmpegenc->context->strict_std_compliance = ffmpegenc->compliance; /* user defined properties */ ffmpegenc->context->bit_rate = ffmpegenc->bitrate; @@ -761,6 +769,9 @@ gst_ffmpegvidenc_set_property (GObject * object, case PROP_RTP_PAYLOAD_SIZE: ffmpegenc->rtp_payload_size = g_value_get_int (value); break; + case PROP_COMPLIANCE: + ffmpegenc->compliance = g_value_get_enum (value); + break; default: if (!gst_ffmpeg_cfg_set_property (object, value, pspec)) G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -794,6 +805,9 @@ gst_ffmpegvidenc_get_property (GObject * object, case PROP_RTP_PAYLOAD_SIZE: g_value_set_int (value, ffmpegenc->rtp_payload_size); break; + case PROP_COMPLIANCE: + g_value_set_enum (value, ffmpegenc->compliance); + break; default: if (!gst_ffmpeg_cfg_get_property (object, value, pspec)) G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -845,6 +859,10 @@ gst_ffmpegvidenc_stop (GstVideoEncoder * encoder) g_free (ffmpegenc->working_buf); ffmpegenc->working_buf = NULL; } + if (ffmpegenc->input_state) { + gst_video_codec_state_unref (ffmpegenc->input_state); + ffmpegenc->input_state = NULL; + } return TRUE; } diff --git a/ext/libav/gstavvidenc.h b/ext/libav/gstavvidenc.h index d19dc39..e841d6c 100644 --- a/ext/libav/gstavvidenc.h +++ b/ext/libav/gstavvidenc.h @@ -49,6 +49,7 @@ struct _GstFFMpegVidEnc gint gop_size; gint buffer_size; gint rtp_payload_size; + gint compliance; guint8 *working_buf; gsize working_buf_size; diff --git a/gst-libav.doap b/gst-libav.doap index c15530e..02f040d 100644 --- a/gst-libav.doap +++ b/gst-libav.doap @@ -34,6 +34,16 @@ colorspace conversion elements. <release> <Version> + <revision>1.2.2</revision> + <branch>1.2</branch> + <name></name> + <created>2013-12-26</created> + <file-release rdf:resource="http://gstreamer.freedesktop.org/src/gst-libav/gst-libav-1.2.2.tar.xz" /> + </Version> + </release> + + <release> + <Version> <revision>1.2.1</revision> <branch>1.2</branch> <name></name> diff --git a/gst-libav.spec b/gst-libav.spec index 761aaab..032061b 100644 --- a/gst-libav.spec +++ b/gst-libav.spec @@ -4,7 +4,7 @@ %define gst_majorminor 1.0 Name: %{gstreamer}-libav -Version: 1.2.1 +Version: 1.2.2 Release: 1 Summary: GStreamer Streaming-media framework plug-in using libav (FFmpeg). Group: Libraries/Multimedia |