Merge branch 'master' into 0.11

Conflicts:
	configure.ac
	gst-libs/gst/pbutils/Makefile.am
This commit is contained in:
Wim Taymans 2011-02-28 11:47:44 +01:00
commit c6dd11981d
231 changed files with 15783 additions and 2864 deletions

1663
ChangeLog

File diff suppressed because it is too large Load diff

129
NEWS
View file

@ -1,4 +1,131 @@
This is GStreamer Base Plug-ins 0.10.31, "Dance Like It's 1982"
This is GStreamer Base Plug-ins 0.10.32, "Your Life You Like It Well"
Changes since 0.10.31:
* GLib requirement is now >= 2.22, gobject-introspection >= 0.9.12
* New encodebin element
* New encoding profile and encoding targets API in pbutils
* audioresample: corrected buffer duration calculation to account for nonzero initial timestamp
* audioresample: provide as much valid output ts and offset as valid input
* audioresample: push half a history length, instead of a full history length, at end-of-stream
so that output segment and input segment have same duration
* decodebin2: deprecate new-decoded-pad and removed-decoded-pad signals (use "pad-added" and "pad-removed" instead)
* multifdsink: add first and last buffer's timestamp to the stats; only keep last valid timestamp
* oggdemux: extract more tags (vorbis comment headers, Kate)
* oggdemux: ignore header pages when looking for keyframe; set headers on caps
* oggdemux: fix interpretation of Theora granule position and parsing of Theora size
* oggparse: Set DELTA_UNIT on buffers
* playbin2: delay stream-changed messages, fixing KATE subtitle recognition
* textoverlay: make text, xpos, ypos, color, and silent properties controllable
* typefinding: (E)AC-3 and ISO typefinder improvements; add yuv4mpeg typefinder
* typefinding: add "stream-format" to h264 caps, and framed=false to DTS caps
* typefinding: assume EBML files without doctype are matroska
* videorate: fix behaviour for frame rate cap changes
* vorbisdec: avoid using invalid timestamps; keep timestamps when no decoded output
* ximagesink, xvimagesink: add read-only window-width and window-height properties
* baseaudiopay: fix timestamps on buffer lists
* baseaudiosink: protect against ringbuffer disappearing while in a query
* basedepay: add support for buffer lists in the depayloader
* basertppay: use RTP base time when invalid timestamps
* rtpbuffer: relax arrangement for RTP bufferlists
* rtpdepayloader: add support for getting events
* rtppayload: copy applied rate to segment
* sdp: add method to check for multicast addresses
* sdp: only parse TTL for IP4 addresses
* video: add 8-bit paletted RGB, YUV9, YVU9 and IYU1 video formats
* video: return correct component width/height for A420
Bugs fixed since 0.10.31:
* 619778 : oggdemux: fails on zero-length pages with Patent_Absurdity_HD_3540kbit.ogv
* 586570 : Add GAP Flag support to audioresample
* 623413 : pbutils: Add/Fix some media descriptions
* 627476 : New profile library and encoding plugin
* 629349 : [oggdemux] extract stream tags for tagreadbin and transcoding
* 632667 : [ximagesink] added read-only properties window-width and window-height
* 634397 : [multifdsink] [PATCH] Add the timestamp of the first and last buffer to the stats
* 634522 : gst-visualize-m.m imports but doesn't use File::Basename
* 635231 : baseaudiosink: protect against ringbuffer disappearing while in a query
* 636198 : decodebin2: " removed-decoded-pad " signal never fired
* 636769 : [appsink] Flushing property is never reset
* 636827 : Usage of gst_caps_interset where gst_caps_can_intersect was intended?
* 637324 : oggdemux: unable to demux Ogg files with Skeleton in push mode
* 637377 : timeoverlay: add missing break
* 637519 : ogg: implement packet duration query for kate streams
* 637586 : playbin2 fails to recognize subtitle caps from katedec
* 637735 : [encoding-profile] automatic load/save support and registry
* 637758 : [exiftag] Generates buffers with uninitialized data during taglist- > exif buffer serialization
* 637822 : oggdemux: allocate buffers using gst_buffer_new_and_alloc
* 637927 : oggdemux: set headers on caps
* 638200 : [oggdemux] fails to playback video file
* 638276 : oggstream: when the last keyframe position is not known, do not use -1
* 638859 : textoverlay: make misc. properties controllable
* 638901 : [encodebin] proper element documentation
* 638903 : [encodebin] missing-plugin support
* 638961 : Small configure bashism 0.10.31.2
* 639039 : gobject-introspection: GstPbutils gir scanner fails to link with gold linker
* 639121 : oggdemux: outdated comment for gst_ogg_demux_submit_buffer()
* 639215 : examples: Allow building with newer GTK+
* 639730 : discoverer: Validate timeouts before processing them
* 639755 : discoverer: Clean up callbacks in dispose()
* 639778 : discoverer: Drop new stream tags once preroll is done
* 639790 : [gdp] Fix metadata g_warning
* 639747 : Please export GST_TYPE_APP_STREAM_TYPE
* 553244 : theoraparse doesn't work at all (throws criticals and asserts)
API added since 0.10.31:
* gst_app_stream_type_get_type()
* gst_discoverer_info_get_seekable()
* gst_encoding_audio_profile_get_type()
* gst_encoding_audio_profile_new()
* gst_encoding_container_profile_add_profile()
* gst_encoding_container_profile_contains_profile()
* gst_encoding_container_profile_get_profiles()
* gst_encoding_container_profile_get_type()
* gst_encoding_container_profile_new()
* gst_encoding_list_all_targets()
* gst_encoding_list_available_categories()
* gst_encoding_profile_find()
* gst_encoding_profile_get_description()
* gst_encoding_profile_get_format()
* gst_encoding_profile_get_input_caps()
* gst_encoding_profile_get_name()
* gst_encoding_profile_get_presence()
* gst_encoding_profile_get_preset()
* gst_encoding_profile_get_restriction()
* gst_encoding_profile_get_type()
* gst_encoding_profile_get_type_nick()
* gst_encoding_profile_is_equal()
* gst_encoding_profile_set_description()
* gst_encoding_profile_set_format()
* gst_encoding_profile_set_name()
* gst_encoding_profile_set_presence()
* gst_encoding_profile_set_preset()
* gst_encoding_profile_set_restriction()
* gst_encoding_target_add_profile()
* gst_encoding_target_get_category()
* gst_encoding_target_get_description()
* gst_encoding_target_get_name()
* gst_encoding_target_get_profile()
* gst_encoding_target_get_profiles()
* gst_encoding_target_get_type()
* gst_encoding_target_load()
* gst_encoding_target_load_from_file()
* gst_encoding_target_new()
* gst_encoding_target_save()
* gst_encoding_target_save_to_file()
* gst_encoding_video_profile_get_pass()
* gst_encoding_video_profile_get_type()
* gst_encoding_video_profile_get_variableframerate()
* gst_encoding_video_profile_new()
* gst_encoding_video_profile_set_pass()
* gst_encoding_video_profile_set_variableframerate()
* gst_base_rtp_depayload_push_list()
* gst_rtsp_url_decode_path_components()
* gst_sdp_address_is_multicast()
* gst_video_parse_caps_palette()
Changes since 0.10.30:

407
RELEASE
View file

@ -1,5 +1,5 @@
Release notes for GStreamer Base Plug-ins 0.10.31 "Dance Like It's 1982"
Release notes for GStreamer Base Plug-ins 0.10.32 "Your Life You Like It Well"
@ -9,8 +9,6 @@ GStreamer Base Plug-ins.
The 0.10.x series is a stable series targeted at end users.
It is not API or ABI compatible with the stable 0.8.x series.
It is, however, parallel installable with the 0.8.x series.
@ -27,13 +25,14 @@ This module contains elements for, among others:
containers: ogg
codecs: vorbis, theora
text: textoverlay, subparse
sources: audiotestsrc, videotestsrc, gnomevfssrc, giosrc, appsrc
sources: audiotestsrc, videotestsrc, gnomevfssrc, giosrc
network: tcp
typefind functions
audio processing: audioconvert, adder, audiorate, audioresample, volume
visualisation: libvisual
video processing: ffmpegcolorspace
aggregate elements: uridecodebin, playbin2, decodebin2, decodebin, playbin
aggregate elements: uridecodebin, playbin2, decodebin2, decodebin, playbin, encodebin
libraries: app, audio, cdda, fft, interfaces, netbuffer, pbutils, riff, rtp, rtsp, sdp, tag, video
Other modules containing plug-ins are:
@ -54,263 +53,130 @@ contains a set of less supported plug-ins that haven't passed the
Features of this release
* adder: Make sure FLUSH_STOP is always sent after a flushing seek
* alsasrc, alsasink: add "card-name" property to get the card name in addition to the device name
* appsrc: don't override buffer caps if appsrc caps are NULL; fix element classification
* audioclock: add a function to invalidate the clock
* audioconvert: optimise remaining conversion code paths with Orc as well
* baseaudiosink,baseaudiosrc: post clock-provide and clock-lost messages when going from/to READY to/from PAUSED
* baseaudiosink: subtract the render_delay from our latency
* decodebin2: don't add non prerolled stream to topology
* ffmpegcolorspace: add support for A420 and fix support for 8 bit paletted RGB and IYU1
* gnomevfsrc: set GST_PARAM_MUTABLE_READY flag on the "handle" property
* libvisual: add latency query; only drop frames that are really too old
* multifdsink: gdp protocol is deprecated. People should use gdppay instead
* oggdemux: fix seeking with negative rate with skeleton; fix wrong flowreturn handling
* pbutils: AAC profile and level detection utility functions
* pbutils: H.264 and MPEG-4 profile and level extraction utility functions
* pbutils: new GstDiscoverer utility API for extracting metadata and tags
* playbin2, decodebin2: declare stable, deprecate the old playbin/decodebin
* playbin2, uridecodebin: add property to configure ring buffer size
* rtcpbuffer: add function to manipulation the data in RTCP feedback packets
* rtpbuffer: add functions to add RFC 5285 header extensions to GstBufferLists
* rtpbuffer: add function to add RTP header extensions with a two bytes header
* rtpbuffer: add function to append RFC 5285 one byte header extensions
* rtpbuffer: add function to parse RFC 5285 header extensions
* rtpbuffer: add function to read RFC 5285 header extensions from GstBufferLists
* rtpbuffer: add function to transform a GstBuffer into a GstBufferList
* rtsp: improve rtsp timeout calculation and handling
* sdp: add methods to convert between uri and message
* tags: try ISO-8859-1 as second fallback in case WINDOWS-1252 is not supported
* tags: add many more photography/capture tags
* tags: EXIF and XMP tag handling improvements
* textoverlay: add support for NV12, NV21 and AYUV; configurable text color and position
* theoradec: expose telemetry properties only if libtheora was compiled with --enable-telemetry
* theoraenc: add support for two-pass encoding; allow change of bitrate and quality on-the-fly
* tools: standalone gst-discoverer-0.10 tool for discovering media file properties
* typefinding: detect avc1 ftyp as video/quicktime
* typefinding: export 3gp profile in caps
* typefinding: detect enhanced AC-3
* typefinding: extend AAC typefinder to detect LOAS streams
* typefinding: fix ADTS caps stream-format detail
* typefinding: more reliable mpeg-ts typefinding
* uridecodebin: Only enable progressive downloading if the upstream duration in bytes is known
* video: add gst_video_convert_frame*() utility functions
* videorate: fixate the pixel-aspect-ratio if necessary
* videorate: mark duplicated frames with the GAP flag
* videoscale: add support for adding black borders to keep the DAR if necessary ("add-borders" property)
* videoscale: Fix caps fixating if the height is fixed but the width isn't
* videoscale: only set the PAR if the caps already had a PAR
* videoscale: refactor using more Orc code
* videotestsrc: new patterns: solid-color, ball, bar and smpte100
* videotestsrc: add "foreground-color" and "background-color" properties, deprecate "colorspec" property
* videotestsrc: add support for UYVP format, fix NV21 rendering
* volume: use Orc to optimise many code paths
* vorbisdec: decode pending buffers upon EOS when doing reverse playback
* xoverlay: add set_window_handle() with guintptr argument, deprecate set_xwindow_id() which doesn't work on some platforms
* xoverlay: allow render rectangle coordinates to be negative
* GLib requirement is now >= 2.22, gobject-introspection >= 0.9.12
* New encodebin element
* New encoding profile and encoding targets API in pbutils
* audioresample: corrected buffer duration calculation to account for nonzero initial timestamp
* audioresample: provide as much valid output ts and offset as valid input
* audioresample: push half a history length, instead of a full history length, at end-of-stream so that output segment and input segment have same duration
* decodebin2: deprecate new-decoded-pad and removed-decoded-pad signals (use "pad-added" and "pad-removed" instead)
* multifdsink: add first and last buffer's timestamp to the stats; only keep last valid timestamp
* oggdemux: extract more tags (vorbis comment headers, Kate)
* oggdemux: ignore header pages when looking for keyframe; set headers on caps
* oggdemux: fix interpretation of Theora granule position and parsing of Theora size
* oggparse: Set DELTA_UNIT on buffers
* playbin2: delay stream-changed messages, fixing KATE subtitle recognition
* textoverlay: make text, xpos, ypos, color, and silent properties controllable
* typefinding: (E)AC-3 and ISO typefinder improvements; add yuv4mpeg typefinder
* typefinding: add "stream-format" to h264 caps, and framed=false to DTS caps
* typefinding: assume EBML files without doctype are matroska
* videorate: fix behaviour for frame rate cap changes
* vorbisdec: avoid using invalid timestamps; keep timestamps when no decoded output
* ximagesink, xvimagesink: add read-only window-width and window-height properties
* baseaudiopay: fix timestamps on buffer lists
* baseaudiosink: protect against ringbuffer disappearing while in a query
* basedepay: add support for buffer lists in the depayloader
* basertppay: use RTP base time when invalid timestamps
* rtpbuffer: relax arrangement for RTP bufferlists
* rtpdepayloader: add support for getting events
* rtppayload: copy applied rate to segment
* sdp: add method to check for multicast addresses
* sdp: only parse TTL for IP4 addresses
* video: add 8-bit paletted RGB, YUV9, YVU9 and IYU1 video formats
* video: return correct component width/height for A420
Bugs fixed in this release
* 628028 : [uridecodebin] Don't enable progressive downloading for live streams
* 623846 : typefinding: add support for " enhanced ac3 " (eac3)
* 602437 : [playbin2] [gapless] Completely broken when switching between files with audio/video only
* 612264 : Notification needed when the first buffer is pushed by the basertppayloader
* 615471 : [videoscale] Interlaced handling makes output worse than no interlaced handling at all
* 616392 : videotestsrc colorspec=0/1 does not affect color-matrix in caps
* 617314 : pbutils: Add codec-specific utility functions for AAC, H.264, MPEG-4 video
* 617506 : [videoscale] Add support for adding black borders if necessary to keep the DAR
* 620291 : typefindfunctions: Export 3gp profile in caps
* 623663 : [typefinding] mpeg-ts file detected as audio/mpeg
* 623807 : [audioclock] Add gst_audio_clock_new_full() with GDestroyNotify for the user_data
* 623837 : typefind: only associate .webm with WebM
* 623918 : [typefind] Extend AAC typefinder to detect LOAS stream
* 624598 : [adder] crash in orc_sse_set_mxcsr()
* 624656 : [videoscale] UYVY scaling broken, introduces green lines
* 624919 : [videotestsrc] add solid color pattern
* 624920 : [textoverlay] configurable text color and position
* 624949 : [playbin2] declare playbin2 stable
* 625001 : [examples] Don't use GdkDraw/GdkGC
* 625118 : [playbin2] Race condition with EOS events in gapless mode
* 625944 : [pbutils] GstDiscoverer - API to discover metadata and stream information
* 626125 : [alsa] Conditional jump or move depends on uninitialised value(s)
* 626570 : [tag] Add resolution tags
* 626581 : [playbin2] regression: occasional deadlocks in streamsynchronizer
* 626621 : [playbin2] streamsynchronizer regressions
* 626629 : [ffmpegcolorspace] doesn't handle palettes any longer
* 626718 : playback: Delay usage of GstFactoryList
* 627203 : [alsa] alsasrc and alsasink should expose card name via property
* 627297 : [regression] build-failure
* 627565 : [xoverlay][win64] gulong can't hold a HANDLE
* 627768 : add NV12 support to textoverlay
* 627780 : GstClockOverlay re-renders string even if it hasn't changed, resulting in very high CPU usage.
* 627924 : riff: add support for 2vuy
* 628009 : [volume] Float processing with orc broken
* 628400 : [videorate] does not generate buffers to fill the duration of the last frame
* 628500 : videotestsrc: add moving color bars pattern
* 628747 : gst-plugins-base: unable to build because of compiler warning in libggsttag
* 629157 : Move video frame conversion from playback plugin to libgstvideo
* 629672 : gnomevfsrsrc: " handle " property should also have the GST_PARAM_MUTABLE_READY flag
* 629848 : build problem with current gtk+: implicit declaration of function 'gdk_draw_rectangle', GtkStyle' has no member named 'black_gc'
* 630303 : theoraenc: Make the bitrate/quality dynamically modifiable
* 630353 : [appsrc] Avoid losing buffers' caps
* 630440 : ringbuffer: use g_once for type-init
* 630443 : baseaudiosink: Add getter and setter for drift tolerance
* 630471 : [tag] ligatures " Œ " and " œ " are not supported in freeform strings
* 630496 : seek example: add new #define to set seek bar graininess
* 630802 : videotestsrc.c doesn't compile in Visual Studio 2008
* 631128 : Add methods to manipulate RFC 5285 header extensions
* 631312 : [streamsynchronizer] Advancing segments too much
* 631633 : [oggdemux] fix seeking with negative rate with skeleton
* 631703 : [oggdemux] sintel ogv delay when playing
* 631756 : Fix build with glib 2.21.3
* 631773 : [tags] Add new exif tags: sharpness, metering mode, file/capturing source
* 631774 : [xvimagesink] sets non-simple caps on pad_alloced buffer
* 632167 : [oggdemux] doesn't parse/push all headers in pull mode
* 632653 : [seek] Don't use deprecated combo box API
* 632656 : [uridecodebin] internal decodebin2 might fail to reach PLAYING in streaming case
* 632789 : [PATCH] tests/icles/: adapted test-colorkey.c and test-xoverlay.c to deprecation of gtk_widget_hide_all
* 632809 : [regression] build failure in 0.10.30.2 in tools/
* 632988 : [discoverer] gst_caps_ref() critical for substreams of unknown streams
* 633023 : [discoverer] Add versionized gst-discoverer tool
* 633203 : Regression: streamsynchroniser + disabled deinterlacing = no DVD menu highlights/subtitles
* 633311 : discoverer: use specific types in getters, rename some boolean getters
* 633336 : [discoverer] Move documentation into the correct section
* 633455 : [rtsp] don't let the rtsp connection timeout
* 634014 : GTK+3 is a moving target, lets not compile against it by default.
* 634584 : decodebin2 docs should mention that " new-decoded-pad " signal may be emitted after " no-more-pads "
* 635067 : [*decodebin*] pad template leaked
* 635392 : Missing information on exported packages from GIRs
* 621349 : [theoraenc] Implement two-pass encoding
* 628488 : [theoradec] add properties to enable telemetry overlay
* 629746 : Enumerations have incorrect names of enum values (GEnumValue.value_name)
* 626869 : The RTP depayloader is sometimes sending partial frames down the pipeline without the DISCONT bit set
* 619778 : oggdemux: fails on zero-length pages with Patent_Absurdity_HD_3540kbit.ogv
* 586570 : Add GAP Flag support to audioresample
* 623413 : pbutils: Add/Fix some media descriptions
* 627476 : New profile library and encoding plugin
* 629349 : [oggdemux] extract stream tags for tagreadbin and transcoding
* 632667 : [ximagesink] added read-only properties window-width and window-height
* 634397 : [multifdsink] [PATCH] Add the timestamp of the first and last buffer to the stats
* 634522 : gst-visualize-m.m imports but doesn't use File::Basename
* 635231 : baseaudiosink: protect against ringbuffer disappearing while in a query
* 636198 : decodebin2: " removed-decoded-pad " signal never fired
* 636769 : [appsink] Flushing property is never reset
* 636827 : Usage of gst_caps_interset where gst_caps_can_intersect was intended?
* 637324 : oggdemux: unable to demux Ogg files with Skeleton in push mode
* 637377 : timeoverlay: add missing break
* 637519 : ogg: implement packet duration query for kate streams
* 637586 : playbin2 fails to recognize subtitle caps from katedec
* 637735 : [encoding-profile] automatic load/save support and registry
* 637758 : [exiftag] Generates buffers with uninitialized data during taglist- > exif buffer serialization
* 637822 : oggdemux: allocate buffers using gst_buffer_new_and_alloc
* 637927 : oggdemux: set headers on caps
* 638200 : [oggdemux] fails to playback video file
* 638276 : oggstream: when the last keyframe position is not known, do not use -1
* 638859 : textoverlay: make misc. properties controllable
* 638901 : [encodebin] proper element documentation
* 638903 : [encodebin] missing-plugin support
* 638961 : Small configure bashism 0.10.31.2
* 639039 : gobject-introspection: GstPbutils gir scanner fails to link with gold linker
* 639121 : oggdemux: outdated comment for gst_ogg_demux_submit_buffer()
* 639215 : examples: Allow building with newer GTK+
* 639730 : discoverer: Validate timeouts before processing them
* 639755 : discoverer: Clean up callbacks in dispose()
* 639778 : discoverer: Drop new stream tags once preroll is done
* 639790 : [gdp] Fix metadata g_warning
* 639747 : Please export GST_TYPE_APP_STREAM_TYPE
* 553244 : theoraparse doesn't work at all (throws criticals and asserts)
API changed in this release
- API additions:
* gst_audio_clock_invalidate()
* gst_audio_clock_new_full()
* gst_base_audio_sink_get_drift_tolerance()
* gst_base_audio_sink_set_drift_tolerance()
* gst_x_overlay_got_window_handle()
* gst_x_overlay_set_window_handle()
* GstXOverlay::set_window_handle()
* gst_codec_utils_aac_caps_set_level_and_profile()
* gst_codec_utils_aac_get_level()
* gst_codec_utils_aac_get_profile()
* gst_codec_utils_aac_get_sample_rate_from_index()
* gst_codec_utils_h264_caps_set_level_and_profile()
* gst_codec_utils_h264_get_level()
* gst_codec_utils_h264_get_profile()
* gst_codec_utils_mpeg4video_caps_set_level_and_profile()
* gst_codec_utils_mpeg4video_get_level()
* gst_codec_utils_mpeg4video_get_profile()
* gst_discoverer_audio_info_get_bitrate()
* gst_discoverer_audio_info_get_channels()
* gst_discoverer_audio_info_get_depth()
* gst_discoverer_audio_info_get_max_bitrate()
* gst_discoverer_audio_info_get_sample_rate()
* gst_discoverer_audio_info_get_type()
* gst_discoverer_container_info_get_streams()
* gst_discoverer_container_info_get_type()
* gst_discoverer_discover_uri()
* gst_discoverer_discover_uri_async()
* gst_discoverer_get_type()
* gst_discoverer_info_copy()
* gst_discoverer_info_get_audio_streams()
* gst_discoverer_info_get_container_streams()
* gst_discoverer_info_get_duration()
* gst_discoverer_info_get_misc()
* gst_discoverer_info_get_result()
* gst_discoverer_info_get_stream_info()
* gst_discoverer_info_get_stream_list()
* gst_discoverer_info_get_streams()
* gst_discoverer_info_get_tags()
* gst_discoverer_info_get_type()
* gst_discoverer_info_get_uri()
* gst_discoverer_info_get_video_streams()
* gst_discoverer_new()
* gst_discoverer_result_get_type()
* gst_discoverer_start()
* gst_discoverer_stop()
* gst_discoverer_stream_info_get_caps()
* gst_discoverer_stream_info_get_misc()
* gst_discoverer_stream_info_get_next()
* gst_discoverer_stream_info_get_previous()
* gst_discoverer_stream_info_get_stream_type_nick()
* gst_discoverer_stream_info_get_tags()
* gst_discoverer_stream_info_get_type()
* gst_discoverer_stream_info_list_free()
* gst_discoverer_video_info_get_bitrate()
* gst_discoverer_video_info_get_depth()
* gst_discoverer_video_info_get_framerate_denom()
* gst_discoverer_video_info_get_framerate_num()
* gst_discoverer_video_info_get_height()
* gst_discoverer_video_info_get_max_bitrate()
* gst_discoverer_video_info_get_par_denom()
* gst_discoverer_video_info_get_par_num()
* gst_discoverer_video_info_get_type()
* gst_discoverer_video_info_get_width()
* gst_discoverer_video_info_is_image()
* gst_discoverer_video_info_is_interlaced()
* GST_PLUGINS_BASE_VERSION_MAJOR
* GST_PLUGINS_BASE_VERSION_MINOR
* GST_PLUGINS_BASE_VERSION_MICRO
* GST_PLUGINS_BASE_VERSION_NANO
* GST_CHECK_PLUGINS_BASE_VERSION
* gst_plugins_base_version()
* gst_plugins_base_version_string()
* gst_rtcp_packet_fb_get_fci()
* gst_rtcp_packet_fb_get_fci_length()
* gst_rtcp_packet_fb_set_fci_length()
* gst_rtp_buffer_add_extension_onebyte_header()
* gst_rtp_buffer_add_extension_twobytes_header()
* gst_rtp_buffer_get_extension_onebyte_header()
* gst_rtp_buffer_get_extension_twobytes_header()
* gst_rtp_buffer_list_add_extension_onebyte_header()
* gst_rtp_buffer_list_add_extension_twobytes_header()
* gst_rtp_buffer_list_from_buffer()
* gst_rtp_buffer_list_get_extension_onebyte_header()
* gst_rtp_buffer_list_get_extension_twobytes_header()
* gst_sdp_message_as_uri()
* gst_sdp_message_parse_uri()
* GST_TAG_CAPTURING_SOURCE
* GST_TAG_CAPTURING_METERING_MODE
* GST_TAG_CAPTURING_SHARPNESS
* GST_TAG_IMAGE_HORIZONTAL_PPI
* GST_TAG_IMAGE_VERTICAL_PPI
* GST_TAG_CAPTURING_FLASH_FIRED
* GST_TAG_CAPTURING_FLASH_MODE
* GST_TAG_CAPTURING_EXPOSURE_PROGRAM
* GST_TAG_CAPTURING_EXPOSURE_MODE
* GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE
* GST_TAG_CAPTURING_GAIN_ADJUSTMENT
* GST_TAG_CAPTURING_WHITE_BALANCE
* GST_TAG_CAPTURING_CONTRAST
* GST_TAG_CAPTURING_SATURATION
* GST_TAG_CAPTURING_SHUTTER_SPEED
* GST_TAG_CAPTURING_FOCAL_RATIO
* GST_TAG_CAPTURING_FOCAL_LENGTH
* GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO
* GST_TAG_CAPTURING_ISO_SPEED
* GST_VIDEO_FORMAT_UYVP
* GST_VIDEO_FORMAT_A420
* gst_video_convert_frame()
* gst_video_convert_frame_async()
* GstTextOverlay:xpos
* GstTextOverlay:ypos
* GstTextOverlay:color
* GstVideoTestSrc:solid-color
* GstVideoTestSrc::foreground-color
* GstVideoTestSrc::background-color
- API deprecations:
* gst_x_overlay_set_xwindow_id()
* gst_x_overlay_got_xwindow_id()
* GstXOverlay::set_xwindow_id()
* gst_app_stream_type_get_type()
* gst_discoverer_info_get_seekable()
* gst_encoding_audio_profile_get_type()
* gst_encoding_audio_profile_new()
* gst_encoding_container_profile_add_profile()
* gst_encoding_container_profile_contains_profile()
* gst_encoding_container_profile_get_profiles()
* gst_encoding_container_profile_get_type()
* gst_encoding_container_profile_new()
* gst_encoding_list_all_targets()
* gst_encoding_list_available_categories()
* gst_encoding_profile_find()
* gst_encoding_profile_get_description()
* gst_encoding_profile_get_format()
* gst_encoding_profile_get_input_caps()
* gst_encoding_profile_get_name()
* gst_encoding_profile_get_presence()
* gst_encoding_profile_get_preset()
* gst_encoding_profile_get_restriction()
* gst_encoding_profile_get_type()
* gst_encoding_profile_get_type_nick()
* gst_encoding_profile_is_equal()
* gst_encoding_profile_set_description()
* gst_encoding_profile_set_format()
* gst_encoding_profile_set_name()
* gst_encoding_profile_set_presence()
* gst_encoding_profile_set_preset()
* gst_encoding_profile_set_restriction()
* gst_encoding_target_add_profile()
* gst_encoding_target_get_category()
* gst_encoding_target_get_description()
* gst_encoding_target_get_name()
* gst_encoding_target_get_profile()
* gst_encoding_target_get_profiles()
* gst_encoding_target_get_type()
* gst_encoding_target_load()
* gst_encoding_target_load_from_file()
* gst_encoding_target_new()
* gst_encoding_target_save()
* gst_encoding_target_save_to_file()
* gst_encoding_video_profile_get_pass()
* gst_encoding_video_profile_get_type()
* gst_encoding_video_profile_get_variableframerate()
* gst_encoding_video_profile_new()
* gst_encoding_video_profile_set_pass()
* gst_encoding_video_profile_set_variableframerate()
* gst_base_rtp_depayload_push_list()
* gst_rtsp_url_decode_path_components()
* gst_sdp_address_is_multicast()
* gst_video_parse_caps_palette()
Download
@ -340,25 +206,23 @@ Applications
Contributors to this release
* Alessandro Decina
* Alexey Fisher
* American Dynamics
* Andrzej K. Haczewski
* Andoni Morales Alastruey
* Andrea Sebastianutti
* Andy Wingo
* Arun Raghavan
* Chris Shoemaker
* Bastien Nocera
* Benjamin Gaignard
* Byeong-ryeol Kim
* David Schleef
* Edward Hervey
* Evan Nemerson
* Guillaume Emont
* Harri Mähönen
* Evan Broder
* Gavin Stark
* Havard Graff
* Jan Schmidt
* Koop Mast
* Lane Brooks
* Leo Singer
* Mark Nauwelaerts
* Matthias Clasen
* Olivier Crête
* Parthasarathi Susarla
* Philip Jägenstedt
* Philippe Normand
* Michael Smith
* René Stadler
* Rob Clark
* Robert Swain
@ -366,11 +230,10 @@ Contributors to this release
* Sreerenj Balachandran
* Stefan Kost
* Thiago Santos
* Thijs Vermeir
* Tim-Philipp Müller
* Tristan Matthews
* Vincent Penquerc'h
* Vladimir
* Wim Taymans
* Zaheer Abbas Merali
 
* Yang Xichuan
* Zeeshan Ali (Khattak)
* christian schaller
 

2
common

@ -1 +1 @@
Subproject commit 011bcc8a0fc7f798ee874a7ba899123fb2470e22
Subproject commit 1de7f6ab2d4bc1af69f06079cf0f4e2cbbfdc178

View file

@ -49,7 +49,7 @@ dnl - interfaces added/removed/changed -> increment CURRENT, REVISION = 0
dnl - interfaces added -> increment AGE
dnl - interfaces removed -> AGE = 0
dnl sets GST_LT_LDFLAGS
AS_LIBTOOL(GST, 22, 0, 22)
AS_LIBTOOL(GST, 23, 0, 23)
dnl FIXME: this macro doesn't actually work;
dnl the generated libtool script has no support for the listed tags.
@ -151,7 +151,7 @@ AC_PATH_PROG(VALGRIND_PATH, valgrind, no)
AM_CONDITIONAL(HAVE_VALGRIND, test ! "x$VALGRIND_PATH" = "xno")
dnl check for gobject-introspection
GOBJECT_INTROSPECTION_CHECK([0.6.3])
GOBJECT_INTROSPECTION_CHECK([0.9.12])
dnl check for documentation tools
GTK_DOC_CHECK([1.3])
@ -337,6 +337,22 @@ AC_COMPILE_IFELSE(
])
AM_CONDITIONAL(HAVE_LINUX_JOYSTICK_HEADERS, test "x$HAVE_LINUX_JOYSTICK_HEADERS" = "xyes")
dnl Check for -Bsymbolic-functions linker flag used to avoid
dnl intra-library PLT jumps, if available.
AC_ARG_ENABLE(Bsymbolic,
[AC_HELP_STRING([--disable-Bsymbolic],
[avoid linking with -Bsymbolic])],,
[SAVED_LDFLAGS="${LDFLAGS}"
AC_MSG_CHECKING([for -Bsymbolic-functions linker flag])
LDFLAGS=-Wl,-Bsymbolic-functions
AC_TRY_LINK([], [int main (void) { return 0; }],
AC_MSG_RESULT(yes)
enable_Bsymbolic=yes,
AC_MSG_RESULT(no)
enable_Bsymbolic=no)
LDFLAGS="${SAVED_LDFLAGS}"])
dnl *** set variables based on configure arguments ***
dnl set license and copyright notice
@ -373,6 +389,11 @@ AG_GST_SET_LEVEL_DEFAULT($GST_GIT)
dnl used in examples
AG_GST_DEFAULT_ELEMENTS
dnl needed for encoding-target
GST_DATADIR="$GST_PREFIX/share"
AC_DEFINE_UNQUOTED(GST_DATADIR, "$GST_DATADIR", [system wide data directory])
AC_DEFINE_UNQUOTED(GST_MAJORMINOR, "$GST_MAJORMINOR", [major/minor version])
dnl behaviour of speex based audio resampler
AC_MSG_CHECKING(which audio resample format to use for integer)
AC_ARG_WITH([audioresample_format],
@ -401,6 +422,7 @@ AG_GST_CHECK_PLUGIN(app)
AG_GST_CHECK_PLUGIN(audioconvert)
AG_GST_CHECK_PLUGIN(audiorate)
AG_GST_CHECK_PLUGIN(audiotestsrc)
AG_GST_CHECK_PLUGIN(encoding)
AG_GST_CHECK_PLUGIN(ffmpegcolorspace)
AG_GST_CHECK_PLUGIN(gdp)
AG_GST_CHECK_PLUGIN(playback)
@ -870,6 +892,9 @@ AC_SUBST(GST_LIBS)
dnl LDFLAGS really should only contain flags, not libs - they get added before
dnl whatevertarget_LIBS and -L flags here affect the rest of the linking
GST_ALL_LDFLAGS="-no-undefined"
if test "x${enable_Bsymbolic}" = "xyes"; then
GST_ALL_LDFLAGS="$GST_ALL_LDFLAGS -Wl,-Bsymbolic-functions"
fi
AC_SUBST(GST_ALL_LDFLAGS)
dnl GST_LIB_LDFLAGS
@ -895,6 +920,7 @@ gst/app/Makefile
gst/audioconvert/Makefile
gst/audiorate/Makefile
gst/audiotestsrc/Makefile
gst/encoding/Makefile
gst/ffmpegcolorspace/Makefile
gst/gdp/Makefile
gst/playback/Makefile
@ -974,6 +1000,7 @@ tests/check/Makefile
tests/examples/Makefile
tests/examples/app/Makefile
tests/examples/dynamic/Makefile
tests/examples/encoding/Makefile
tests/examples/gio/Makefile
tests/examples/overlay/Makefile
tests/examples/seek/Makefile
@ -1034,7 +1061,7 @@ sed \
-e 's/.* PLUGINDIR$/#ifdef _DEBUG\n# define PLUGINDIR PREFIX "\\\\debug\\\\lib\\\\gstreamer-0.11"\n#else\n# define PLUGINDIR PREFIX "\\\\lib\\\\gstreamer-0.11"\n#endif/' \
-e 's/.* USE_BINARY_REGISTRY$/#define USE_BINARY_REGISTRY/' \
-e 's/.* VERSION$/#define VERSION "'$VERSION'"/' \
-e "s/.* DEFAULT_AUDIOSINK$/#define DEFAULT_AUDIOSINK \"directaudiosink\"/" \
-e "s/.* DEFAULT_AUDIOSINK$/#define DEFAULT_AUDIOSINK \"directsoundsink\"/" \
-e "s/.* DEFAULT_VIDEOSINK$/#define DEFAULT_VIDEOSINK \"directdrawsink\"/" \
-e "s/.* DEFAULT_VISUALIZER$/#define DEFAULT_VISUALIZER \"goom\"/" \
config.h.in >win32/common/config.h-new

View file

@ -12,7 +12,6 @@ SUBDIRS = design libs $(PLUGIN_DOCS_DIRS)
DIST_SUBDIRS = design libs plugins
EXTRA_DIST = \
design-audiosinks.txt \
version.entities.in
upload:

View file

@ -2,7 +2,9 @@ SUBDIRS =
EXTRA_DIST = \
design-audiosinks.txt \
design-decodebin.txt \
design-encoding.txt \
design-orc-integration.txt \
draft-keyframe-force.txt \
draft-va.txt \

View file

@ -0,0 +1,571 @@
Encoding and Muxing
-------------------
Summary
-------
A. Problems
B. Goals
1. EncodeBin
2. Encoding Profile System
3. Helper Library for Profiles
I. Use-cases researched
A. Problems this proposal attempts to solve
-------------------------------------------
* Duplication of pipeline code for gstreamer-based applications
wishing to encode and or mux streams, leading to subtle differences
and inconsistencies accross those applications.
* No unified system for describing encoding targets for applications
in a user-friendly way.
* No unified system for creating encoding targets for applications,
resulting in duplication of code accross all applications,
differences and inconsistencies that come with that duplication,
and applications hardcoding element names and settings resulting in
poor portability.
B. Goals
--------
1. Convenience encoding element
Create a convenience GstBin for encoding and muxing several streams,
hereafter called 'EncodeBin'.
This element will only contain one single property, which is a
profile.
2. Define a encoding profile system
2. Encoding profile helper library
Create a helper library to:
* create EncodeBin instances based on profiles, and
* help applications to create/load/save/browse those profiles.
1. EncodeBin
------------
1.1 Proposed API
----------------
EncodeBin is a GstBin subclass.
It implements the GstTagSetter interface, by which it will proxy the
calls to the muxer.
Only two introspectable property (i.e. usable without extra API):
* A GstEncodingProfile*
* The name of the profile to use
When a profile is selected, encodebin will:
* Add REQUEST sinkpads for all the GstStreamProfile
* Create the muxer and expose the source pad
Whenever a request pad is created, encodebin will:
* Create the chain of elements for that pad
* Ghost the sink pad
* Return that ghost pad
This allows reducing the code to the minimum for applications
wishing to encode a source for a given profile:
...
encbin = gst_element_factory_make("encodebin, NULL);
g_object_set (encbin, "profile", "N900/H264 HQ", NULL);
gst_element_link (encbin, filesink);
...
vsrcpad = gst_element_get_src_pad(source, "src1");
vsinkpad = gst_element_get_request_pad (encbin, "video_%d");
gst_pad_link(vsrcpad, vsinkpad);
...
1.2 Explanation of the Various stages in EncodeBin
--------------------------------------------------
This describes the various stages which can happen in order to end
up with a multiplexed stream that can then be stored or streamed.
1.2.1 Incoming streams
The streams fed to EncodeBin can be of various types:
* Video
* Uncompressed (but maybe subsampled)
* Compressed
* Audio
* Uncompressed (audio/x-raw-{int|float})
* Compressed
* Timed text
* Private streams
1.2.2 Steps involved for raw video encoding
(0) Incoming Stream
(1) Transform raw video feed (optional)
Here we modify the various fundamental properties of a raw video
stream to be compatible with the intersection of:
* The encoder GstCaps and
* The specified "Stream Restriction" of the profile/target
The fundamental properties that can be modified are:
* width/height
This is done with a video scaler.
The DAR (Display Aspect Ratio) MUST be respected.
If needed, black borders can be added to comply with the target DAR.
* framerate
* format/colorspace/depth
All of this is done with a colorspace converter
(2) Actual encoding (optional for raw streams)
An encoder (with some optional settings) is used.
(3) Muxing
A muxer (with some optional settings) is used.
(4) Outgoing encoded and muxed stream
1.2.3 Steps involved for raw audio encoding
This is roughly the same as for raw video, expect for (1)
(1) Transform raw audo feed (optional)
We modify the various fundamental properties of a raw audio stream to
be compatible with the intersection of:
* The encoder GstCaps and
* The specified "Stream Restriction" of the profile/target
The fundamental properties that can be modifier are:
* Number of channels
* Type of raw audio (integer or floating point)
* Depth (number of bits required to encode one sample)
1.2.4 Steps involved for encoded audio/video streams
Steps (1) and (2) are replaced by a parser if a parser is available
for the given format.
1.2.5 Steps involved for other streams
Other streams will just be forwarded as-is to the muxer, provided the
muxer accepts the stream type.
2. Encoding Profile System
--------------------------
This work is based on:
* The existing GstPreset system for elements [0]
* The gnome-media GConf audio profile system [1]
* The investigation done into device profiles by Arista and
Transmageddon [2 and 3]
2.2 Terminology
---------------
* Encoding Target Category
A Target Category is a classification of devices/systems/use-cases
for encoding.
Such a classification is required in order for:
* Applications with a very-specific use-case to limit the number of
profiles they can offer the user. A screencasting application has
no use with the online services targets for example.
* Offering the user some initial classification in the case of a
more generic encoding application (like a video editor or a
transcoder).
Ex:
Consumer devices
Online service
Intermediate Editing Format
Screencast
Capture
Computer
* Encoding Profile Target
A Profile Target describes a specific entity for which we wish to
encode.
A Profile Target must belong to at least one Target Category.
It will define at least one Encoding Profile.
Ex (with category):
Nokia N900 (Consumer device)
Sony PlayStation 3 (Consumer device)
Youtube (Online service)
DNxHD (Intermediate editing format)
HuffYUV (Screencast)
Theora (Computer)
* Encoding Profile
A specific combination of muxer, encoders, presets and limitations.
Ex:
Nokia N900/H264 HQ
Ipod/High Quality
DVD/Pal
Youtube/High Quality
HTML5/Low Bandwith
DNxHD
2.3 Encoding Profile
--------------------
An encoding profile requires the following information:
* Name
This string is not translatable and must be unique.
A recommendation to guarantee uniqueness of the naming could be:
<target>/<name>
* Description
This is a translatable string describing the profile
* Muxing format
This is a string containing the GStreamer media-type of the
container format.
* Muxing preset
This is an optional string describing the preset(s) to use on the
muxer.
* Multipass setting
This is a boolean describing whether the profile requires several
passes.
* List of Stream Profile
2.3.1 Stream Profiles
A Stream Profile consists of:
* Type
The type of stream profile (audio, video, text, private-data)
* Encoding Format
This is a string containing the GStreamer media-type of the encoding
format to be used. If encoding is not to be applied, the raw audio
media type will be used.
* Encoding preset
This is an optional string describing the preset(s) to use on the
encoder.
* Restriction
This is an optional GstCaps containing the restriction of the
stream that can be fed to the encoder.
This will generally containing restrictions in video
width/heigh/framerate or audio depth.
* presence
This is an integer specifying how many streams can be used in the
containing profile. 0 means that any number of streams can be
used.
* pass
This is an integer which is only meaningful if the multipass flag
has been set in the profile. If it has been set it indicates which
pass this Stream Profile corresponds to.
2.4 Example profile
-------------------
The representation used here is XML only as an example. No decision is
made as to which formatting to use for storing targets and profiles.
<gst-encoding-target>
<name>Nokia N900</name>
<category>Consumer Device</category>
<profiles>
<profile>Nokia N900/H264 HQ</profile>
<profile>Nokia N900/MP3</profile>
<profile>Nokia N900/AAC</profile>
</profiles>
</gst-encoding-target>
<gst-encoding-profile>
<name>Nokia N900/H264 HQ</name>
<description>
High Quality H264/AAC for the Nokia N900
</description>
<format>video/quicktime,variant=iso</format>
<streams>
<stream-profile>
<type>audio</type>
<format>audio/mpeg,mpegversion=4</format>
<preset>Quality High/Main</preset>
<restriction>audio/x-raw-int,channels=[1,2]</restriction>
<presence>1</presence>
</stream-profile>
<stream-profile>
<type>video</type>
<format>video/x-h264</format>
<preset>Profile Baseline/Quality High</preset>
<restriction>
video/x-raw-yuv,width=[16, 800],\
height=[16, 480],framerate=[1/1, 30000/1001]
</restriction>
<presence>1</presence>
</stream-profile>
</streams>
</gst-encoding-profile>
2.5 API
-------
A proposed C API is contained in the gstprofile.h file in this directory.
2.6 Modifications required in the existing GstPreset system
-----------------------------------------------------------
2.6.1. Temporary preset.
Currently a preset needs to be saved on disk in order to be
used.
This makes it impossible to have temporary presets (that exist only
during the lifetime of a process), which might be required in the
new proposed profile system
2.6.2 Categorisation of presets.
Currently presets are just aliases of a group of property/value
without any meanings or explanation as to how they exclude each
other.
Take for example the H264 encoder. It can have presets for:
* passes (1,2 or 3 passes)
* profiles (Baseline, Main, ...)
* quality (Low, medium, High)
In order to programmatically know which presets exclude each other,
we here propose the categorisation of these presets.
This can be done in one of two ways
1. in the name (by making the name be [<category>:]<name>)
This would give for example: "Quality:High", "Profile:Baseline"
2. by adding a new _meta key
This would give for example: _meta/category:quality
2.6.3 Aggregation of presets.
There can be more than one choice of presets to be done for an
element (quality, profile, pass).
This means that one can not currently describe the full
configuration of an element with a single string but with many.
The proposal here is to extend the GstPreset API to be able to set
all presets using one string and a well-known separator ('/').
This change only requires changes in the core preset handling code.
This would allow doing the following:
gst_preset_load_preset (h264enc,
"pass:1/profile:baseline/quality:high");
2.7 Points to be determined
---------------------------
This document hasn't determined yet how to solve the following
problems:
2.7.1 Storage of profiles
One proposal for storage would be to use a system wide directory
(like $prefix/share/gstreamer-0.10/profiles) and store XML files for
every individual profiles.
Users could then add their own profiles in ~/.gstreamer-0.10/profiles
This poses some limitations as to what to do if some applications
want to have some profiles limited to their own usage.
3. Helper library for profiles
------------------------------
These helper methods could also be added to existing libraries (like
GstPreset, GstPbUtils, ..).
The various API proposed are in the accompanying gstprofile.h file.
3.1 Getting user-readable names for formats
This is already provided by GstPbUtils.
3.2 Hierarchy of profiles
The goal is for applications to be able to present to the user a list
of combo-boxes for choosing their output profile:
[ Category ] # optional, depends on the application
[ Device/Site/.. ] # optional, depends on the application
[ Profile ]
Convenience methods are offered to easily get lists of categories,
devices, and profiles.
3.3 Creating Profiles
The goal is for applications to be able to easily create profiles.
The applications needs to be able to have a fast/efficient way to:
* select a container format and see all compatible streams he can use
with it.
* select a codec format and see which container formats he can use
with it.
The remaining parts concern the restrictions to encoder
input.
3.4 Ensuring availability of plugins for Profiles
When an application wishes to use a Profile, it should be able to
query whether it has all the needed plugins to use it.
This part will use GstPbUtils to query, and if needed install the
missing plugins through the installed distribution plugin installer.
I. Use-cases researched
-----------------------
This is a list of various use-cases where encoding/muxing is being
used.
* Transcoding
The goal is to convert with as minimal loss of quality any input
file for a target use.
A specific variant of this is transmuxing (see below).
Example applications: Arista, Transmageddon
* Rendering timelines
The incoming streams are a collection of various segments that need
to be rendered.
Those segments can vary in nature (i.e. the video width/height can
change).
This requires the use of identiy with the single-segment property
activated to transform the incoming collection of segments to a
single continuous segment.
Example applications: PiTiVi, Jokosher
* Encoding of live sources
The major risk to take into account is the encoder not encoding the
incoming stream fast enough. This is outside of the scope of
encodebin, and should be solved by using queues between the sources
and encodebin, as well as implementing QoS in encoders and sources
(the encoders emitting QoS events, and the upstream elements
adapting themselves accordingly).
Example applications: camerabin, cheese
* Screencasting applications
This is similar to encoding of live sources.
The difference being that due to the nature of the source (size and
amount/frequency of updates) one might want to do the encoding in
two parts:
* The actual live capture is encoded with a 'almost-lossless' codec
(such as huffyuv)
* Once the capture is done, the file created in the first step is
then rendered to the desired target format.
Fixing sources to only emit region-updates and having encoders
capable of encoding those streams would fix the need for the first
step but is outside of the scope of encodebin.
Example applications: Istanbul, gnome-shell, recordmydesktop
* Live transcoding
This is the case of an incoming live stream which will be
broadcasted/transmitted live.
One issue to take into account is to reduce the encoding latency to
a minimum. This should mostly be done by picking low-latency
encoders.
Example applications: Rygel, Coherence
* Transmuxing
Given a certain file, the aim is to remux the contents WITHOUT
decoding into either a different container format or the same
container format.
Remuxing into the same container format is useful when the file was
not created properly (for example, the index is missing).
Whenever available, parsers should be applied on the encoded streams
to validate and/or fix the streams before muxing them.
Metadata from the original file must be kept in the newly created
file.
Example applications: Arista, Transmaggedon
* Loss-less cutting
Given a certain file, the aim is to extract a certain part of the
file without going through the process of decoding and re-encoding
that file.
This is similar to the transmuxing use-case.
Example applications: PiTiVi, Transmageddon, Arista, ...
* Multi-pass encoding
Some encoders allow doing a multi-pass encoding.
The initial pass(es) are only used to collect encoding estimates and
are not actually muxed and outputted.
The final pass uses previously collected information, and the output
is then muxed and outputted.
* Archiving and intermediary format
The requirement is to have lossless
* CD ripping
Example applications: Sound-juicer
* DVD ripping
Example application: Thoggen
* Research links
Some of these are still active documents, some other not
[0] GstPreset API documentation
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstPreset.html
[1] gnome-media GConf profiles
http://www.gnome.org/~bmsmith/gconf-docs/C/gnome-media.html
[2] Research on a Device Profile API
http://gstreamer.freedesktop.org/wiki/DeviceProfile
[3] Research on defining presets usage
http://gstreamer.freedesktop.org/wiki/PresetDesign

View file

@ -206,6 +206,7 @@
<xi:include href="xml/gstpbutilsmissingplugins.xml" />
<xi:include href="xml/gstpbutilsinstallplugins.xml" />
<xi:include href="xml/gstdiscoverer.xml" />
<xi:include href="xml/encoding-profile.xml" />
</chapter>
<chapter id="gstreamer-video">

View file

@ -547,6 +547,7 @@ GST_MIXER_GET_CLASS
GST_MIXER_TYPE
GST_IS_MIXER
GST_IS_MIXER_CLASS
GST_TYPE_STREAM_VOLUME_FORMAT
gst_mixer_get_type
gst_mixer_type_get_type
gst_mixer_flags_get_type
@ -1098,6 +1099,7 @@ GST_BASE_RTP_DEPAYLOAD_SRCPAD
gst_base_rtp_depayload_push
gst_base_rtp_depayload_push_ts
gst_base_rtp_depayload_push_list
<SUBSECTION Standard>
GstBaseRTPDepayloadPrivate
@ -1573,6 +1575,7 @@ gst_rtsp_url_free
gst_rtsp_url_get_request_uri
gst_rtsp_url_set_port
gst_rtsp_url_get_port
gst_rtsp_url_decode_path_components
<SUBSECTION Standard>
gst_rtsp_url_get_type
</SECTION>
@ -1599,6 +1602,9 @@ GstSDPConnection
GST_SDP_BWTYPE_CT
GST_SDP_BWTYPE_AS
GST_SDP_BWTYPE_EXT_PREFIX
GST_SDP_BWTYPE_RR
GST_SDP_BWTYPE_RS
GST_SDP_BWTYPE_TIAS
GstSDPBandwidth
GstSDPTime
GstSDPZone
@ -1617,6 +1623,8 @@ gst_sdp_message_as_text
gst_sdp_message_parse_uri
gst_sdp_message_as_uri
gst_sdp_address_is_multicast
gst_sdp_message_get_version
gst_sdp_message_set_version
gst_sdp_message_get_origin
@ -1907,6 +1915,95 @@ gst_codec_utils_mpeg4video_get_level
gst_codec_utils_mpeg4video_caps_set_level_and_profile
</SECTION>
<SECTION>
<FILE>encoding-profile</FILE>
<INCLUDE>gst/pbutils/encoding-profile.h</INCLUDE>
GstEncodingProfile
gst_encoding_profile_unref
gst_encoding_profile_ref
gst_encoding_profile_find
gst_encoding_profile_get_name
gst_encoding_profile_get_description
gst_encoding_profile_get_format
gst_encoding_profile_get_preset
gst_encoding_profile_get_presence
gst_encoding_profile_get_restriction
gst_encoding_profile_set_name
gst_encoding_profile_set_description
gst_encoding_profile_set_format
gst_encoding_profile_set_preset
gst_encoding_profile_set_restriction
gst_encoding_profile_set_presence
gst_encoding_profile_is_equal
gst_encoding_profile_get_input_caps
gst_encoding_profile_get_type_nick
<SUBSECTION container>
GstEncodingContainerProfile
gst_encoding_container_profile_new
gst_encoding_container_profile_add_profile
gst_encoding_container_profile_contains_profile
gst_encoding_container_profile_get_profiles
<SUBSECTION audio>
GstEncodingAudioProfile
gst_encoding_audio_profile_new
<SUBSECTION video>
GstEncodingVideoProfile
gst_encoding_video_profile_new
gst_encoding_video_profile_get_pass
gst_encoding_video_profile_get_variableframerate
gst_encoding_video_profile_set_pass
gst_encoding_video_profile_set_variableframerate
<SUBSECTION targets>
GST_ENCODING_CATEGORY_DEVICE
GST_ENCODING_CATEGORY_ONLINE_SERVICE
GST_ENCODING_CATEGORY_STORAGE_EDITING
GST_ENCODING_CATEGORY_CAPTURE
GstEncodingTarget
gst_encoding_target_unref
gst_encoding_target_ref
gst_encoding_target_new
gst_encoding_target_get_name
gst_encoding_target_get_category
gst_encoding_target_get_description
gst_encoding_target_get_profiles
gst_encoding_target_get_profile
gst_encoding_target_add_profile
gst_encoding_target_save
gst_encoding_target_save_to_file
gst_encoding_target_load
gst_encoding_target_load_from_file
gst_encoding_list_all_targets
gst_encoding_list_available_categories
<SUBSECTION Standard>
GST_ENCODING_PROFILE
GST_IS_ENCODING_PROFILE
GST_TYPE_ENCODING_PROFILE
gst_encoding_profile_get_type
GST_ENCODING_TARGET
GST_IS_ENCODING_TARGET
GST_TYPE_ENCODING_TARGET
gst_encoding_target_get_type
GstEncodingProfileClass
GST_TYPE_ENCODING_CONTAINER_PROFILE
GST_ENCODING_CONTAINER_PROFILE
gst_encoding_container_profile_get_type
GST_TYPE_ENCODING_VIDEO_PROFILE
GST_ENCODING_VIDEO_PROFILE
GST_IS_ENCODING_VIDEO_PROFILE
GstEncodingVideoProfileClass
gst_encoding_video_profile_get_type
GST_TYPE_ENCODING_AUDIO_PROFILE
GST_ENCODING_AUDIO_PROFILE
GST_IS_ENCODING_AUDIO_PROFILE
GstEncodingAudioProfileClass
gst_encoding_audio_profile_get_type
GST_IS_ENCODING_CONTAINER_PROFILE
GstEncodingContainerProfileClass
GstEncodingTargetClass
</SECTION>
# video
<SECTION>
@ -1945,6 +2042,9 @@ GST_VIDEO_CAPS_YUV
GST_VIDEO_CAPS_xBGR
GST_VIDEO_CAPS_xRGB
GST_VIDEO_CAPS_xRGB_HOST_ENDIAN
GST_VIDEO_CAPS_BGR_15
GST_VIDEO_CAPS_BGR_16
GST_VIDEO_CAPS_RGB8_PALETTED
GST_VIDEO_CAPS_GRAY8
GST_VIDEO_CAPS_GRAY16
GST_VIDEO_FPS_RANGE
@ -1985,6 +2085,7 @@ gst_video_parse_caps_framerate
gst_video_parse_caps_pixel_aspect_ratio
gst_video_parse_caps_color_matrix
gst_video_parse_caps_chroma_site
gst_video_parse_caps_palette
GstVideoConvertFrameCallback
gst_video_convert_frame
gst_video_convert_frame_async
@ -1992,6 +2093,7 @@ gst_video_event_new_still_frame
gst_video_event_parse_still_frame
<SUBSECTION Standard>
gst_video_format_get_type
GST_TYPE_VIDEO_FORMAT
</SECTION>
<SECTION>
@ -2051,6 +2153,8 @@ gst_discoverer_info_get_stream_info
gst_discoverer_info_get_stream_list
gst_discoverer_info_get_tags
gst_discoverer_info_get_uri
gst_discoverer_info_get_seekable
gst_discoverer_info_ref
gst_discoverer_info_unref
<SUBSECTION>
GstDiscovererStreamInfo
@ -2066,8 +2170,6 @@ gst_discoverer_stream_info_ref
gst_discoverer_stream_info_unref
gst_discoverer_stream_info_list_free
gst_discoverer_stream_info_get_stream_type_nick
gst_discoverer_info_copy
gst_discoverer_info_ref
gst_discoverer_info_get_audio_streams
gst_discoverer_info_get_container_streams
gst_discoverer_info_get_streams
@ -2122,6 +2224,7 @@ gst_discoverer_audio_info_get_type
gst_discoverer_container_info_get_type
gst_discoverer_get_type
gst_discoverer_info_get_type
gst_discoverer_info_copy
gst_discoverer_result_get_type
gst_discoverer_stream_info_get_type
gst_discoverer_video_info_get_type

View file

@ -59,3 +59,14 @@ gst_video_sink_get_type
#include <gst/pbutils/pbutils.h>
gst_discoverer_get_type
#include <gst/pbutils/encoding-profile.h>
#include <gst/pbutils/encoding-target.h>
gst_encoding_profile_get_type
gst_encoding_video_profile_get_type
gst_encoding_video_profile_get_type
gst_encoding_audio_profile_get_type
gst_encoding_container_profile_get_type
gst_encoding_target_get_type

View file

@ -50,7 +50,7 @@ MKDB_OPTIONS=--sgml-mode
# Extra options to supply to gtkdoc-fixref.
FIXXREF_OPTIONS=--extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html \
--extra-dir=$(GST_PREFIX)/share/gtk-doc/html \
--extra-dir=$(datadir)/gtk-doc/html
--extra-dir=$(datadir)/gtk-doc/html
# Used for dependencies.
HFILE_GLOB=$(DOC_SOURCE_DIR)/*/*/*.h
@ -102,6 +102,7 @@ EXTRA_HFILES = \
$(top_srcdir)/gst/audioconvert/audioconvert.h \
$(top_srcdir)/gst/audioconvert/gstaudioconvert.h \
$(top_srcdir)/gst/audiotestsrc/gstaudiotestsrc.h \
$(top_srcdir)/gst/encoding/gstencodebin.h \
$(top_srcdir)/gst/ffmpegcolorspace/gstffmpegcolorspace.h \
$(top_srcdir)/gst/gdp/gstgdpdepay.h \
$(top_srcdir)/gst/gdp/gstgdppay.h \

View file

@ -31,6 +31,7 @@
<xi:include href="xml/element-clockoverlay.xml" />
<xi:include href="xml/element-decodebin.xml" />
<xi:include href="xml/element-decodebin2.xml" />
<xi:include href="xml/element-encodebin.xml" />
<xi:include href="xml/element-ffmpegcolorspace.xml" />
<xi:include href="xml/element-gdpdepay.xml" />
<xi:include href="xml/element-gdppay.xml" />
@ -80,6 +81,7 @@
<xi:include href="xml/plugin-audiotestsrc.xml" />
<xi:include href="xml/plugin-cdparanoia.xml" />
<xi:include href="xml/plugin-decodebin.xml" />
<xi:include href="xml/plugin-encoding.xml" />
<xi:include href="xml/plugin-ffmpegcolorspace.xml" />
<xi:include href="xml/plugin-gdp.xml" />
<xi:include href="xml/plugin-gio.xml" />

View file

@ -247,6 +247,22 @@ GstDecodeBin2
<SUBSECTION Standard>
</SECTION>
<SECTION>
<FILE>element-encodebin</FILE>
<TITLE>encodebin</TITLE>
GstEncodeBin
<SUBSECTION Standard>
GST_ENCODE_BIN
GST_ENCODE_BIN_CLASS
GST_IS_ENCODE_BIN
GST_IS_ENCODE_BIN_CLASS
GST_TYPE_ENCODE_BIN
GstEncodeBinClass
gst_encode_bin_get_type
</SECTION>
<SECTION>
<FILE>element-ffmpegcolorspace</FILE>
<TITLE>ffmpegcolorspace</TITLE>

View file

@ -158,6 +158,26 @@
<DEFAULT>TRUE</DEFAULT>
</ARG>
<ARG>
<NAME>GstXvImageSink::window-height</NAME>
<TYPE>guint64</TYPE>
<RANGE></RANGE>
<FLAGS>r</FLAGS>
<NICK>window-height</NICK>
<BLURB>Height of the window.</BLURB>
<DEFAULT>0</DEFAULT>
</ARG>
<ARG>
<NAME>GstXvImageSink::window-width</NAME>
<TYPE>guint64</TYPE>
<RANGE></RANGE>
<FLAGS>r</FLAGS>
<NICK>window-width</NICK>
<BLURB>Width of the window.</BLURB>
<DEFAULT>0</DEFAULT>
</ARG>
<ARG>
<NAME>GstXImageSink::display</NAME>
<TYPE>gchar*</TYPE>
@ -218,6 +238,26 @@
<DEFAULT>TRUE</DEFAULT>
</ARG>
<ARG>
<NAME>GstXImageSink::window-height</NAME>
<TYPE>guint64</TYPE>
<RANGE></RANGE>
<FLAGS>r</FLAGS>
<NICK>window-height</NICK>
<BLURB>Height of the window.</BLURB>
<DEFAULT>0</DEFAULT>
</ARG>
<ARG>
<NAME>GstXImageSink::window-width</NAME>
<TYPE>guint64</TYPE>
<RANGE></RANGE>
<FLAGS>r</FLAGS>
<NICK>window-width</NICK>
<BLURB>Width of the window.</BLURB>
<DEFAULT>0</DEFAULT>
</ARG>
<ARG>
<NAME>GstV4lSrc::autoprobe</NAME>
<TYPE>gboolean</TYPE>
@ -3215,7 +3255,7 @@
<FLAGS>rw</FLAGS>
<NICK>Stream Type</NICK>
<BLURB>the type of the stream.</BLURB>
<DEFAULT>Stream</DEFAULT>
<DEFAULT>GST_APP_STREAM_TYPE_STREAM</DEFAULT>
</ARG>
<ARG>
@ -3378,3 +3418,63 @@
<DEFAULT>NULL</DEFAULT>
</ARG>
<ARG>
<NAME>GstEncodeBin::audio-jitter-tolerance</NAME>
<TYPE>guint64</TYPE>
<RANGE></RANGE>
<FLAGS>rw</FLAGS>
<NICK>Audio jitter tolerance</NICK>
<BLURB>Amount of timestamp jitter/imperfection to allow on audio streams before inserting/dropping samples (ns).</BLURB>
<DEFAULT>20000000</DEFAULT>
</ARG>
<ARG>
<NAME>GstEncodeBin::avoid-reencoding</NAME>
<TYPE>gboolean</TYPE>
<RANGE></RANGE>
<FLAGS>rw</FLAGS>
<NICK>Avoid re-encoding</NICK>
<BLURB>Whether to re-encode portions of compatible video streams that lay on segment boundaries.</BLURB>
<DEFAULT>FALSE</DEFAULT>
</ARG>
<ARG>
<NAME>GstEncodeBin::profile</NAME>
<TYPE>GstEncodingProfile*</TYPE>
<RANGE></RANGE>
<FLAGS>rw</FLAGS>
<NICK>Profile</NICK>
<BLURB>The GstEncodingProfile to use.</BLURB>
<DEFAULT></DEFAULT>
</ARG>
<ARG>
<NAME>GstEncodeBin::queue-buffers-max</NAME>
<TYPE>guint</TYPE>
<RANGE></RANGE>
<FLAGS>rw</FLAGS>
<NICK>Max. size (buffers)</NICK>
<BLURB>Max. number of buffers in the queue (0=disable).</BLURB>
<DEFAULT>200</DEFAULT>
</ARG>
<ARG>
<NAME>GstEncodeBin::queue-bytes-max</NAME>
<TYPE>guint</TYPE>
<RANGE></RANGE>
<FLAGS>rw</FLAGS>
<NICK>Max. size (kB)</NICK>
<BLURB>Max. amount of data in the queue (bytes, 0=disable).</BLURB>
<DEFAULT>10485760</DEFAULT>
</ARG>
<ARG>
<NAME>GstEncodeBin::queue-time-max</NAME>
<TYPE>guint64</TYPE>
<RANGE></RANGE>
<FLAGS>rw</FLAGS>
<NICK>Max. size (ns)</NICK>
<BLURB>Max. amount of data in the queue (in ns, 0=disable).</BLURB>
<DEFAULT>1000000000</DEFAULT>
</ARG>

View file

@ -56,6 +56,7 @@ GObject
GstBin
GstDecodeBin
GstDecodeBin2
GstEncodeBin
GstPipeline
GstPlayBaseBin
GstPlayBin
@ -73,7 +74,6 @@ GObject
GstOgmAudioParse
GstOgmTextParse
GstOgmVideoParse
GstPlaybin2InputSelector
GstSsaParse
GstStreamSelector
GstSubParse
@ -85,12 +85,20 @@ GObject
GstTheoraEnc
GstTheoraParse
GstVideoRate
GstVisual
GstVisualbumpscope
GstVisualcorona
GstVisualinfinite
GstVisualjakdaw
GstVisualjess
GstVisuallv_analyzer
GstVisuallv_scope
GstVisualoinksie
GstVorbisDec
GstVorbisEnc
GstVorbisParse
GstVorbisTag
GstPad
GstPlaybin2SelectorPad
GstPadTemplate
GstPlugin
GstPluginFeature

View file

@ -3,29 +3,30 @@ GstPipeline GstChildProxy
GstPlayBaseBin GstChildProxy
GstPlayBin GstChildProxy
GstPlayBin2 GstChildProxy GstStreamVolume
GstDecodeBin2 GstChildProxy
GstURIDecodeBin GstChildProxy
GstDecodeBin GstChildProxy
GstPlaySink GstChildProxy
GstSubtitleOverlay GstChildProxy
GstDecodeBin2 GstChildProxy
GstURIDecodeBin GstChildProxy
GstEncodeBin GstChildProxy
GstVorbisEnc GstTagSetter GstPreset
GstVorbisTag GstTagSetter
GstCddaBaseSrc GstURIHandler
GstCdParanoiaSrc GstURIHandler
GstAlsaSrc GstImplementsInterface GstMixer GstPropertyProbe
GstV4lElement GstImplementsInterface GstTuner GstXOverlay GstColorBalance GstPropertyProbe
GstV4lSrc GstImplementsInterface GstTuner GstXOverlay GstColorBalance GstPropertyProbe
GstGnomeVFSSrc GstURIHandler
GstGioSrc GstURIHandler
GstGnomeVFSSrc GstURIHandler
GstAppSrc GstURIHandler
GstGnomeVFSSink GstURIHandler
GstAlsaSink GstPropertyProbe
GstGioSink GstURIHandler
GstAlsaSink GstPropertyProbe
GstGnomeVFSSink GstURIHandler
GstXImageSink GstImplementsInterface GstNavigation GstXOverlay
GstXvImageSink GstImplementsInterface GstNavigation GstXOverlay GstColorBalance GstPropertyProbe
GstAppSink GstURIHandler
GstVorbisEnc GstTagSetter GstPreset
GstVorbisTag GstTagSetter
GstTheoraEnc GstPreset
GstAlsaMixerElement GstImplementsInterface GstMixer GstPropertyProbe
GstTheoraEnc GstPreset
GstOggMux GstPreset
GstVolume GstImplementsInterface GstMixer GstStreamVolume
PangoCairoFcFontMap PangoCairoFontMap

View file

@ -2,9 +2,9 @@ GstChildProxy GstObject
GstTagSetter GstElement
GstImplementsInterface GstElement
GstMixer GstImplementsInterface GstElement
GstTuner GstImplementsInterface GstElement
GstXOverlay GstImplementsInterface GstElement
GstColorBalance GstImplementsInterface GstElement
GstTuner GstImplementsInterface GstElement
GstStreamVolume GObject
GFile GObject
PangoCairoFontMap PangoFontMap
GFile GObject

View file

@ -471,3 +471,11 @@ GstPlaySink *gstplaysink
GstCaps *arg1
</SIGNAL>
<SIGNAL>
<NAME>GstEncodeBin::request-pad</NAME>
<RETURNS>GstPad*</RETURNS>
<FLAGS>la</FLAGS>
GstEncodeBin *gstencodebin
GstCaps *arg1
</SIGNAL>

View file

@ -3,7 +3,7 @@
<description>Adds multiple streams</description>
<filename>../../gst/adder/.libs/libgstadder.so</filename>
<basename>libgstadder.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>ALSA plugin library</description>
<filename>../../ext/alsa/.libs/libgstalsa.so</filename>
<basename>libgstalsa.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>Elements used to communicate with applications</description>
<filename>../../gst/app/.libs/libgstapp.so</filename>
<basename>libgstapp.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>Convert audio to different formats</description>
<filename>../../gst/audioconvert/.libs/libgstaudioconvert.so</filename>
<basename>libgstaudioconvert.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>Adjusts audio frames</description>
<filename>../../gst/audiorate/.libs/libgstaudiorate.so</filename>
<basename>libgstaudiorate.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>Resamples audio</description>
<filename>../../gst/audioresample/.libs/libgstaudioresample.so</filename>
<basename>libgstaudioresample.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>Creates audio test signals of given frequency and volume</description>
<filename>../../gst/audiotestsrc/.libs/libgstaudiotestsrc.so</filename>
<basename>libgstaudiotestsrc.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>Read audio from CD in paranoid mode</description>
<filename>../../ext/cdparanoia/.libs/libgstcdparanoia.so</filename>
<basename>libgstcdparanoia.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>decoder bin</description>
<filename>../../gst/playback/.libs/libgstdecodebin.so</filename>
<basename>libgstdecodebin.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -0,0 +1,46 @@
<plugin>
<name>encoding</name>
<description>various encoding-related elements</description>
<filename>../../gst/encoding/.libs/libgstencodebin.so</filename>
<basename>libgstencodebin.so</basename>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>
<origin>Unknown package origin</origin>
<elements>
<element>
<name>encodebin</name>
<longname>Encoder Bin</longname>
<class>Generic/Bin/Encoder</class>
<description>Convenience encoding/muxing element</description>
<author>Edward Hervey &lt;edward.hervey@collabora.co.uk&gt;</author>
<pads>
<caps>
<name>audio_%d</name>
<direction>sink</direction>
<presence>request</presence>
<details>ANY</details>
</caps>
<caps>
<name>private_%d</name>
<direction>sink</direction>
<presence>request</presence>
<details>ANY</details>
</caps>
<caps>
<name>video_%d</name>
<direction>sink</direction>
<presence>request</presence>
<details>ANY</details>
</caps>
<caps>
<name>src</name>
<direction>source</direction>
<presence>always</presence>
<details>ANY</details>
</caps>
</pads>
</element>
</elements>
</plugin>

View file

@ -3,7 +3,7 @@
<description>colorspace conversion copied from FFMpeg 0.4.9-pre1</description>
<filename>../../gst/ffmpegcolorspace/.libs/libgstffmpegcolorspace.so</filename>
<basename>libgstffmpegcolorspace.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>FFMpeg</package>

View file

@ -3,7 +3,7 @@
<description>Payload/depayload GDP packets</description>
<filename>../../gst/gdp/.libs/libgstgdp.so</filename>
<basename>libgstgdp.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>GIO elements</description>
<filename>../../ext/gio/.libs/libgstgio.so</filename>
<basename>libgstgio.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>elements to read from and write to Gnome-VFS uri&apos;s</description>
<filename>../../ext/gnomevfs/.libs/libgstgnomevfs.so</filename>
<basename>libgstgnomevfs.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>libvisual visualization plugins</description>
<filename>../../ext/libvisual/.libs/libgstlibvisual.so</filename>
<basename>libgstlibvisual.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>ogg stream manipulation (info about ogg: http://xiph.org)</description>
<filename>../../ext/ogg/.libs/libgstogg.so</filename>
<basename>libgstogg.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>Pango-based text rendering and overlay</description>
<filename>../../ext/pango/.libs/libgstpango.so</filename>
<basename>libgstpango.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>various playback elements</description>
<filename>../../gst/playback/.libs/libgstplaybin.so</filename>
<basename>libgstplaybin.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>Subtitle parsing</description>
<filename>../../gst/subparse/.libs/libgstsubparse.so</filename>
<basename>libgstsubparse.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>transfer data over the network via TCP</description>
<filename>../../gst/tcp/.libs/libgsttcp.so</filename>
<basename>libgsttcp.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>Theora plugin library</description>
<filename>../../ext/theora/.libs/libgsttheora.so</filename>
<basename>libgsttheora.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>default typefind functions</description>
<filename>../../gst/typefind/.libs/libgsttypefindfunctions.so</filename>
<basename>libgsttypefindfunctions.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>URI Decoder bin</description>
<filename>../../gst/playback/.libs/libgstdecodebin2.so</filename>
<basename>libgstdecodebin2.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>elements for Video 4 Linux</description>
<filename>../../sys/v4l/.libs/libgstvideo4linux.so</filename>
<basename>libgstvideo4linux.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>Adjusts video frames</description>
<filename>../../gst/videorate/.libs/libgstvideorate.so</filename>
<basename>libgstvideorate.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>Resizes video</description>
<filename>../../gst/videoscale/.libs/libgstvideoscale.so</filename>
<basename>libgstvideoscale.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>
@ -12,7 +12,7 @@
<element>
<name>videoscale</name>
<longname>Video scaler</longname>
<class>Filter/Effect/Video</class>
<class>Filter/Converter/Video/Scaler</class>
<description>Resizes video</description>
<author>Wim Taymans &lt;wim.taymans@chello.be&gt;</author>
<pads>

View file

@ -3,7 +3,7 @@
<description>Creates a test video stream</description>
<filename>../../gst/videotestsrc/.libs/libgstvideotestsrc.so</filename>
<basename>libgstvideotestsrc.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>plugin for controlling audio volume</description>
<filename>../../gst/volume/.libs/libgstvolume.so</filename>
<basename>libgstvolume.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>Vorbis plugin library</description>
<filename>../../ext/vorbis/.libs/libgstvorbis.so</filename>
<basename>libgstvorbis.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>X11 video output element based on standard Xlib calls</description>
<filename>../../sys/ximage/.libs/libgstximagesink.so</filename>
<basename>libgstximagesink.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -3,7 +3,7 @@
<description>XFree86 video output plugin using Xv extension</description>
<filename>../../sys/xvimage/.libs/libgstxvimagesink.so</filename>
<basename>libgstxvimagesink.so</basename>
<version>0.10.31.1</version>
<version>0.10.32.1</version>
<license>LGPL</license>
<source>gst-plugins-base</source>
<package>GStreamer Base Plug-ins git</package>

View file

@ -122,6 +122,9 @@ static GstFlowReturn gst_ogg_demux_combine_flows (GstOggDemux * ogg,
GstOggPad * pad, GstFlowReturn ret);
static void gst_ogg_demux_sync_streams (GstOggDemux * ogg);
GstCaps *gst_ogg_demux_set_header_on_caps (GstOggDemux * ogg,
GstCaps * caps, GList * headers);
GType gst_ogg_pad_get_type (void);
G_DEFINE_TYPE (GstOggPad, gst_ogg_pad, GST_TYPE_PAD);
@ -449,6 +452,8 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet,
guint64 out_offset, out_offset_end;
gboolean delta_unit = FALSE;
cret = GST_FLOW_OK;
GST_DEBUG_OBJECT (ogg,
"%p streaming to peer serial %08lx", pad, pad->map.serialno);
@ -464,7 +469,6 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet,
if ((data[0] & 1) || (data[0] & 3 && pad->map.is_ogm_text)) {
/* We don't push header packets for OGM */
cret = gst_ogg_demux_combine_flows (ogg, pad, GST_FLOW_OK);
goto done;
}
@ -485,7 +489,6 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet,
packet->b_o_s ||
(packet->bytes >= 5 && memcmp (packet->packet, "OVP80", 5) == 0)) {
/* We don't push header packets for VP8 */
cret = gst_ogg_demux_combine_flows (ogg, pad, GST_FLOW_OK);
goto done;
}
offset = 0;
@ -540,7 +543,12 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet,
} else if (pad->map.is_sparse) {
out_timestamp = gst_ogg_stream_granule_to_time (&pad->map,
pad->current_granule);
out_duration = GST_CLOCK_TIME_NONE;
if (duration == GST_CLOCK_TIME_NONE) {
out_duration = GST_CLOCK_TIME_NONE;
} else {
out_duration = gst_util_uint64_scale (duration,
GST_SECOND * pad->map.granulerate_d, pad->map.granulerate_n);
}
} else {
out_timestamp = gst_ogg_stream_granule_to_time (&pad->map,
pad->current_granule - duration);
@ -562,15 +570,11 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet,
goto empty_packet;
}
ret =
gst_pad_alloc_buffer_and_set_caps (GST_PAD_CAST (pad),
GST_BUFFER_OFFSET_NONE, packet->bytes - offset - trim,
GST_PAD_CAPS (pad), &buf);
if (!pad->added)
goto not_added;
/* combine flows */
cret = gst_ogg_demux_combine_flows (ogg, pad, ret);
if (ret != GST_FLOW_OK)
goto no_buffer;
buf = gst_buffer_new_and_alloc (packet->bytes - offset - trim);
gst_buffer_set_caps (buf, GST_PAD_CAPS (pad));
/* set delta flag for OGM content */
if (delta_unit)
@ -651,23 +655,17 @@ done:
empty_packet:
{
GST_DEBUG_OBJECT (ogg, "Skipping empty packet");
cret = gst_ogg_demux_combine_flows (ogg, pad, GST_FLOW_OK);
goto done;
}
no_timestamp:
{
GST_DEBUG_OBJECT (ogg, "skipping packet: no valid granule found yet");
cret = gst_ogg_demux_combine_flows (ogg, pad, GST_FLOW_OK);
goto done;
}
no_buffer:
not_added:
{
GST_DEBUG_OBJECT (ogg,
"%p could not get buffer from peer %08lx, %d (%s), combined %d (%s)",
pad, pad->map.serialno, ret, gst_flow_get_name (ret),
cret, gst_flow_get_name (cret));
GST_DEBUG_OBJECT (ogg, "pad not added yet");
goto done;
}
}
@ -1398,10 +1396,7 @@ gst_ogg_demux_sink_event (GstPad * pad, GstEvent * event)
return res;
}
/* submit the given buffer to the ogg sync.
*
* Returns the number of bytes submited.
*/
/* submit the given buffer to the ogg sync */
static GstFlowReturn
gst_ogg_demux_submit_buffer (GstOggDemux * ogg, GstBuffer * buffer)
{
@ -1705,6 +1700,47 @@ gst_ogg_demux_deactivate_current_chain (GstOggDemux * ogg)
return TRUE;
}
GstCaps *
gst_ogg_demux_set_header_on_caps (GstOggDemux * ogg, GstCaps * caps,
GList * headers)
{
GstStructure *structure;
GValue array = { 0 };
GST_LOG_OBJECT (ogg, "caps: %" GST_PTR_FORMAT, caps);
if (G_UNLIKELY (!caps))
return NULL;
if (G_UNLIKELY (!headers))
return NULL;
caps = gst_caps_make_writable (caps);
structure = gst_caps_get_structure (caps, 0);
g_value_init (&array, GST_TYPE_ARRAY);
while (headers) {
GValue value = { 0 };
GstBuffer *buffer;
ogg_packet *op = headers->data;
g_assert (op);
buffer = gst_buffer_new_and_alloc (op->bytes);
memcpy (GST_BUFFER_DATA (buffer), op->packet, op->bytes);
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_IN_CAPS);
g_value_init (&value, GST_TYPE_BUFFER);
gst_value_take_buffer (&value, buffer);
gst_value_array_append_value (&array, &value);
g_value_unset (&value);
headers = headers->next;
}
gst_structure_set_value (structure, "streamheader", &array);
g_value_unset (&array);
GST_LOG_OBJECT (ogg, "here are the newly set caps: %" GST_PTR_FORMAT, caps);
return caps;
}
static gboolean
gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain,
GstEvent * event)
@ -1728,7 +1764,6 @@ gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain,
/* first add the pads */
for (i = 0; i < chain->streams->len; i++) {
GstOggPad *pad;
GstStructure *structure;
pad = g_array_index (chain->streams, GstOggPad *, i);
@ -1746,8 +1781,6 @@ gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain,
GST_DEBUG_OBJECT (ogg, "adding pad %" GST_PTR_FORMAT, pad);
structure = gst_caps_get_structure (GST_PAD_CAPS (pad), 0);
/* activate first */
gst_pad_set_active (GST_PAD_CAST (pad), TRUE);
@ -1790,6 +1823,11 @@ gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain,
pad->map.taglist = NULL;
}
/* Set headers on caps */
pad->map.caps =
gst_ogg_demux_set_header_on_caps (ogg, pad->map.caps, pad->map.headers);
gst_pad_set_caps (GST_PAD_CAST (pad), pad->map.caps);
GST_DEBUG_OBJECT (ogg, "pushing headers");
/* push headers */
for (walk = pad->map.headers; walk; walk = g_list_next (walk)) {
@ -2068,7 +2106,7 @@ gst_ogg_demux_do_seek (GstOggDemux * ogg, GstSegment * segment,
goto next;
granulepos = ogg_page_granulepos (&og);
if (granulepos == -1) {
if (granulepos == -1 || granulepos == 0) {
GST_LOG_OBJECT (ogg, "granulepos of next page is -1");
continue;
}

View file

@ -282,7 +282,8 @@ gst_ogg_mux_ogg_pad_destroy_notify (GstCollectData * data)
GstOggPadData *oggpad = (GstOggPadData *) data;
GstBuffer *buf;
ogg_stream_clear (&oggpad->stream);
ogg_stream_clear (&oggpad->map.stream);
gst_caps_replace (&oggpad->map.caps, NULL);
if (oggpad->pagebuffers) {
while ((buf = g_queue_pop_head (oggpad->pagebuffers)) != NULL) {
@ -336,6 +337,34 @@ gst_ogg_mux_sink_event (GstPad * pad, GstEvent * event)
return ret;
}
static gboolean
gst_ogg_mux_is_serialno_present (GstOggMux * ogg_mux, guint32 serialno)
{
GSList *walk;
walk = ogg_mux->collect->data;
while (walk) {
GstOggPadData *pad = (GstOggPadData *) walk->data;
if (pad->map.serialno == serialno)
return TRUE;
walk = walk->next;
}
return FALSE;
}
static guint32
gst_ogg_mux_generate_serialno (GstOggMux * ogg_mux)
{
guint32 serialno;
do {
serialno = g_random_int_range (0, G_MAXINT32);
} while (gst_ogg_mux_is_serialno_present (ogg_mux, serialno));
return serialno;
}
static GstPad *
gst_ogg_mux_request_new_pad (GstElement * element,
GstPadTemplate * templ, const gchar * req_name)
@ -363,7 +392,7 @@ gst_ogg_mux_request_new_pad (GstElement * element,
if (req_name == NULL || strlen (req_name) < 6) {
/* no name given when requesting the pad, use random serial number */
serial = rand ();
serial = gst_ogg_mux_generate_serialno (ogg_mux);
} else {
/* parse serial number from requested padname */
serial = atoi (&req_name[5]);
@ -384,8 +413,8 @@ gst_ogg_mux_request_new_pad (GstElement * element,
sizeof (GstOggPadData), gst_ogg_mux_ogg_pad_destroy_notify);
ogg_mux->active_pads++;
oggpad->serial = serial;
ogg_stream_init (&oggpad->stream, serial);
oggpad->map.serialno = serial;
ogg_stream_init (&oggpad->map.stream, oggpad->map.serialno);
oggpad->packetno = 0;
oggpad->pageno = 0;
oggpad->eos = FALSE;
@ -394,7 +423,10 @@ gst_ogg_mux_request_new_pad (GstElement * element,
oggpad->new_page = TRUE;
oggpad->first_delta = FALSE;
oggpad->prev_delta = FALSE;
oggpad->data_pushed = FALSE;
oggpad->pagebuffers = g_queue_new ();
oggpad->map.headers = NULL;
oggpad->map.queued = NULL;
oggpad->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (newpad);
gst_pad_set_event_function (newpad,
@ -750,7 +782,6 @@ gst_ogg_mux_queue_pads (GstOggMux * ogg_mux)
/* try to get a new buffer for this pad if needed and possible */
if (pad->buffer == NULL) {
GstBuffer *buf;
gboolean incaps;
/* shift the buffer along if needed (it's okay if next_buffer is NULL) */
if (pad->buffer == NULL) {
@ -769,19 +800,46 @@ gst_ogg_mux_queue_pads (GstOggMux * ogg_mux)
GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT))
ogg_mux->delta_pad = pad;
incaps = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
/* if we need headers */
if (pad->state == GST_OGG_PAD_STATE_CONTROL) {
/* and we have one */
if (incaps) {
ogg_packet packet;
gboolean is_header;
packet.packet = GST_BUFFER_DATA (buf);
packet.bytes = GST_BUFFER_SIZE (buf);
if (GST_BUFFER_OFFSET_END_IS_VALID (buf))
packet.granulepos = GST_BUFFER_OFFSET_END (buf);
else
packet.granulepos = 0;
/* if we're not yet in data mode, ensure we're setup on the first packet */
if (!pad->have_type) {
pad->have_type = gst_ogg_stream_setup_map (&pad->map, &packet);
if (!pad->have_type) {
GST_ERROR_OBJECT (pad, "mapper didn't recognise input stream "
"(pad caps: %" GST_PTR_FORMAT ")", GST_PAD_CAPS (pad));
} else {
GST_DEBUG_OBJECT (pad, "caps detected: %" GST_PTR_FORMAT,
pad->map.caps);
}
}
if (pad->have_type)
is_header = gst_ogg_stream_packet_is_header (&pad->map, &packet);
else /* fallback (FIXME 0.11: remove IN_CAPS hack) */
is_header = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
if (is_header) {
GST_DEBUG_OBJECT (ogg_mux,
"got incaps buffer in control state, ignoring");
"got header buffer in control state, ignoring");
/* just ignore */
gst_buffer_unref (buf);
buf = NULL;
} else {
GST_DEBUG_OBJECT (ogg_mux,
"got data buffer in control state, switching " "to data mode");
"got data buffer in control state, switching to data mode");
/* this is a data buffer so switch to data state */
pad->state = GST_OGG_PAD_STATE_DATA;
}
@ -798,7 +856,7 @@ gst_ogg_mux_queue_pads (GstOggMux * ogg_mux)
/* Just gone to EOS. Flush existing page(s) */
pad->eos = TRUE;
while (ogg_stream_flush (&pad->stream, &page)) {
while (ogg_stream_flush (&pad->map.stream, &page)) {
/* Place page into the per-pad queue */
ret = gst_ogg_mux_pad_queue_page (ogg_mux, pad, &page,
pad->first_delta);
@ -973,7 +1031,7 @@ gst_ogg_mux_send_headers (GstOggMux * mux)
continue;
/* now figure out the headers */
pad->headers = gst_ogg_mux_get_headers (pad);
pad->map.headers = gst_ogg_mux_get_headers (pad);
}
GST_LOG_OBJECT (mux, "creating BOS pages");
@ -999,9 +1057,9 @@ gst_ogg_mux_send_headers (GstOggMux * mux)
GST_LOG_OBJECT (thepad, "looping over headers");
if (pad->headers) {
buf = GST_BUFFER (pad->headers->data);
pad->headers = g_list_remove (pad->headers, buf);
if (pad->map.headers) {
buf = GST_BUFFER (pad->map.headers->data);
pad->map.headers = g_list_remove (pad->map.headers, buf);
} else if (pad->buffer) {
buf = pad->buffer;
gst_buffer_ref (buf);
@ -1010,10 +1068,10 @@ gst_ogg_mux_send_headers (GstOggMux * mux)
gst_buffer_ref (buf);
} else {
/* fixme -- should be caught in the previous list traversal. */
GST_OBJECT_LOCK (pad);
GST_OBJECT_LOCK (thepad);
g_critical ("No headers or buffers on pad %s:%s",
GST_DEBUG_PAD_NAME (pad));
GST_OBJECT_UNLOCK (pad);
GST_DEBUG_PAD_NAME (thepad));
GST_OBJECT_UNLOCK (thepad);
continue;
}
@ -1030,11 +1088,11 @@ gst_ogg_mux_send_headers (GstOggMux * mux)
packet.e_o_s = 0;
/* swap the packet in */
ogg_stream_packetin (&pad->stream, &packet);
ogg_stream_packetin (&pad->map.stream, &packet);
gst_buffer_unref (buf);
GST_LOG_OBJECT (thepad, "flushing out BOS page");
if (!ogg_stream_flush (&pad->stream, &page))
if (!ogg_stream_flush (&pad->map.stream, &page))
g_critical ("Could not flush BOS page");
hbuf = gst_ogg_mux_buffer_from_page (mux, &page, FALSE);
@ -1078,7 +1136,7 @@ gst_ogg_mux_send_headers (GstOggMux * mux)
GST_LOG_OBJECT (mux, "looping over headers for pad %s:%s",
GST_DEBUG_PAD_NAME (thepad));
hwalk = pad->headers;
hwalk = pad->map.headers;
while (hwalk) {
GstBuffer *buf = GST_BUFFER (hwalk->data);
ogg_packet packet;
@ -1099,15 +1157,15 @@ gst_ogg_mux_send_headers (GstOggMux * mux)
packet.e_o_s = 0;
/* swap the packet in */
ogg_stream_packetin (&pad->stream, &packet);
ogg_stream_packetin (&pad->map.stream, &packet);
gst_buffer_unref (buf);
/* if last header, flush page */
if (hwalk == NULL) {
GST_LOG_OBJECT (mux,
"flushing page as packet %" G_GUINT64_FORMAT " is first or "
"last packet", pad->packetno);
while (ogg_stream_flush (&pad->stream, &page)) {
"last packet", packet.packetno);
while (ogg_stream_flush (&pad->map.stream, &page)) {
GstBuffer *hbuf = gst_ogg_mux_buffer_from_page (mux, &page, FALSE);
GST_LOG_OBJECT (mux, "swapped out page");
@ -1116,7 +1174,7 @@ gst_ogg_mux_send_headers (GstOggMux * mux)
} else {
GST_LOG_OBJECT (mux, "try to swap out page");
/* just try to swap out a page then */
while (ogg_stream_pageout (&pad->stream, &page) > 0) {
while (ogg_stream_pageout (&pad->map.stream, &page) > 0) {
GstBuffer *hbuf = gst_ogg_mux_buffer_from_page (mux, &page, FALSE);
GST_LOG_OBJECT (mux, "swapped out page");
@ -1124,8 +1182,8 @@ gst_ogg_mux_send_headers (GstOggMux * mux)
}
}
}
g_list_free (pad->headers);
pad->headers = NULL;
g_list_free (pad->map.headers);
pad->map.headers = NULL;
}
/* hbufs holds all buffers for the headers now */
@ -1206,9 +1264,10 @@ gst_ogg_mux_process_best_pad (GstOggMux * ogg_mux, GstOggPadData * best)
GST_LOG_OBJECT (pad->collect.pad,
GST_GP_FORMAT " stored packet %" G_GINT64_FORMAT
" will make page too long, flushing",
GST_BUFFER_OFFSET_END (pad->buffer), (gint64) pad->stream.packetno);
GST_BUFFER_OFFSET_END (pad->buffer),
(gint64) pad->map.stream.packetno);
while (ogg_stream_flush (&pad->stream, &page)) {
while (ogg_stream_flush (&pad->map.stream, &page)) {
/* end time of this page is the timestamp of the next buffer */
ogg_mux->pulling->timestamp_end = GST_BUFFER_TIMESTAMP (pad->buffer);
/* Place page into the per-pad queue */
@ -1306,11 +1365,15 @@ gst_ogg_mux_process_best_pad (GstOggMux * ogg_mux, GstOggPadData * best)
}
if (GST_BUFFER_IS_DISCONT (buf)) {
GST_LOG_OBJECT (pad->collect.pad, "got discont");
packet.packetno++;
/* No public API for this; hack things in */
pad->stream.pageno++;
force_flush = TRUE;
if (pad->data_pushed) {
GST_LOG_OBJECT (pad->collect.pad, "got discont");
packet.packetno++;
/* No public API for this; hack things in */
pad->map.stream.pageno++;
force_flush = TRUE;
} else {
GST_LOG_OBJECT (pad->collect.pad, "discont at stream start");
}
}
/* flush the currently built page if necessary */
@ -1318,7 +1381,7 @@ gst_ogg_mux_process_best_pad (GstOggMux * ogg_mux, GstOggPadData * best)
GST_LOG_OBJECT (pad->collect.pad,
GST_GP_FORMAT " forced flush of page before this packet",
GST_BUFFER_OFFSET_END (pad->buffer));
while (ogg_stream_flush (&pad->stream, &page)) {
while (ogg_stream_flush (&pad->map.stream, &page)) {
/* end time of this page is the timestamp of the next buffer */
ogg_mux->pulling->timestamp_end = GST_BUFFER_TIMESTAMP (pad->buffer);
ret = gst_ogg_mux_pad_queue_page (ogg_mux, pad, &page,
@ -1363,7 +1426,8 @@ gst_ogg_mux_process_best_pad (GstOggMux * ogg_mux, GstOggPadData * best)
if (packet.b_o_s == 1)
GST_DEBUG_OBJECT (pad->collect.pad, "swapping in BOS packet");
ogg_stream_packetin (&pad->stream, &packet);
ogg_stream_packetin (&pad->map.stream, &packet);
pad->data_pushed = TRUE;
gp_time = GST_BUFFER_OFFSET (pad->buffer);
granulepos = GST_BUFFER_OFFSET_END (pad->buffer);
@ -1381,7 +1445,7 @@ gst_ogg_mux_process_best_pad (GstOggMux * ogg_mux, GstOggPadData * best)
/* let ogg write out the pages now. The packet we got could end
* up in more than one page so we need to write them all */
if (ogg_stream_pageout (&pad->stream, &page) > 0) {
if (ogg_stream_pageout (&pad->map.stream, &page) > 0) {
/* we have a new page, so we need to timestamp it correctly.
* if this fresh packet ends on this page, then the page's granulepos
* comes from that packet, and we should set this buffer's timestamp */
@ -1392,7 +1456,7 @@ gst_ogg_mux_process_best_pad (GstOggMux * ogg_mux, GstOggPadData * best)
granulepos, (gint64) packet.packetno, GST_TIME_ARGS (timestamp));
GST_LOG_OBJECT (pad->collect.pad,
GST_GP_FORMAT " new page %ld",
GST_GP_CAST (ogg_page_granulepos (&page)), pad->stream.pageno);
GST_GP_CAST (ogg_page_granulepos (&page)), pad->map.stream.pageno);
if (ogg_page_granulepos (&page) == granulepos) {
/* the packet we streamed in finishes on the current page,
@ -1421,7 +1485,7 @@ gst_ogg_mux_process_best_pad (GstOggMux * ogg_mux, GstOggPadData * best)
/* use an inner loop here to flush the remaining pages and
* mark them as delta frames as well */
while (ogg_stream_pageout (&pad->stream, &page) > 0) {
while (ogg_stream_pageout (&pad->map.stream, &page) > 0) {
if (ogg_page_granulepos (&page) == granulepos) {
/* the page has taken up the new packet completely, which means
* the packet ends the page and we can update the gp time
@ -1598,7 +1662,7 @@ gst_ogg_mux_init_collectpads (GstCollectPads * collect)
while (walk) {
GstOggPadData *oggpad = (GstOggPadData *) walk->data;
ogg_stream_init (&oggpad->stream, oggpad->serial);
ogg_stream_init (&oggpad->map.stream, oggpad->map.serialno);
oggpad->packetno = 0;
oggpad->pageno = 0;
oggpad->eos = FALSE;
@ -1607,6 +1671,7 @@ gst_ogg_mux_init_collectpads (GstCollectPads * collect)
oggpad->new_page = TRUE;
oggpad->first_delta = FALSE;
oggpad->prev_delta = FALSE;
oggpad->data_pushed = FALSE;
oggpad->pagebuffers = g_queue_new ();
walk = g_slist_next (walk);
@ -1623,7 +1688,7 @@ gst_ogg_mux_clear_collectpads (GstCollectPads * collect)
GstOggPadData *oggpad = (GstOggPadData *) walk->data;
GstBuffer *buf;
ogg_stream_clear (&oggpad->stream);
ogg_stream_clear (&oggpad->map.stream);
while ((buf = g_queue_pop_head (oggpad->pagebuffers)) != NULL) {
gst_buffer_unref (buf);

View file

@ -25,6 +25,7 @@
#include <gst/gst.h>
#include <gst/base/gstcollectpads.h>
#include "gstoggstream.h"
G_BEGIN_DECLS
@ -49,13 +50,14 @@ typedef struct
{
GstCollectData collect; /* we extend the CollectData */
GstOggStream map;
gboolean have_type;
/* These two buffers make a very simple queue - they enter as 'next_buffer'
* and (usually) leave as 'buffer', except at EOS, when buffer will be NULL */
GstBuffer *buffer; /* the first waiting buffer for the pad */
GstBuffer *next_buffer; /* the second waiting buffer for the pad */
gint serial;
ogg_stream_state stream;
gint64 packetno; /* number of next packet */
gint64 pageno; /* number of next page */
guint64 duration; /* duration of current page */
@ -71,13 +73,12 @@ typedef struct
GstOggPadState state; /* state of the pad */
GList *headers;
GQueue *pagebuffers; /* List of pages in buffers ready for pushing */
gboolean new_page; /* starting a new page */
gboolean first_delta; /* was the first packet in the page a delta */
gboolean prev_delta; /* was the previous buffer a delta frame */
gboolean data_pushed; /* whether we pushed data already */
GstPadEventFunction collect_event;

View file

@ -115,6 +115,7 @@ free_stream (GstOggStream * stream)
{
g_list_foreach (stream->headers, (GFunc) gst_mini_object_unref, NULL);
g_list_foreach (stream->unknown_pages, (GFunc) gst_mini_object_unref, NULL);
g_list_foreach (stream->stored_buffers, (GFunc) gst_mini_object_unref, NULL);
g_free (stream);
}
@ -281,29 +282,41 @@ gst_ogg_parse_dispose (GObject * object)
G_OBJECT_CLASS (parent_class)->dispose (object);
}
/* submit the given buffer to the ogg sync.
*
* Returns the number of bytes submited.
*/
static gint
/* submit the given buffer to the ogg sync */
static GstFlowReturn
gst_ogg_parse_submit_buffer (GstOggParse * ogg, GstBuffer * buffer)
{
guint size;
guint8 *data;
gchar *oggbuffer;
GstFlowReturn ret = GST_FLOW_OK;
size = GST_BUFFER_SIZE (buffer);
data = GST_BUFFER_DATA (buffer);
/* We now have a buffer, submit it to the ogg sync layer */
oggbuffer = ogg_sync_buffer (&ogg->sync, size);
memcpy (oggbuffer, data, size);
ogg_sync_wrote (&ogg->sync, size);
GST_DEBUG_OBJECT (ogg, "submitting %u bytes", size);
if (G_UNLIKELY (size == 0))
goto done;
/* We've copied all the neccesary data, so we're done with the buffer */
oggbuffer = ogg_sync_buffer (&ogg->sync, size);
if (G_UNLIKELY (oggbuffer == NULL)) {
GST_ELEMENT_ERROR (ogg, STREAM, DECODE,
(NULL), ("failed to get ogg sync buffer"));
ret = GST_FLOW_ERROR;
goto done;
}
memcpy (oggbuffer, data, size);
if (G_UNLIKELY (ogg_sync_wrote (&ogg->sync, size) < 0)) {
GST_ELEMENT_ERROR (ogg, STREAM, DECODE,
(NULL), ("failed to write %d bytes to the sync buffer", size));
ret = GST_FLOW_ERROR;
}
done:
gst_buffer_unref (buffer);
return size;
return ret;
}
static void
@ -350,7 +363,7 @@ gst_ogg_parse_is_header (GstOggParse * ogg, GstOggStream * stream,
static GstBuffer *
gst_ogg_parse_buffer_from_page (ogg_page * page,
guint64 offset, gboolean keyframe, GstClockTime timestamp)
guint64 offset, GstClockTime timestamp)
{
int size = page->header_len + page->body_len;
GstBuffer *buf = gst_buffer_new_and_alloc (size);
@ -361,9 +374,6 @@ gst_ogg_parse_buffer_from_page (ogg_page * page,
GST_BUFFER_TIMESTAMP (buf) = timestamp;
GST_BUFFER_OFFSET (buf) = offset;
GST_BUFFER_OFFSET_END (buf) = offset + size;
if (!keyframe) {
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
}
return buf;
}
@ -435,7 +445,7 @@ gst_ogg_parse_chain (GstPad * pad, GstBuffer * buffer)
keyframe = TRUE;
}
pagebuffer = gst_ogg_parse_buffer_from_page (&page, startoffset,
keyframe, buffertimestamp);
buffertimestamp);
/* We read out 'ret' bytes, so we set the next offset appropriately */
ogg->offset += ret;
@ -647,15 +657,42 @@ gst_ogg_parse_chain (GstPad * pad, GstBuffer * buffer)
g_list_free (stream->unknown_pages);
stream->unknown_pages = NULL;
}
}
gst_buffer_set_caps (pagebuffer, caps);
result = gst_pad_push (ogg->srcpad, GST_BUFFER (pagebuffer));
if (result != GST_FLOW_OK)
return result;
if (granule == -1) {
stream->stored_buffers = g_list_append (stream->stored_buffers,
pagebuffer);
} else {
/* Normal data page, submit buffer */
if (stream->stored_buffers) {
int j;
for (j = 0; j < g_list_length (stream->stored_buffers); j++) {
GstBuffer *buf =
GST_BUFFER (g_list_nth_data (stream->stored_buffers, j));
gst_buffer_set_caps (buf, ogg->caps);
GST_BUFFER_TIMESTAMP (buf) = buffertimestamp;
if (!keyframe) {
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
} else {
keyframe = FALSE;
}
result = gst_pad_push (ogg->srcpad, buf);
if (result != GST_FLOW_OK)
return result;
}
g_list_free (stream->stored_buffers);
stream->stored_buffers = NULL;
}
gst_buffer_set_caps (pagebuffer, ogg->caps);
if (!keyframe) {
GST_BUFFER_FLAG_SET (pagebuffer, GST_BUFFER_FLAG_DELTA_UNIT);
} else {
keyframe = FALSE;
}
result = gst_pad_push (ogg->srcpad, GST_BUFFER (pagebuffer));
if (result != GST_FLOW_OK)
return result;

View file

@ -255,6 +255,11 @@ granule_to_granulepos_default (GstOggStream * pad, gint64 granule,
gint64 keyoffset;
if (pad->granuleshift != 0) {
/* If we don't know where the previous keyframe is yet, assume it is
at 0 or 1, depending on bitstream version. If nothing else, this
avoids getting negative granpos back. */
if (keyframe_granule < 0)
keyframe_granule = pad->theora_has_zero_keyoffset ? 0 : 1;
keyoffset = granule - keyframe_granule;
return (keyframe_granule << pad->granuleshift) | keyoffset;
} else {
@ -342,9 +347,14 @@ setup_theora_mapper (GstOggStream * pad, ogg_packet * packet)
{
guint8 *data = packet->packet;
guint w, h, par_d, par_n;
guint8 vmaj, vmin, vrev;
w = GST_READ_UINT24_BE (data + 14) & 0xFFFFF0;
h = GST_READ_UINT24_BE (data + 17) & 0xFFFFF0;
vmaj = data[7];
vmin = data[8];
vrev = data[9];
w = GST_READ_UINT24_BE (data + 14) & 0xFFFFFF;
h = GST_READ_UINT24_BE (data + 17) & 0xFFFFFF;
pad->granulerate_n = GST_READ_UINT32_BE (data + 22);
pad->granulerate_d = GST_READ_UINT32_BE (data + 26);
@ -371,6 +381,12 @@ setup_theora_mapper (GstOggStream * pad, ogg_packet * packet)
return FALSE;
}
/* The interpretation of the granule position has changed with 3.2.1.
The granule is now made from the number of frames encoded, rather than
the index of the frame being encoded - so there is a difference of 1. */
pad->theora_has_zero_keyoffset =
((vmaj << 16) | (vmin << 8) | vrev) < 0x030201;
pad->caps = gst_caps_new_simple ("video/x-theora", NULL);
if (w > 0 && h > 0) {
@ -398,9 +414,6 @@ granulepos_to_granule_theora (GstOggStream * pad, gint64 granulepos)
if (pad->granuleshift != 0) {
keyindex = granulepos >> pad->granuleshift;
keyoffset = granulepos - (keyindex << pad->granuleshift);
if (keyoffset == 0) {
pad->theora_has_zero_keyoffset = TRUE;
}
if (pad->theora_has_zero_keyoffset) {
keyoffset++;
}
@ -1732,6 +1745,83 @@ setup_kate_mapper (GstOggStream * pad, ogg_packet * packet)
return TRUE;
}
static gint64
packet_duration_kate (GstOggStream * pad, ogg_packet * packet)
{
gint64 duration;
if (packet->bytes < 1)
return 0;
switch (packet->packet[0]) {
case 0x00: /* text data */
if (packet->bytes < 1 + 8 * 2) {
duration = 0;
} else {
duration = GST_READ_UINT64_LE (packet->packet + 1 + 8);
if (duration < 0)
duration = 0;
}
break;
default:
duration = GST_CLOCK_TIME_NONE;
break;
}
return duration;
}
static void
extract_tags_kate (GstOggStream * pad, ogg_packet * packet)
{
GstTagList *list = NULL;
if (packet->bytes <= 0)
return;
switch (packet->packet[0]) {
case 0x80:{
const gchar *canonical;
char language[16];
if (packet->bytes < 64) {
GST_WARNING ("Kate ID header packet is less than 64 bytes, ignored");
break;
}
/* the language tag is 16 bytes at offset 32, ensure NUL terminator */
memcpy (language, packet->packet + 32, 16);
language[15] = 0;
/* language is an ISO 639-1 code or RFC 3066 language code, we
* truncate to ISO 639-1 */
g_strdelimit (language, NULL, '\0');
canonical = gst_tag_get_language_code_iso_639_1 (language);
if (canonical) {
list = gst_tag_list_new_full (GST_TAG_LANGUAGE_CODE, canonical, NULL);
} else {
GST_WARNING ("Unknown or invalid language code %s, ignored", language);
}
break;
}
case 0x81:
tag_list_from_vorbiscomment_packet (packet,
(const guint8 *) "\201kate\0\0\0\0", 9, &list);
break;
default:
break;
}
if (list) {
if (pad->taglist) {
/* ensure the comment packet cannot override the category/language
from the identification header */
gst_tag_list_insert (pad->taglist, list, GST_TAG_MERGE_KEEP_ALL);
} else
pad->taglist = list;
}
}
/* *INDENT-OFF* */
/* indent hates our freedoms */
@ -1875,9 +1965,9 @@ const GstOggMap mappers[] = {
granule_to_granulepos_default,
NULL,
is_header_count,
packet_duration_kate,
NULL,
NULL,
NULL
extract_tags_kate
},
{
"BBCD\0", 5, 13,

View file

@ -53,6 +53,7 @@ struct _GstOggStream
/* for oggparse */
gboolean in_headers;
GList *unknown_pages;
GList *stored_buffers;
gint map;
gboolean is_skeleton;

View file

@ -15,12 +15,14 @@ libgstpango_la_SOURCES = \
libgstpango_la_CFLAGS = \
$(GST_PLUGINS_BASE_CFLAGS) \
$(GST_BASE_CFLAGS) \
$(GST_CONTROLLER_CFLAGS) \
$(GST_CFLAGS) \
$(PANGO_CFLAGS)
libgstpango_la_LIBADD = \
$(GST_PLUGINS_BASE_LIBS) \
$(top_builddir)/gst-libs/gst/video/libgstvideo-$(GST_MAJORMINOR).la \
$(GST_BASE_LIBS) \
$(GST_CONTROLLER_LIBS) \
$(GST_LIBS) \
$(PANGO_LIBS)
libgstpango_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)

View file

@ -216,6 +216,7 @@ gst_text_overlay_valign_get_type (void)
{GST_TEXT_OVERLAY_VALIGN_BOTTOM, "bottom", "bottom"},
{GST_TEXT_OVERLAY_VALIGN_TOP, "top", "top"},
{GST_TEXT_OVERLAY_VALIGN_POS, "position", "position"},
{GST_TEXT_OVERLAY_VALIGN_CENTER, "center", "center"},
{0, NULL, NULL},
};
@ -382,7 +383,7 @@ gst_text_overlay_class_init (GstTextOverlayClass * klass)
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TEXT,
g_param_spec_string ("text", "text",
"Text to be display.", DEFAULT_PROP_TEXT,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SHADING,
g_param_spec_boolean ("shaded-background", "shaded background",
"Whether to shade the background under the text area",
@ -430,7 +431,8 @@ gst_text_overlay_class_init (GstTextOverlayClass * klass)
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_XPOS,
g_param_spec_double ("xpos", "horizontal position",
"Horizontal position when using position alignment", 0, 1.0,
DEFAULT_PROP_XPOS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
DEFAULT_PROP_XPOS,
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
/**
* GstTextOverlay:ypos
*
@ -441,7 +443,8 @@ gst_text_overlay_class_init (GstTextOverlayClass * klass)
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_YPOS,
g_param_spec_double ("ypos", "vertical position",
"Vertical position when using position alignment", 0, 1.0,
DEFAULT_PROP_YPOS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
DEFAULT_PROP_YPOS,
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_WRAP_MODE,
g_param_spec_enum ("wrap-mode", "wrap mode",
"Whether to wrap the text and if so how.",
@ -463,7 +466,8 @@ gst_text_overlay_class_init (GstTextOverlayClass * klass)
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_COLOR,
g_param_spec_uint ("color", "Color",
"Color to use for text (big-endian ARGB).", 0, G_MAXUINT32,
DEFAULT_PROP_COLOR, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
DEFAULT_PROP_COLOR,
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
/**
* GstTextOverlay:line-alignment
@ -489,7 +493,8 @@ gst_text_overlay_class_init (GstTextOverlayClass * klass)
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SILENT,
g_param_spec_boolean ("silent", "silent",
"Whether to render the text string",
DEFAULT_PROP_SILENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
DEFAULT_PROP_SILENT,
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
/**
* GstTextOverlay:wait-text
*
@ -848,10 +853,9 @@ gst_text_overlay_set_property (GObject * object, guint prop_id,
overlay->wait_text = g_value_get_boolean (value);
break;
case PROP_AUTO_ADJUST_SIZE:
{
overlay->auto_adjust_size = g_value_get_boolean (value);
overlay->need_render = TRUE;
}
break;
case PROP_VERTICAL_RENDER:
overlay->use_vertical_render = g_value_get_boolean (value);
gst_text_overlay_update_render_mode (overlay);
@ -1795,6 +1799,9 @@ gst_text_overlay_push_frame (GstTextOverlay * overlay, GstBuffer * video_frame)
ypos = (gint) (overlay->height * overlay->ypos) - height / 2;
ypos = CLAMP (ypos, 0, overlay->height - height);
break;
case GST_TEXT_OVERLAY_VALIGN_CENTER:
ypos = (overlay->height - height) / 2;
break;
default:
ypos = overlay->ypad;
break;
@ -2248,6 +2255,8 @@ gst_text_overlay_video_chain (GstPad * pad, GstBuffer * buffer)
}
}
gst_object_sync_values (G_OBJECT (overlay), GST_BUFFER_TIMESTAMP (buffer));
wait_for_text_buf:
GST_OBJECT_LOCK (overlay);
@ -2532,6 +2541,8 @@ gst_text_overlay_change_state (GstElement * element, GstStateChange transition)
static gboolean
plugin_init (GstPlugin * plugin)
{
gst_controller_init (NULL, NULL);
if (!gst_element_register (plugin, "textoverlay", GST_RANK_NONE,
GST_TYPE_TEXT_OVERLAY) ||
!gst_element_register (plugin, "timeoverlay", GST_RANK_NONE,

View file

@ -3,6 +3,7 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include <gst/controller/gstcontroller.h>
#include <pango/pangocairo.h>
G_BEGIN_DECLS
@ -34,7 +35,8 @@ typedef enum {
GST_TEXT_OVERLAY_VALIGN_BASELINE,
GST_TEXT_OVERLAY_VALIGN_BOTTOM,
GST_TEXT_OVERLAY_VALIGN_TOP,
GST_TEXT_OVERLAY_VALIGN_POS
GST_TEXT_OVERLAY_VALIGN_POS,
GST_TEXT_OVERLAY_VALIGN_CENTER
} GstTextOverlayVAlign;
/**

View file

@ -175,6 +175,57 @@ granulepos_to_timestamp (GstTheoraEnc * theoraenc, ogg_int64_t granulepos)
theoraenc->info.fps_numerator);
}
/* Generate a dummy encoder context for use in th_encode_ctl queries
Release with th_encode_free()
This and the next routine from theora/examples/libtheora_info.c */
static th_enc_ctx *
dummy_encode_ctx (void)
{
th_enc_ctx *ctx;
th_info info;
/* set the minimal video parameters */
th_info_init (&info);
info.frame_width = 320;
info.frame_height = 240;
info.fps_numerator = 1;
info.fps_denominator = 1;
/* allocate and initialize a context object */
ctx = th_encode_alloc (&info);
if (!ctx)
GST_WARNING ("Failed to allocate dummy encoder context.");
/* clear the info struct */
th_info_clear (&info);
return ctx;
}
/* Query the current and maximum values for the 'speed level' setting.
This can be used to ask the encoder to trade off encoding quality
vs. performance cost, for example to adapt to realtime constraints. */
static int
check_speed_level (th_enc_ctx * ctx, int *current, int *max)
{
int ret;
/* query the current speed level */
ret = th_encode_ctl (ctx, TH_ENCCTL_GET_SPLEVEL, current, sizeof (int));
if (ret) {
GST_WARNING ("Error %d getting current speed level.", ret);
return ret;
}
/* query the maximum speed level, which varies by encoder version */
ret = th_encode_ctl (ctx, TH_ENCCTL_GET_SPLEVEL_MAX, max, sizeof (int));
if (ret) {
GST_WARNING ("Error %d getting maximum speed level.", ret);
return ret;
}
return 0;
}
static GstStaticPadTemplate theora_enc_sink_factory =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
@ -242,6 +293,21 @@ gst_theora_enc_class_init (GstTheoraEncClass * klass)
GObjectClass *gobject_class = (GObjectClass *) klass;
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
/* query runtime encoder properties */
th_enc_ctx *th_ctx;
int default_speed_level = THEORA_DEF_SPEEDLEVEL;
int max_speed_level = default_speed_level;
GST_DEBUG_CATEGORY_INIT (theoraenc_debug, "theoraenc", 0, "Theora encoder");
th_ctx = dummy_encode_ctx ();
if (th_ctx) {
if (!check_speed_level (th_ctx, &default_speed_level, &max_speed_level))
GST_WARNING
("Failed to determine settings for the speed-level property.");
th_encode_free (th_ctx);
}
gobject_class->set_property = theora_enc_set_property;
gobject_class->get_property = theora_enc_get_property;
gobject_class->finalize = theora_enc_finalize;
@ -301,40 +367,38 @@ gst_theora_enc_class_init (GstTheoraEncClass * klass)
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_SPEEDLEVEL,
g_param_spec_int ("speed-level", "Speed level",
"Controls the amount of motion vector searching done while "
"encoding. This property requires libtheora version >= 1.0",
0, 3, THEORA_DEF_SPEEDLEVEL,
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
"Controls the amount of analysis performed when encoding."
" Higher values trade compression quality for speed."
" This property requires libtheora version >= 1.0"
", and the maximum value may vary based on encoder version.",
0, max_speed_level, default_speed_level,
(GParamFlags) G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_VP3_COMPATIBLE,
g_param_spec_boolean ("vp3-compatible", "VP3 Compatible",
"Disables non-VP3 compatible features."
" This property requires libtheora version >= 1.1",
"Disables non-VP3 compatible features",
THEORA_DEF_VP3_COMPATIBLE,
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_DROP_FRAMES,
g_param_spec_boolean ("drop-frames", "VP3 Compatible",
"Allow or disallow frame dropping."
" This property requires libtheora version >= 1.1",
"Allow or disallow frame dropping",
THEORA_DEF_DROP_FRAMES,
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_CAP_OVERFLOW,
g_param_spec_boolean ("cap-overflow", "VP3 Compatible",
"Enable capping of bit reservoir overflows."
" This property requires libtheora version >= 1.1",
"Enable capping of bit reservoir overflows",
THEORA_DEF_CAP_OVERFLOW,
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_CAP_UNDERFLOW,
g_param_spec_boolean ("cap-underflow", "VP3 Compatible",
"Enable capping of bit reservoir underflows."
" This property requires libtheora version >= 1.1",
"Enable capping of bit reservoir underflows",
THEORA_DEF_CAP_UNDERFLOW,
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_RATE_BUFFER,
g_param_spec_int ("rate-buffer", "Rate Control Buffer",
"Sets the size of the rate control buffer, in units of frames. "
"The default value of 0 instructs the encoder to automatically "
"select an appropriate value."
" This property requires libtheora version >= 1.1",
"select an appropriate value",
0, 1000, THEORA_DEF_RATE_BUFFER,
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_MULTIPASS_CACHE_FILE,
@ -348,7 +412,6 @@ gst_theora_enc_class_init (GstTheoraEncClass * klass)
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gstelement_class->change_state = theora_enc_change_state;
GST_DEBUG_CATEGORY_INIT (theoraenc_debug, "theoraenc", 0, "Theora encoder");
}
static void
@ -377,7 +440,7 @@ gst_theora_enc_init (GstTheoraEnc * enc, GstTheoraEncClass * g_class)
enc->expected_ts = GST_CLOCK_TIME_NONE;
enc->speed_level = THEORA_DEF_SPEEDLEVEL;
/* enc->speed_level is set to the libtheora default by the constructor */
enc->vp3_compatible = THEORA_DEF_VP3_COMPATIBLE;
enc->drop_frames = THEORA_DEF_DROP_FRAMES;
enc->cap_overflow = THEORA_DEF_CAP_OVERFLOW;
@ -1378,13 +1441,12 @@ theora_enc_set_property (GObject * object, guint prop_id,
case PROP_BITRATE:
GST_OBJECT_LOCK (enc);
enc->video_bitrate = g_value_get_int (value) * 1000;
enc->video_quality = 0;
enc->bitrate_changed = TRUE;
GST_OBJECT_UNLOCK (enc);
break;
case PROP_QUALITY:
GST_OBJECT_LOCK (enc);
if (GST_STATE (enc) >= GST_STATE_PAUSED && enc->video_quality == 0) {
if (GST_STATE (enc) >= GST_STATE_PAUSED && enc->video_bitrate > 0) {
GST_WARNING_OBJECT (object, "Can't change from bitrate to quality mode"
" while playing");
} else {
@ -1405,6 +1467,10 @@ theora_enc_set_property (GObject * object, guint prop_id,
break;
case PROP_SPEEDLEVEL:
enc->speed_level = g_value_get_int (value);
if (enc->encoder) {
th_encode_ctl (enc->encoder, TH_ENCCTL_SET_SPLEVEL, &enc->speed_level,
sizeof (enc->speed_level));
}
break;
case PROP_VP3_COMPATIBLE:
enc->vp3_compatible = g_value_get_boolean (value);

View file

@ -827,7 +827,7 @@ vorbis_do_timestamps (GstVorbisDec * vd, GstBuffer * buf, gboolean reverse,
GstClockTime timestamp, GstClockTime duration)
{
/* interpolate reverse */
if (vd->last_timestamp != -1 && reverse)
if (vd->last_timestamp != -1 && duration != -1 && reverse)
vd->last_timestamp -= duration;
/* take buffer timestamp, use interpolated timestamp otherwise */
@ -837,11 +837,18 @@ vorbis_do_timestamps (GstVorbisDec * vd, GstBuffer * buf, gboolean reverse,
timestamp = vd->last_timestamp;
/* interpolate forwards */
if (vd->last_timestamp != -1 && !reverse)
if (vd->last_timestamp != -1 && duration != -1 && !reverse)
vd->last_timestamp += duration;
GST_BUFFER_TIMESTAMP (buf) = timestamp;
GST_BUFFER_DURATION (buf) = duration;
GST_LOG_OBJECT (vd,
"keeping timestamp %" GST_TIME_FORMAT " ts %" GST_TIME_FORMAT " dur %"
GST_TIME_FORMAT, GST_TIME_ARGS (vd->last_timestamp),
GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration));
if (buf) {
GST_BUFFER_TIMESTAMP (buf) = timestamp;
GST_BUFFER_DURATION (buf) = duration;
}
}
static GstFlowReturn
@ -850,7 +857,7 @@ vorbis_handle_data_packet (GstVorbisDec * vd, ogg_packet * packet,
{
vorbis_sample_t **pcm;
guint sample_count;
GstBuffer *out;
GstBuffer *out = NULL;
GstFlowReturn result;
gint size;
@ -910,6 +917,10 @@ vorbis_handle_data_packet (GstVorbisDec * vd, ogg_packet * packet,
result = vorbis_dec_push_reverse (vd, out);
done:
if (out == NULL) {
/* no output, still keep track of timestamps */
vorbis_do_timestamps (vd, NULL, FALSE, timestamp, duration);
}
vorbis_synthesis_read (&vd->vd, sample_count);
return result;

View file

@ -70,7 +70,8 @@ typelibsdir = $(libdir)/girepository-1.0/
typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib)
%.typelib: %.gir $(INTROSPECTION_COMPILER)
$(AM_V_GEN)$(INTROSPECTION_COMPILER) \
$(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \
$(INTROSPECTION_COMPILER) \
--includedir=$(srcdir) \
--includedir=$(builddir) \
--includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-`@GST_MAJORMINOR@ \

View file

@ -37,9 +37,9 @@ static GstBufferClass *parent_class;
GType
gst_app_buffer_get_type (void)
{
static GType _gst_app_buffer_type;
static volatile gsize app_buffer_type = 0;
if (G_UNLIKELY (_gst_app_buffer_type == 0)) {
if (g_once_init_enter (&app_buffer_type)) {
static const GTypeInfo app_buffer_info = {
sizeof (GstBufferClass),
NULL,
@ -52,10 +52,12 @@ gst_app_buffer_get_type (void)
(GInstanceInitFunc) gst_app_buffer_init,
NULL
};
_gst_app_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
"GstAppBuffer", &app_buffer_info, 0);
GType tmp = g_type_register_static (GST_TYPE_BUFFER, "GstAppBuffer",
&app_buffer_info, 0);
g_once_init_leave (&app_buffer_type, tmp);
}
return _gst_app_buffer_type;
return (GType) app_buffer_type;
}
static void

View file

@ -111,6 +111,8 @@ struct _GstAppSinkPrivate
GstAppSinkCallbacks callbacks;
gpointer user_data;
GDestroyNotify notify;
gboolean buffer_lists_supported;
};
GST_DEBUG_CATEGORY_STATIC (app_sink_debug);
@ -271,7 +273,8 @@ gst_app_sink_class_init (GstAppSinkClass * klass)
g_object_class_install_property (gobject_class, PROP_EMIT_SIGNALS,
g_param_spec_boolean ("emit-signals", "Emit signals",
"Emit new-preroll and new-buffer signals", DEFAULT_PROP_EMIT_SIGNALS,
"Emit new-preroll, new-buffer and new-buffer-list signals",
DEFAULT_PROP_EMIT_SIGNALS,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_MAX_BUFFERS,
@ -622,6 +625,21 @@ gst_app_sink_flush_unlocked (GstAppSink * appsink)
g_cond_signal (priv->cond);
}
#define NEW_BUFFER_LIST_SIGID \
gst_app_sink_signals[SIGNAL_NEW_BUFFER_LIST]
static gboolean
gst_app_sink_check_buffer_lists_support (GstAppSink * appsink)
{
gboolean ret;
ret = (appsink->priv->callbacks.new_buffer_list != NULL) ||
g_signal_has_handler_pending (appsink, NEW_BUFFER_LIST_SIGID, 0, FALSE);
GST_INFO_OBJECT (appsink, "application supports buffer lists: %d", ret);
return ret;
}
static gboolean
gst_app_sink_start (GstBaseSink * psink)
{
@ -630,7 +648,10 @@ gst_app_sink_start (GstBaseSink * psink)
g_mutex_lock (priv->mutex);
GST_DEBUG_OBJECT (appsink, "starting");
priv->flushing = FALSE;
priv->started = TRUE;
priv->buffer_lists_supported =
gst_app_sink_check_buffer_lists_support (appsink);
g_mutex_unlock (priv->mutex);
return TRUE;
@ -779,6 +800,8 @@ restart:
if (is_list) {
if (priv->callbacks.new_buffer_list)
priv->callbacks.new_buffer_list (appsink, priv->user_data);
else if (emit)
g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_NEW_BUFFER_LIST], 0);
} else {
if (priv->callbacks.new_buffer)
priv->callbacks.new_buffer (appsink, priv->user_data);
@ -808,9 +831,46 @@ gst_app_sink_render (GstBaseSink * psink, GstBuffer * buffer)
}
static GstFlowReturn
gst_app_sink_render_list (GstBaseSink * psink, GstBufferList * list)
gst_app_sink_render_list (GstBaseSink * sink, GstBufferList * list)
{
return gst_app_sink_render_common (psink, GST_MINI_OBJECT_CAST (list), TRUE);
GstBufferListIterator *it;
GstFlowReturn flow;
GstAppSink *appsink;
GstBuffer *group;
appsink = GST_APP_SINK_CAST (sink);
if (appsink->priv->buffer_lists_supported)
return gst_app_sink_render_common (sink, GST_MINI_OBJECT_CAST (list), TRUE);
/* The application doesn't support buffer lists, extract individual buffers
* then and push them one-by-one */
GST_INFO_OBJECT (sink, "chaining each group in list as a merged buffer");
it = gst_buffer_list_iterate (list);
if (gst_buffer_list_iterator_next_group (it)) {
do {
group = gst_buffer_list_iterator_merge_group (it);
if (group == NULL) {
group = gst_buffer_new ();
GST_DEBUG_OBJECT (sink, "chaining empty group");
} else {
GST_DEBUG_OBJECT (sink, "chaining group");
}
flow = gst_app_sink_render (sink, group);
gst_buffer_unref (group);
} while (flow == GST_FLOW_OK && gst_buffer_list_iterator_next_group (it));
} else {
GST_DEBUG_OBJECT (sink, "chaining empty group");
group = gst_buffer_new ();
flow = gst_app_sink_render (sink, group);
gst_buffer_unref (group);
}
gst_buffer_list_iterator_free (it);
return flow;
}
static GstCaps *
@ -1331,6 +1391,8 @@ gst_app_sink_set_callbacks (GstAppSink * appsink,
priv->callbacks = *callbacks;
priv->user_data = user_data;
priv->notify = notify;
priv->buffer_lists_supported =
gst_app_sink_check_buffer_lists_support (appsink);
GST_OBJECT_UNLOCK (appsink);
}

View file

@ -198,23 +198,24 @@ GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
#define GST_TYPE_APP_STREAM_TYPE (stream_type_get_type ())
static GType
stream_type_get_type (void)
GType
gst_app_stream_type_get_type (void)
{
static GType stream_type_type = 0;
static volatile gsize stream_type_type = 0;
static const GEnumValue stream_type[] = {
{GST_APP_STREAM_TYPE_STREAM, "Stream", "stream"},
{GST_APP_STREAM_TYPE_SEEKABLE, "Seekable", "seekable"},
{GST_APP_STREAM_TYPE_RANDOM_ACCESS, "Random Access", "random-access"},
{0, NULL, NULL},
{GST_APP_STREAM_TYPE_STREAM, "GST_APP_STREAM_TYPE_STREAM", "stream"},
{GST_APP_STREAM_TYPE_SEEKABLE, "GST_APP_STREAM_TYPE_SEEKABLE", "seekable"},
{GST_APP_STREAM_TYPE_RANDOM_ACCESS, "GST_APP_STREAM_TYPE_RANDOM_ACCESS",
"random-access"},
{0, NULL, NULL}
};
if (!stream_type_type) {
stream_type_type = g_enum_register_static ("GstAppStreamType", stream_type);
if (g_once_init_enter (&stream_type_type)) {
GType tmp = g_enum_register_static ("GstAppStreamType", stream_type);
g_once_init_leave (&stream_type_type, tmp);
}
return stream_type_type;
return (GType) stream_type_type;
}
static void gst_app_src_uri_handler_init (gpointer g_iface,

View file

@ -117,6 +117,10 @@ struct _GstAppSrcClass
GType gst_app_src_get_type(void);
/* GType getter for GstAppStreamType, since 0.10.32 */
#define GST_TYPE_APP_STREAM_TYPE (gst_app_stream_type_get_type ())
GType gst_app_stream_type_get_type (void);
void gst_app_src_set_caps (GstAppSrc *appsrc, const GstCaps *caps);
GstCaps* gst_app_src_get_caps (GstAppSrc *appsrc);

View file

@ -101,7 +101,8 @@ typelibsdir = $(libdir)/girepository-1.0/
typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib)
%.typelib: %.gir $(INTROSPECTION_COMPILER)
$(AM_V_GEN)$(INTROSPECTION_COMPILER) \
$(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \
$(INTROSPECTION_COMPILER) \
--includedir=$(srcdir) \
--includedir=$(builddir) \
--includedir=$(builddir)/../interfaces \

View file

@ -71,15 +71,6 @@ enum
LAST_SIGNAL
};
/* we tollerate half a second diff before we start resyncing. This
* should be enough to compensate for various rounding errors in the timestamp
* and sample offset position.
* This is an emergency resync fallback since buffers marked as DISCONT will
* always lock to the correct timestamp immediatly and buffers not marked as
* DISCONT are contiguous by definition.
*/
#define DIFF_TOLERANCE 2
/* FIXME: 0.11, store the buffer_time and latency_time in nanoseconds */
#define DEFAULT_BUFFER_TIME ((200 * GST_MSECOND) / GST_USECOND)
#define DEFAULT_LATENCY_TIME ((10 * GST_MSECOND) / GST_USECOND)
@ -89,7 +80,7 @@ enum
/* FIXME, enable pull mode when clock slaving and trick modes are figured out */
#define DEFAULT_CAN_ACTIVATE_PULL FALSE
/* when timestamps or clock slaving drift for more than 20ms we resync. This is
/* when timestamps or clock slaving drift for more than 40ms we resync. This is
* a reasonable default */
#define DEFAULT_DRIFT_TOLERANCE ((40 * GST_MSECOND) / GST_USECOND)
@ -267,6 +258,7 @@ gst_base_audio_sink_init (GstBaseAudioSink * baseaudiosink,
GstBaseAudioSinkClass * g_class)
{
GstPluginFeature *feature;
GstBaseSink *basesink;
baseaudiosink->priv = GST_BASE_AUDIO_SINK_GET_PRIVATE (baseaudiosink);
@ -274,13 +266,16 @@ gst_base_audio_sink_init (GstBaseAudioSink * baseaudiosink,
baseaudiosink->latency_time = DEFAULT_LATENCY_TIME;
baseaudiosink->provide_clock = DEFAULT_PROVIDE_CLOCK;
baseaudiosink->priv->slave_method = DEFAULT_SLAVE_METHOD;
baseaudiosink->priv->drift_tolerance = DEFAULT_DRIFT_TOLERANCE;
baseaudiosink->provided_clock = gst_audio_clock_new ("GstAudioSinkClock",
(GstAudioClockGetTimeFunc) gst_base_audio_sink_get_time, baseaudiosink);
GST_BASE_SINK (baseaudiosink)->can_activate_push = TRUE;
GST_BASE_SINK (baseaudiosink)->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL;
baseaudiosink->priv->drift_tolerance = DEFAULT_DRIFT_TOLERANCE;
basesink = GST_BASE_SINK_CAST (baseaudiosink);
basesink->can_activate_push = TRUE;
basesink->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL;
gst_base_sink_set_last_buffer_enabled (basesink, FALSE);
/* install some custom pad_query functions */
gst_pad_set_query_function (GST_BASE_SINK_PAD (baseaudiosink),
@ -417,13 +412,6 @@ gst_base_audio_sink_query (GstElement * element, GstQuery * query)
GST_DEBUG_OBJECT (basesink, "latency query");
if (!basesink->ringbuffer || !basesink->ringbuffer->spec.rate) {
GST_DEBUG_OBJECT (basesink,
"we are not yet negotiated, can't report latency yet");
res = FALSE;
goto done;
}
/* ask parent first, it will do an upstream query for us. */
if ((res =
gst_base_sink_query_latency (GST_BASE_SINK_CAST (basesink), &live,
@ -434,6 +422,15 @@ gst_base_audio_sink_query (GstElement * element, GstQuery * query)
if (live && us_live) {
GstRingBufferSpec *spec;
GST_OBJECT_LOCK (basesink);
if (!basesink->ringbuffer || !basesink->ringbuffer->spec.rate) {
GST_OBJECT_UNLOCK (basesink);
GST_DEBUG_OBJECT (basesink,
"we are not yet negotiated, can't report latency yet");
res = FALSE;
goto done;
}
spec = &basesink->ringbuffer->spec;
basesink->priv->us_latency = min_l;
@ -441,6 +438,7 @@ gst_base_audio_sink_query (GstElement * element, GstQuery * query)
min_latency =
gst_util_uint64_scale_int (spec->seglatency * spec->segsize,
GST_SECOND, spec->rate * spec->bytes_per_sample);
GST_OBJECT_UNLOCK (basesink);
/* we cannot go lower than the buffer size and the min peer latency */
min_latency = min_latency + min_l;

View file

@ -54,7 +54,8 @@ typelibsdir = $(libdir)/girepository-1.0/
typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib)
%.typelib: %.gir $(INTROSPECTION_COMPILER)
$(AM_V_GEN)$(INTROSPECTION_COMPILER) \
$(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \
$(INTROSPECTION_COMPILER) \
--includedir=$(srcdir) \
--includedir=$(builddir) \
--includedir=$(builddir)/../tag \

View file

@ -77,7 +77,8 @@ typelibsdir = $(libdir)/girepository-1.0/
typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib)
%.typelib: %.gir $(INTROSPECTION_COMPILER)
$(AM_V_GEN)$(INTROSPECTION_COMPILER) \
$(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \
$(INTROSPECTION_COMPILER) \
--includedir=$(srcdir) \
--includedir=$(builddir) \
--includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \

View file

@ -108,7 +108,8 @@ typelibsdir = $(libdir)/girepository-1.0/
typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib)
%.typelib: %.gir $(INTROSPECTION_COMPILER)
$(AM_V_GEN)$(INTROSPECTION_COMPILER) \
$(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \
$(INTROSPECTION_COMPILER) \
--includedir=$(srcdir) \
--includedir=$(builddir) \
--includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \

View file

@ -42,7 +42,8 @@ typelibsdir = $(libdir)/girepository-1.0/
typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib)
%.typelib: %.gir $(INTROSPECTION_COMPILER)
$(AM_V_GEN)$(INTROSPECTION_COMPILER) \
$(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \
$(INTROSPECTION_COMPILER) \
--includedir=$(srcdir) \
--includedir=$(builddir) \
--includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \

View file

@ -4,6 +4,8 @@ headers_pbutils = \
pbutils.h \
codec-utils.h \
descriptions.h \
encoding-profile.h \
encoding-target.h \
install-plugins.h \
missing-plugins.h \
gstdiscoverer.h
@ -22,6 +24,8 @@ libgstpbutils_@GST_MAJORMINOR@_la_SOURCES = \
pbutils.c \
codec-utils.c \
descriptions.c \
encoding-profile.c \
encoding-target.c \
install-plugins.c \
missing-plugins.c \
gstdiscoverer.c \
@ -81,11 +85,14 @@ GstPbutils-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstpbutils-@GST_MAJ
--add-include-path=$(srcdir)/../video \
--add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \
--library=libgstpbutils-@GST_MAJORMINOR@.la \
--library-path=`$(PKG_CONFIG) --variable=libdir gstreamer-@GST_MAJORMINOR@` \
--library=gstreamer-@GST_MAJORMINOR@ \
--include=Gst-@GST_MAJORMINOR@ \
--libtool="$(top_builddir)/libtool" \
--pkg gstreamer-@GST_MAJORMINOR@ \
--pkg gstreamer-video-@GST_MAJORMINOR@ \
--pkg-export gstreamer-pbutils-@GST_MAJORMINOR@ \
--add-init-section="gst_init(NULL,NULL);" \
--output $@ \
$(gir_headers) \
$(gir_sources)
@ -100,7 +107,8 @@ typelibsdir = $(libdir)/girepository-1.0/
typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib)
%.typelib: %.gir $(INTROSPECTION_COMPILER)
$(AM_V_GEN)$(INTROSPECTION_COMPILER) \
$(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \
$(INTROSPECTION_COMPILER) \
--includedir=$(srcdir) \
--includedir=$(srcdir)/../video \
--includedir=$(builddir) \

View file

@ -25,9 +25,8 @@
*
* <refsect2>
* <para>
* Provides numerous codec-specific ulility functions such as functions to
* provide the codec profile and level in human-readable string form from
* header data.
* Provides codec-specific ulility functions such as functions to provide the
* codec profile and level in human-readable string form from header data.
* </para>
* </refsect2>
*/
@ -87,7 +86,7 @@ gst_codec_utils_aac_get_sample_rate_from_index (guint sr_idx)
* gst_codec_utils_aac_get_profile:
* @audio_config: a pointer to the AudioSpecificConfig as specified in the
* Elementary Stream Descriptor (esds) in ISO/IEC 14496-1 (see
* below for a more details).
* gst_codec_utils_aac_get_level() for a more details).
* @len: Length of @audio_config in bytes
*
* Returns the profile of the given AAC stream as a string. The profile is
@ -98,7 +97,7 @@ gst_codec_utils_aac_get_sample_rate_from_index (guint sr_idx)
* HE-AAC support has not yet been implemented.
* </note>
*
* Returns: The profile as a const string and NULL if the profile could not be
* Returns: The profile as a const string and %NULL if the profile could not be
* determined.
*
* Since: 0.10.31
@ -134,8 +133,7 @@ gst_codec_utils_aac_get_profile (const guint8 * audio_config, guint len)
/**
* gst_codec_utils_aac_get_level:
* @audio_config: a pointer to the AudioSpecificConfig as specified in the
* Elementary Stream Descriptor (esds) in ISO/IEC 14496-1 (see
* below for a more detailed description).
* Elementary Stream Descriptor (esds) in ISO/IEC 14496-1.
* @len: Length of @audio_config in bytes
*
* Determines the level of a stream as defined in ISO/IEC 14496-3. For AAC LC
@ -145,17 +143,25 @@ gst_codec_utils_aac_get_profile (const guint8 * audio_config, guint len)
* The @audio_config parameter follows the following format, starting from the
* most significant bit of the first byte:
*
* Bit 0:4 contains the AudioObjectType
* Bit 5:8 contains the sample frequency index (if this is 0xf, then the next
* 24 bits define the actual sample frequency, and subsequent fields
* are appropriately shifted).
* Bit 9:12 contains the channel configuration
* <itemizedlist>
* <listitem><para>
* Bit 0:4 contains the AudioObjectType
* </para></listitem>
* <listitem><para>
* Bit 5:8 contains the sample frequency index (if this is 0xf, then the
* next 24 bits define the actual sample frequency, and subsequent
* fields are appropriately shifted).
* </para></listitem>
* <listitem><para>
* Bit 9:12 contains the channel configuration
* </para></listitem>
* </itemizedlist>
*
* <note>
* HE-AAC support has not yet been implemented.
* </note>
*
* Returns: The level as a const string and NULL if the level could not be
* Returns: The level as a const string and %NULL if the level could not be
* determined.
*
* Since: 0.10.31
@ -325,12 +331,12 @@ gst_codec_utils_aac_get_level (const guint8 * audio_config, guint len)
* @len: Length of @audio_config in bytes
*
* Sets the level and profile on @caps if it can be determined from
* @audio_config. See #gst_codec_utils_aac_get_level() and
* @audio_config. See gst_codec_utils_aac_get_level() and
* gst_codec_utils_aac_get_profile() for more details on the parameters.
* @caps must be audio/mpeg caps with an "mpegversion" field of either 2 or 4.
* If mpegversion is 4, the "base-profile" field is also set in @caps.
*
* Returns: TRUE if the level and profile could be set, FALSE otherwise.
* Returns: %TRUE if the level and profile could be set, %FALSE otherwise.
*
* Since: 0.10.31
*/
@ -386,16 +392,18 @@ gst_codec_utils_aac_caps_set_level_and_profile (GstCaps * caps,
* as a bitstream here, with bit 0 being the most significant bit of the first
* byte.
*
* Bit 0:7 - Profile indication
* Bit 8 - constraint_set0_flag
* Bit 9 - constraint_set1_flag
* Bit 10 - constraint_set2_flag
* Bit 11 - constraint_set3_flag
* Bit 12 - constraint_set3_flag
* Bit 13:15 - Reserved
* Bit 16:24 - Level indication
* <itemizedlist>
* <listitem><para>Bit 0:7 - Profile indication</para></listitem>
* <listitem><para>Bit 8 - constraint_set0_flag</para></listitem>
* <listitem><para>Bit 9 - constraint_set1_flag</para></listitem>
* <listitem><para>Bit 10 - constraint_set2_flag</para></listitem>
* <listitem><para>Bit 11 - constraint_set3_flag</para></listitem>
* <listitem><para>Bit 12 - constraint_set3_flag</para></listitem>
* <listitem><para>Bit 13:15 - Reserved</para></listitem>
* <listitem><para>Bit 16:24 - Level indication</para></listitem>
* </itemizedlist>
*
* Returns: The profile as a const string, or NULL if there is an error.
* Returns: The profile as a const string, or %NULL if there is an error.
*
* Since: 0.10.31
*/
@ -466,9 +474,9 @@ gst_codec_utils_h264_get_profile (const guint8 * sps, guint len)
*
* Converts the level indication (level_idc) in the stream's
* sequence parameter set into a string. The SPS is expected to have the
* same format as for @gst_codec_utils_aac_get_profile().
* same format as for gst_codec_utils_h264_get_profile().
*
* Returns: The level as a const string, or NULL if there is an error.
* Returns: The level as a const string, or %NULL if there is an error.
*
* Since: 0.10.31
*/
@ -525,10 +533,10 @@ gst_codec_utils_h264_get_level (const guint8 * sps, guint len)
* @len: Length of the data available in @sps.
*
* Sets the level and profile in @caps if it can be determined from @sps. See
* #gst_codec_utils_h264_get_level() and #gst_codec_utils_h264_get_profile()
* gst_codec_utils_h264_get_level() and gst_codec_utils_h264_get_profile()
* for more details on the parameters.
*
* Returns: TRUE if the level and profile could be set, FALSE otherwise.
* Returns: %TRUE if the level and profile could be set, %FALSE otherwise.
*
* Since: 0.10.31
*/
@ -724,11 +732,11 @@ gst_codec_utils_mpeg4video_get_level (const guint8 * vis_obj_seq, guint len)
* @len: Length of the data available in @sps.
*
* Sets the level and profile in @caps if it can be determined from
* @vis_obj_seq. See #gst_codec_utils_mpeg4video_get_level() and
* #gst_codec_utils_mpeg4video_get_profile() for more details on the
* @vis_obj_seq. See gst_codec_utils_mpeg4video_get_level() and
* gst_codec_utils_mpeg4video_get_profile() for more details on the
* parameters.
*
* Returns: TRUE if the level and profile could be set, FALSE otherwise.
* Returns: %TRUE if the level and profile could be set, %FALSE otherwise.
*
* Since: 0.10.31
*/

View file

@ -62,9 +62,11 @@ typedef struct
static const FormatInfo formats[] = {
/* container/tag formats with static descriptions */
{"application/gxf", "General Exchange Format (GXF)", FLAG_CONTAINER},
{"application/ogg", "Ogg", FLAG_CONTAINER},
{"application/mxf", "MXF", FLAG_CONTAINER},
{"application/mxf", "Material eXchange Format (MXF)", FLAG_CONTAINER},
{"application/vnd.rn-realmedia", "Realmedia", FLAG_CONTAINER},
{"application/x-annodex", "Ogg", FLAG_CONTAINER},
{"application/x-id3", N_("ID3 tag"), FLAG_CONTAINER},
{"application/x-ape", N_("APE tag"), FLAG_CONTAINER},
{"application/x-apetag", N_("APE tag"), FLAG_CONTAINER},
@ -78,7 +80,7 @@ static const FormatInfo formats[] = {
{"video/x-matroska", "Matroska", FLAG_CONTAINER},
{"video/webm", "WebM", FLAG_CONTAINER},
{"video/x-ms-asf", "Advanced Streaming Format (ASF)", FLAG_CONTAINER},
{"video/x-msvideo", "AVI", FLAG_CONTAINER},
{"video/x-msvideo", "Audio Video Interleave (AVI)", FLAG_CONTAINER},
{"video/x-quicktime", "Quicktime", FLAG_CONTAINER},
{"video/quicktime", "Quicktime", FLAG_CONTAINER},
{"video/mj2", "Motion JPEG 2000", FLAG_CONTAINER},
@ -160,6 +162,7 @@ static const FormatInfo formats[] = {
{"video/x-compressed-yuv", N_("CYUV Lossless"), 0},
{"video/x-dirac", "Dirac", 0},
{"video/x-dnxhd", "Digital Nonlinear Extensible High Definition (DNxHD)", 0},
/* FIXME 0.11: rename to subpicture/x-dvd or so */
{"video/x-dvd-subpicture", "DVD subpicture", 0},
{"video/x-ffv", N_("FFMpeg v1"), 0},
{"video/x-flash-screen", "Flash Screen Video", 0},
@ -209,17 +212,21 @@ static const FormatInfo formats[] = {
{"image/jpeg", "JPEG", 0},
{"image/jng", "JPEG Network Graphics (JNG)", 0},
{"image/png", "PNG", 0},
{"image/pbm", "PBM", 0},
{"image/ppm", "PPM", 0},
{"image/pbm", "Portable BitMap (PBM)", 0},
{"image/ppm", "Portable PixMap (PPM)", 0},
{"image/svg+xml", "Scalable Vector Graphics (SVG)", 0},
{"image/tiff", "TIFF", 0},
{"image/x-cmu-raster", "CMU Raster Format", 0},
{"image/x-degas", "DEGAS", 0},
{"image/x-icon", "ICO", 0},
{"image/x-j2c", "JPEG 2000", 0},
{"image/x-jpc", "JPEG 2000", 0},
{"image/jp2", "JPEG 2000", 0},
{"image/x-pcx", "PCX", 0},
{"image/x-xcf", "XFC", 0},
{"image/x-pixmap", "XPM", 0},
{"image/x-portable-anymap", "Portable AnyMap (PAM)", 0},
{"image/x-portable-graymap", "Portable GrayMap (PGM)", 0},
{"image/x-xpixmap", "XPM", 0},
{"image/x-quicktime", "QuickTime Image Format (QTIF)", 0},
{"image/x-sun-raster", "Sun Raster Format (RAS)", 0},
@ -231,6 +238,7 @@ static const FormatInfo formats[] = {
{"application/x-subtitle-tmplayer", N_("TMPlayer subtitle format"), 0},
{"application/x-kate", "Kate", 0},
{"subtitle/x-kate", N_("Kate subtitle format"), 0},
{"subpicture/x-dvb", "DVB subtitles", 0},
/* add variant field to typefinder? { "application/x-subtitle", N_("subtitle"), 0}, */
/* non-audio/video/container formats */

View file

@ -0,0 +1,966 @@
/* GStreamer encoding profiles library
* Copyright (C) 2009-2010 Edward Hervey <edward.hervey@collabora.co.uk>
* (C) 2009-2010 Nokia Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* 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.
*/
/**
* SECTION:encoding-profile
* @short_description: Encoding profile library
*
* <refsect2>
* <para>
* Functions to create and handle encoding profiles.
* </para>
* <para>
* Encoding profiles describe the media types and settings one wishes to use for
* an encoding process. The top-level profiles are commonly
* #GstEncodingContainerProfile(s) (which contains a user-readable name and
* description along with which container format to use). These, in turn,
* reference one or more #GstEncodingProfile(s) which indicate which encoding
* format should be used on each individual streams.
* </para>
* <para>
* #GstEncodingProfile(s) can be provided to the 'encodebin' element, which will take
* care of selecting and setting up the required elements to produce an output stream
* conforming to the specifications of the profile.
* </para>
* <para>
* Unlike other systems, the encoding profiles do not specify which #GstElement to use
* for the various encoding and muxing steps, but instead relies on specifying the format
* one wishes to use.
* </para>
* <para>
* Encoding profiles can be created at runtime by the application or loaded from (and saved
* to) file using the #GstEncodingTarget API.
* </para>
* </refsect2>
* <refsect2>
* <title>Example: Creating a profile</title>
* <para>
* |[
* #include <gst/pbutils/encoding-profile.h>
* ...
* GstEncodingProfile *
* create_ogg_theora_profile(void)
*{
* GstEncodingContainerProfile *prof;
* GstCaps *caps;
*
* caps = gst_caps_from_string("application/ogg");
* prof = gst_encoding_container_profile_new("Ogg audio/video",
* "Standard OGG/THEORA/VORBIS",
* caps, NULL);
* gst_caps_unref (caps);
*
* caps = gst_caps_from_string("video/x-theora");
* sprof = gst_encoding_container_profile_add_profile(
* (GstEncodingProfile*) gst_encoding_video_profile_new(caps, NULL, NULL, 0));
* gst_caps_unref (caps);
*
* caps = gst_caps_from_string("audio/x-vorbis");
* sprof = gst_encoding_container_profile_add_profile(
* (GstEncodingProfile*) gst_encoding_audio_profile_new(caps, NULL, NULL, 0));
* gst_caps_unref (caps);
*
* return (GstEncodingProfile*) prof;
*}
*
*
* ]|
* </para>
* </refsect2>
* <refsect2>
* <title>Example: Listing categories, targets and profiles</title>
* <para>
* |[
* #include <gst/pbutils/encoding-profile.h>
* ...
* GstEncodingProfile *prof;
* GList *categories, *tmpc;
* GList *targets, *tmpt;
* ...
* categories = gst_encoding_target_list_available_categories();
*
* ... Show available categories to user ...
*
* for (tmpc = categories; tmpc; tmpc = tmpc->next) {
* gchar *category = (gchar *) tmpc->data;
*
* ... and we can list all targets within that category ...
*
* targets = gst_encoding_target_list_all (category);
*
* ... and show a list to our users ...
*
* g_list_foreach (targets, (GFunc) gst_encoding_target_unref, NULL);
* g_list_free (targets);
* }
*
* g_list_foreach (categories, (GFunc) g_free, NULL);
* g_list_free (categories);
*
* ...
* ]|
* </para>
* </refsect2>
*
* Since: 0.10.32
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "encoding-profile.h"
#include "encoding-target.h"
/* GstEncodingProfile API */
struct _GstEncodingProfile
{
GstMiniObject parent;
/*< public > */
gchar *name;
gchar *description;
GstCaps *format;
gchar *preset;
guint presence;
GstCaps *restriction;
};
static void string_to_profile_transform (const GValue * src_value,
GValue * dest_value);
static gboolean gst_encoding_profile_deserialize_valfunc (GValue * value,
const gchar * s);
static void gst_encoding_profile_class_init (GstEncodingProfileClass * klass);
static gpointer gst_encoding_profile_parent_class = NULL;
static void
gst_encoding_profile_class_intern_init (gpointer klass)
{
gst_encoding_profile_parent_class = g_type_class_peek_parent (klass);
gst_encoding_profile_class_init ((GstEncodingProfileClass *) klass);
}
GType
gst_encoding_profile_get_type (void)
{
static volatile gsize g_define_type_id__volatile = 0;
if (g_once_init_enter (&g_define_type_id__volatile)) {
GType g_define_type_id =
g_type_register_static_simple (GST_TYPE_MINI_OBJECT,
g_intern_static_string ("GstEncodingProfile"),
sizeof (GstEncodingProfileClass),
(GClassInitFunc) gst_encoding_profile_class_intern_init,
sizeof (GstEncodingProfile),
NULL,
(GTypeFlags) 0);
static GstValueTable gstvtable = {
G_TYPE_NONE,
(GstValueCompareFunc) NULL,
(GstValueSerializeFunc) NULL,
(GstValueDeserializeFunc) gst_encoding_profile_deserialize_valfunc
};
gstvtable.type = g_define_type_id;
/* Register a STRING=>PROFILE GValueTransformFunc */
g_value_register_transform_func (G_TYPE_STRING, g_define_type_id,
string_to_profile_transform);
/* Register gst-specific GValue functions */
gst_value_register (&gstvtable);
g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
}
return g_define_type_id__volatile;
}
static void
gst_encoding_profile_finalize (GstEncodingProfile * prof)
{
if (prof->name)
g_free (prof->name);
if (prof->format)
gst_caps_unref (prof->format);
if (prof->preset)
g_free (prof->preset);
if (prof->description)
g_free (prof->description);
if (prof->restriction)
gst_caps_unref (prof->restriction);
}
static void
gst_encoding_profile_class_init (GstMiniObjectClass * klass)
{
klass->finalize =
(GstMiniObjectFinalizeFunction) gst_encoding_profile_finalize;
}
/**
* gst_encoding_profile_get_name:
* @profile: a #GstEncodingProfile
*
* Since: 0.10.32
*
* Returns: the name of the profile, can be %NULL.
*/
const gchar *
gst_encoding_profile_get_name (GstEncodingProfile * profile)
{
return profile->name;
}
/**
* gst_encoding_profile_get_description:
* @profile: a #GstEncodingProfile
*
* Since: 0.10.32
*
* Returns: the description of the profile, can be %NULL.
*/
const gchar *
gst_encoding_profile_get_description (GstEncodingProfile * profile)
{
return profile->description;
}
/**
* gst_encoding_profile_get_format:
* @profile: a #GstEncodingProfile
*
* Since: 0.10.32
*
* Returns: the #GstCaps corresponding to the media format used in the profile.
*/
const GstCaps *
gst_encoding_profile_get_format (GstEncodingProfile * profile)
{
return profile->format;
}
/**
* gst_encoding_profile_get_preset:
* @profile: a #GstEncodingProfile
*
* Since: 0.10.32
*
* Returns: the name of the #GstPreset to be used in the profile.
*/
const gchar *
gst_encoding_profile_get_preset (GstEncodingProfile * profile)
{
return profile->preset;
}
/**
* gst_encoding_profile_get_presence:
* @profile: a #GstEncodingProfile
*
* Since: 0.10.32
*
* Returns: The number of times the profile is used in its parent
* container profile. If 0, it is not a mandatory stream.
*/
guint
gst_encoding_profile_get_presence (GstEncodingProfile * profile)
{
return profile->presence;
}
/**
* gst_encoding_profile_get_restriction:
* @profile: a #GstEncodingProfile
*
* Since: 0.10.32
*
* Returns: The restriction #GstCaps to apply before the encoder
* that will be used in the profile. The fields present in restriction caps are
* properties of the raw stream (that is before encoding), such as height and
* width for video and depth and sampling rate for audio. Does not apply to
* #GstEncodingContainerProfile (since there is no corresponding raw stream).
* Can be %NULL.
*/
const GstCaps *
gst_encoding_profile_get_restriction (GstEncodingProfile * profile)
{
return profile->restriction;
}
/**
* gst_encoding_profile_set_name:
* @profile: a #GstEncodingProfile
* @name: the name to set on the profile
*
* Set @name as the given name for the @profile. A copy of @name will be made
* internally.
*
* Since: 0.10.32
*/
void
gst_encoding_profile_set_name (GstEncodingProfile * profile, const gchar * name)
{
if (profile->name)
g_free (profile->name);
profile->name = g_strdup (name);
}
/**
* gst_encoding_profile_set_description:
* @profile: a #GstEncodingProfile
* @description: the description to set on the profile
*
* Set @description as the given description for the @profile. A copy of @description will be made
* internally.
*
* Since: 0.10.32
*/
void
gst_encoding_profile_set_description (GstEncodingProfile * profile,
const gchar * description)
{
if (profile->description)
g_free (profile->description);
profile->description = g_strdup (description);
}
/**
* gst_encoding_profile_set_format:
* @profile: a #GstEncodingProfile
* @format: the media format to use in the profile.
*
* Sets the media format used in the profile.
*
* Since: 0.10.32
*/
void
gst_encoding_profile_set_format (GstEncodingProfile * profile, GstCaps * format)
{
if (profile->format)
gst_caps_unref (profile->format);
profile->format = gst_caps_ref (format);
}
/**
* gst_encoding_profile_set_preset:
* @profile: a #GstEncodingProfile
* @preset: the element preset to use
*
* Sets the preset to use for the profile.
*
* Since: 0.10.32
*/
void
gst_encoding_profile_set_preset (GstEncodingProfile * profile,
const gchar * preset)
{
if (profile->preset)
g_free (profile->preset);
profile->preset = g_strdup (preset);
}
/**
* gst_encoding_profile_set_presence:
* @profile: a #GstEncodingProfile
* @presence: the number of time the profile can be used
*
* Set the number of time the profile is used in its parent
* container profile. If 0, it is not a mandatory stream
*
* Since: 0.10.32
*/
void
gst_encoding_profile_set_presence (GstEncodingProfile * profile, guint presence)
{
profile->presence = presence;
}
/**
* gst_encoding_profile_set_restriction:
* @profile: a #GstEncodingProfile
* @restriction: the restriction to apply
*
* Set the restriction #GstCaps to apply before the encoder
* that will be used in the profile. See gst_encoding_profile_set_restriction()
* for more about restrictions. Does not apply to #GstEncodingContainerProfile.
*
* Since: 0.10.32
*/
void
gst_encoding_profile_set_restriction (GstEncodingProfile * profile,
GstCaps * restriction)
{
if (profile->restriction)
gst_caps_unref (profile->restriction);
profile->restriction = restriction;
}
/* Container profiles */
struct _GstEncodingContainerProfile
{
GstEncodingProfile parent;
GList *encodingprofiles;
};
G_DEFINE_TYPE (GstEncodingContainerProfile, gst_encoding_container_profile,
GST_TYPE_ENCODING_PROFILE);
static void
gst_encoding_container_profile_init (GstEncodingContainerProfile * prof)
{
/* Nothing to initialize */
}
static void
gst_encoding_container_profile_finalize (GstEncodingContainerProfile * prof)
{
g_list_foreach (prof->encodingprofiles, (GFunc) gst_mini_object_unref, NULL);
g_list_free (prof->encodingprofiles);
GST_MINI_OBJECT_CLASS (gst_encoding_container_profile_parent_class)->finalize
((GstMiniObject *) prof);
}
static void
gst_encoding_container_profile_class_init (GstMiniObjectClass * klass)
{
klass->finalize =
(GstMiniObjectFinalizeFunction) gst_encoding_container_profile_finalize;
}
const GList *
gst_encoding_container_profile_get_profiles (GstEncodingContainerProfile *
profile)
{
return profile->encodingprofiles;
}
/* Video profiles */
struct _GstEncodingVideoProfile
{
GstEncodingProfile parent;
guint pass;
gboolean variableframerate;
};
G_DEFINE_TYPE (GstEncodingVideoProfile, gst_encoding_video_profile,
GST_TYPE_ENCODING_PROFILE);
static void
gst_encoding_video_profile_init (GstEncodingVideoProfile * prof)
{
/* Nothing to initialize */
}
static void
gst_encoding_video_profile_class_init (GstMiniObjectClass * klass)
{
}
/**
* gst_encoding_video_profile_get_pass:
* @prof: a #GstEncodingVideoProfile
*
* Since: 0.10.32
*
* Returns: The pass number if this is part of a multi-pass profile. Starts at
* 1 for multi-pass. 0 if this is not a multi-pass profile
**/
guint
gst_encoding_video_profile_get_pass (GstEncodingVideoProfile * prof)
{
return prof->pass;
}
/**
* gst_encoding_video_profile_get_variableframerate:
* @prof: a #GstEncodingVideoProfile
*
* Since: 0.10.32
*
* Returns: Whether non-constant video framerate is allowed for encoding.
*/
gboolean
gst_encoding_video_profile_get_variableframerate (GstEncodingVideoProfile *
prof)
{
return prof->variableframerate;
}
/**
* gst_encoding_video_profile_set_pass:
* @prof: a #GstEncodingVideoProfile
* @pass: the pass number for this profile
*
* Sets the pass number of this video profile. The first pass profile should have
* this value set to 1. If this video profile isn't part of a multi-pass profile,
* you may set it to 0 (the default value).
*
* Since: 0.10.32
*/
void
gst_encoding_video_profile_set_pass (GstEncodingVideoProfile * prof, guint pass)
{
prof->pass = pass;
}
/**
* gst_encoding_video_profile_set_variableframerate:
* @prof: a #GstEncodingVideoProfile
* @variableframerate: a boolean
*
* If set to %TRUE, then the incoming streamm will be allowed to have non-constant
* framerate. If set to %FALSE (default value), then the incoming stream will
* be normalized by dropping/duplicating frames in order to produce a
* constance framerate.
*
* Since: 0.10.32
*/
void
gst_encoding_video_profile_set_variableframerate (GstEncodingVideoProfile *
prof, gboolean variableframerate)
{
prof->variableframerate = variableframerate;
}
/* Audio profiles */
struct _GstEncodingAudioProfile
{
GstEncodingProfile parent;
};
G_DEFINE_TYPE (GstEncodingAudioProfile, gst_encoding_audio_profile,
GST_TYPE_ENCODING_PROFILE);
static void
gst_encoding_audio_profile_init (GstEncodingAudioProfile * prof)
{
/* Nothing to initialize */
}
static void
gst_encoding_audio_profile_class_init (GstMiniObjectClass * klass)
{
}
static inline gboolean
_gst_caps_is_equal_safe (GstCaps * a, GstCaps * b)
{
if (a == b)
return TRUE;
if ((a == NULL) || (b == NULL))
return FALSE;
return gst_caps_is_equal (a, b);
}
static gint
_compare_container_encoding_profiles (GstEncodingContainerProfile * ca,
GstEncodingContainerProfile * cb)
{
GList *tmp;
if (g_list_length (ca->encodingprofiles) !=
g_list_length (cb->encodingprofiles))
return -1;
for (tmp = ca->encodingprofiles; tmp; tmp = tmp->next) {
GstEncodingProfile *prof = (GstEncodingProfile *) tmp->data;
if (!gst_encoding_container_profile_contains_profile (ca, prof))
return -1;
}
return 0;
}
static gint
_compare_encoding_profiles (const GstEncodingProfile * a,
const GstEncodingProfile * b)
{
if ((G_TYPE_FROM_INSTANCE (a) != G_TYPE_FROM_INSTANCE (b)) ||
!_gst_caps_is_equal_safe (a->format, b->format) ||
(g_strcmp0 (a->preset, b->preset) != 0) ||
(g_strcmp0 (a->name, b->name) != 0) ||
(g_strcmp0 (a->description, b->description) != 0))
return -1;
if (GST_IS_ENCODING_CONTAINER_PROFILE (a))
return
_compare_container_encoding_profiles (GST_ENCODING_CONTAINER_PROFILE
(a), GST_ENCODING_CONTAINER_PROFILE (b));
if (GST_IS_ENCODING_VIDEO_PROFILE (a)) {
GstEncodingVideoProfile *va = (GstEncodingVideoProfile *) a;
GstEncodingVideoProfile *vb = (GstEncodingVideoProfile *) b;
if ((va->pass != vb->pass)
|| (va->variableframerate != vb->variableframerate))
return -1;
}
return 0;
}
/**
* gst_encoding_container_profile_contains_profile:
* @container: a #GstEncodingContainerProfile
* @profile: a #GstEncodingProfile
*
* Checks if @container contains a #GstEncodingProfile identical to
* @profile.
*
* Since: 0.10.32
*
* Returns: %TRUE if @container contains a #GstEncodingProfile identical
* to @profile, else %FALSE.
*/
gboolean
gst_encoding_container_profile_contains_profile (GstEncodingContainerProfile *
container, GstEncodingProfile * profile)
{
g_return_val_if_fail (GST_IS_ENCODING_CONTAINER_PROFILE (container), FALSE);
g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE);
return (g_list_find_custom (container->encodingprofiles, profile,
(GCompareFunc) _compare_encoding_profiles) != NULL);
}
/**
* gst_encoding_container_profile_add_profile:
* @container: the #GstEncodingContainerProfile to use
* @profile: the #GstEncodingProfile to add.
*
* Add a #GstEncodingProfile to the list of profiles handled by @container.
*
* No copy of @profile will be made, if you wish to use it elsewhere after this
* method you should increment its reference count.
*
* Since: 0.10.32
*
* Returns: %TRUE if the @stream was properly added, else %FALSE.
*/
gboolean
gst_encoding_container_profile_add_profile (GstEncodingContainerProfile *
container, GstEncodingProfile * profile)
{
g_return_val_if_fail (GST_IS_ENCODING_CONTAINER_PROFILE (container), FALSE);
g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE);
if (g_list_find_custom (container->encodingprofiles, profile,
(GCompareFunc) _compare_encoding_profiles)) {
GST_ERROR
("Encoding profile already contains an identical GstEncodingProfile");
return FALSE;
}
container->encodingprofiles =
g_list_append (container->encodingprofiles, profile);
return TRUE;
}
static GstEncodingProfile *
common_creation (GType objtype, GstCaps * format, const gchar * preset,
const gchar * name, const gchar * description, GstCaps * restriction,
guint presence)
{
GstEncodingProfile *prof;
prof = (GstEncodingProfile *) gst_mini_object_new (objtype);
if (name)
prof->name = g_strdup (name);
if (description)
prof->description = g_strdup (description);
if (preset)
prof->preset = g_strdup (preset);
if (format)
prof->format = gst_caps_ref (format);
if (restriction)
prof->restriction = gst_caps_ref (restriction);
prof->presence = presence;
return prof;
}
/**
* gst_encoding_container_profile_new:
* @name: The name of the container profile, can be %NULL
* @description: The description of the container profile, can be %NULL
* @format: The format to use for this profile
* @preset: The preset to use for this profile
*
* Creates a new #GstEncodingContainerProfile.
*
* Since: 0.10.32
*
* Returns: The newly created #GstEncodingContainerProfile.
*/
GstEncodingContainerProfile *
gst_encoding_container_profile_new (const gchar * name,
const gchar * description, GstCaps * format, const gchar * preset)
{
g_return_val_if_fail (GST_IS_CAPS (format), NULL);
return (GstEncodingContainerProfile *)
common_creation (GST_TYPE_ENCODING_CONTAINER_PROFILE, format, preset,
name, description, NULL, 0);
}
/**
* gst_encoding_video_profile_new:
* @format: the #GstCaps
* @preset: the preset(s) to use on the encoder, can be #NULL
* @restriction: the #GstCaps used to restrict the input to the encoder, can be
* NULL. See gst_encoding_profile_get_restriction() for more details.
* @presence: the number of time this stream must be used. 0 means any number of
* times (including never)
*
* Creates a new #GstEncodingVideoProfile
*
* All provided allocatable arguments will be internally copied, so can be
* safely freed/unreferenced after calling this method.
*
* If you wish to control the pass number (in case of multi-pass scenarios),
* please refer to the gst_encoding_video_profile_set_pass() documentation.
*
* If you wish to use/force a constant framerate please refer to the
* gst_encoding_video_profile_set_variableframerate() documentation.
*
* Since: 0.10.32
*
* Returns: the newly created #GstEncodingVideoProfile.
*/
GstEncodingVideoProfile *
gst_encoding_video_profile_new (GstCaps * format, const gchar * preset,
GstCaps * restriction, guint presence)
{
return (GstEncodingVideoProfile *)
common_creation (GST_TYPE_ENCODING_VIDEO_PROFILE, format, preset, NULL,
NULL, restriction, presence);
}
/**
* gst_encoding_audio_profile_new:
* @format: the #GstCaps
* @preset: the preset(s) to use on the encoder, can be #NULL
* @restriction: the #GstCaps used to restrict the input to the encoder, can be
* NULL. See gst_encoding_profile_get_restriction() for more details.
* @presence: the number of time this stream must be used. 0 means any number of
* times (including never)
*
* Creates a new #GstEncodingAudioProfile
*
* All provided allocatable arguments will be internally copied, so can be
* safely freed/unreferenced after calling this method.
*
* Since: 0.10.32
*
* Returns: the newly created #GstEncodingAudioProfile.
*/
GstEncodingAudioProfile *
gst_encoding_audio_profile_new (GstCaps * format, const gchar * preset,
GstCaps * restriction, guint presence)
{
return (GstEncodingAudioProfile *)
common_creation (GST_TYPE_ENCODING_AUDIO_PROFILE, format, preset, NULL,
NULL, restriction, presence);
}
/**
* gst_encoding_profile_is_equal:
* @a: a #GstEncodingProfile
* @b: a #GstEncodingProfile
*
* Checks whether the two #GstEncodingProfile are equal
*
* Since: 0.10.32
*
* Returns: %TRUE if @a and @b are equal, else %FALSE.
*/
gboolean
gst_encoding_profile_is_equal (GstEncodingProfile * a, GstEncodingProfile * b)
{
return (_compare_encoding_profiles (a, b) == 0);
}
/**
* gst_encoding_profile_get_input_caps:
* @profile: a #GstEncodingProfile
*
* Computes the full output caps that this @profile will be able to consume.
*
* Since: 0.10.32
*
* Returns: The full caps the given @profile can consume. Call gst_caps_unref()
* when you are done with the caps.
*/
GstCaps *
gst_encoding_profile_get_input_caps (GstEncodingProfile * profile)
{
GstCaps *out, *tmp;
GList *ltmp;
GstStructure *st, *outst;
GQuark out_name;
guint i, len;
const GstCaps *fcaps;
if (GST_IS_ENCODING_CONTAINER_PROFILE (profile)) {
GstCaps *res = gst_caps_new_empty ();
for (ltmp = GST_ENCODING_CONTAINER_PROFILE (profile)->encodingprofiles;
ltmp; ltmp = ltmp->next) {
GstEncodingProfile *sprof = (GstEncodingProfile *) ltmp->data;
gst_caps_merge (res, gst_encoding_profile_get_input_caps (sprof));
}
return res;
}
fcaps = profile->format;
/* fast-path */
if ((profile->restriction == NULL) || gst_caps_is_any (profile->restriction))
return gst_caps_copy (fcaps);
/* Combine the format with the restriction caps */
outst = gst_caps_get_structure (fcaps, 0);
out_name = gst_structure_get_name_id (outst);
tmp = gst_caps_new_empty ();
len = gst_caps_get_size (profile->restriction);
for (i = 0; i < len; i++) {
st = gst_structure_copy (gst_caps_get_structure (profile->restriction, i));
st->name = out_name;
gst_caps_append_structure (tmp, st);
}
out = gst_caps_intersect (tmp, fcaps);
gst_caps_unref (tmp);
return out;
}
/**
* gst_encoding_profile_get_type_nick:
* @profile: a #GstEncodingProfile
*
* Since: 0.10.32
*
* Returns: the human-readable name of the type of @profile.
*/
const gchar *
gst_encoding_profile_get_type_nick (GstEncodingProfile * profile)
{
if (GST_IS_ENCODING_CONTAINER_PROFILE (profile))
return "container";
if (GST_IS_ENCODING_VIDEO_PROFILE (profile))
return "video";
if (GST_IS_ENCODING_AUDIO_PROFILE (profile))
return "audio";
return NULL;
}
/**
* gst_encoding_profile_find:
* @targetname: (transfer none): The name of the target
* @profilename: (transfer none): The name of the profile
* @category: (transfer none) (allow-none): The target category. Can be %NULL
*
* Find the #GstEncodingProfile with the specified name and category.
*
* Returns: (transfer full): The matching #GstEncodingProfile or %NULL.
*
* Since: 0.10.32
*/
GstEncodingProfile *
gst_encoding_profile_find (const gchar * targetname, const gchar * profilename,
const gchar * category)
{
GstEncodingProfile *res = NULL;
GstEncodingTarget *target;
g_return_val_if_fail (targetname != NULL, NULL);
g_return_val_if_fail (profilename != NULL, NULL);
/* FIXME : how do we handle profiles named the same in several
* categories but of which only one has the required profile ? */
target = gst_encoding_target_load (targetname, category, NULL);
if (target) {
res = gst_encoding_target_get_profile (target, profilename);
gst_encoding_target_unref (target);
}
return res;
}
static GstEncodingProfile *
combo_search (const gchar * pname)
{
GstEncodingProfile *res;
gchar **split;
/* Splitup */
split = g_strsplit (pname, "/", 2);
if (g_strv_length (split) != 2)
return NULL;
res = gst_encoding_profile_find (split[0], split[1], NULL);
g_strfreev (split);
return res;
}
/* GValue transform function */
static void
string_to_profile_transform (const GValue * src_value, GValue * dest_value)
{
const gchar *profilename;
GstEncodingProfile *profile;
profilename = g_value_get_string (src_value);
profile = combo_search (profilename);
if (profile)
gst_value_take_mini_object (dest_value, (GstMiniObject *) profile);
}
static gboolean
gst_encoding_profile_deserialize_valfunc (GValue * value, const gchar * s)
{
GstEncodingProfile *profile;
profile = combo_search (s);
if (profile) {
gst_value_take_mini_object (value, (GstMiniObject *) profile);
return TRUE;
}
return FALSE;
}

View file

@ -0,0 +1,187 @@
/* GStreamer encoding profiles library
* Copyright (C) 2009-2010 Edward Hervey <edward.hervey@collabora.co.uk>
* (C) 2009-2010 Nokia Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* 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.
*/
#ifndef __GST_PROFILE_H__
#define __GST_PROFILE_H__
#include <gst/gst.h>
G_BEGIN_DECLS
#include <gst/pbutils/pbutils-enumtypes.h>
/**
* GstEncodingProfile:
*
* The opaque base class object for all encoding profiles. This contains generic
* information like name, description, format and preset.
*
* Since: 0.10.32
*/
#define GST_TYPE_ENCODING_PROFILE \
(gst_encoding_profile_get_type ())
#define GST_ENCODING_PROFILE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ENCODING_PROFILE, GstEncodingProfile))
#define GST_IS_ENCODING_PROFILE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ENCODING_PROFILE))
typedef struct _GstEncodingProfile GstEncodingProfile;
typedef GstMiniObjectClass GstEncodingProfileClass;
GType gst_encoding_profile_get_type (void);
/**
* GstEncodingContainerProfile:
*
* Encoding profiles for containers. Keeps track of a list of #GstEncodingProfile
*
* Since: 0.10.32
*/
#define GST_TYPE_ENCODING_CONTAINER_PROFILE \
(gst_encoding_container_profile_get_type ())
#define GST_ENCODING_CONTAINER_PROFILE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ENCODING_CONTAINER_PROFILE, GstEncodingContainerProfile))
#define GST_IS_ENCODING_CONTAINER_PROFILE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ENCODING_CONTAINER_PROFILE))
typedef struct _GstEncodingContainerProfile GstEncodingContainerProfile;
typedef GstEncodingProfileClass GstEncodingContainerProfileClass;
GType gst_encoding_container_profile_get_type (void);
/**
* GstEncodingVideoProfile:
*
* Variant of #GstEncodingProfile for video streams, allows specifying the @pass.
*
* Since: 0.10.32
*/
#define GST_TYPE_ENCODING_VIDEO_PROFILE \
(gst_encoding_video_profile_get_type ())
#define GST_ENCODING_VIDEO_PROFILE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ENCODING_VIDEO_PROFILE, GstEncodingVideoProfile))
#define GST_IS_ENCODING_VIDEO_PROFILE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ENCODING_VIDEO_PROFILE))
typedef struct _GstEncodingVideoProfile GstEncodingVideoProfile;
typedef GstEncodingProfileClass GstEncodingVideoProfileClass;
GType gst_encoding_video_profile_get_type (void);
/**
* GstEncodingAudioProfile:
*
* Variant of #GstEncodingProfile for audio streams.
*
* Since: 0.10.32
*/
#define GST_TYPE_ENCODING_AUDIO_PROFILE \
(gst_encoding_audio_profile_get_type ())
#define GST_ENCODING_AUDIO_PROFILE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ENCODING_AUDIO_PROFILE, GstEncodingAudioProfile))
#define GST_IS_ENCODING_AUDIO_PROFILE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ENCODING_AUDIO_PROFILE))
typedef struct _GstEncodingAudioProfile GstEncodingAudioProfile;
typedef GstEncodingProfileClass GstEncodingAudioProfileClass;
GType gst_encoding_audio_profile_get_type (void);
/* GstEncodingProfile API */
/**
* gst_encoding_profile_unref:
* @profile: a #GstEncodingProfile
*
* Decreases the reference count of the @profile, possibly freeing the @profile.
*
* Since: 0.10.32
*/
#define gst_encoding_profile_unref(profile) (gst_mini_object_unref ((GstMiniObject*) profile))
/**
* gst_encoding_profile_ref:
* @profile: a #GstEncodingProfile
*
* Increases the reference count of the @profile.
*
* Since: 0.10.32
*/
#define gst_encoding_profile_ref(profile) (gst_mini_object_ref ((GstMiniObject*) profile))
const gchar * gst_encoding_profile_get_name(GstEncodingProfile *profile);
const gchar * gst_encoding_profile_get_description(GstEncodingProfile *profile);
const GstCaps * gst_encoding_profile_get_format(GstEncodingProfile *profile);
const gchar * gst_encoding_profile_get_preset(GstEncodingProfile *profile);
guint gst_encoding_profile_get_presence(GstEncodingProfile *profile);
const GstCaps * gst_encoding_profile_get_restriction(GstEncodingProfile *profile);
void gst_encoding_profile_set_name(GstEncodingProfile *profile, const gchar *name);
void gst_encoding_profile_set_description(GstEncodingProfile *profile, const gchar *description);
void gst_encoding_profile_set_format(GstEncodingProfile *profile, GstCaps *format);
void gst_encoding_profile_set_preset(GstEncodingProfile *profile, const gchar *preset);
void gst_encoding_profile_set_restriction(GstEncodingProfile *profile, GstCaps *restriction);
void gst_encoding_profile_set_presence(GstEncodingProfile *profile, guint presence);
gboolean gst_encoding_profile_is_equal (GstEncodingProfile *a,
GstEncodingProfile *b);
GstCaps * gst_encoding_profile_get_input_caps (GstEncodingProfile *profile);
const gchar *gst_encoding_profile_get_type_nick (GstEncodingProfile *profile);
GstEncodingProfile * gst_encoding_profile_find (const gchar *targetname,
const gchar *profilename,
const gchar *category);
/* GstEncodingContainerProfile API */
gboolean gst_encoding_container_profile_add_profile (GstEncodingContainerProfile *container,
GstEncodingProfile *profile);
gboolean gst_encoding_container_profile_contains_profile (GstEncodingContainerProfile * container,
GstEncodingProfile *profile);
const GList *gst_encoding_container_profile_get_profiles (GstEncodingContainerProfile *profile);
GstEncodingContainerProfile * gst_encoding_container_profile_new (const gchar *name,
const gchar *description,
GstCaps *format,
const gchar *preset);
/* Invidual stream encodingprofile API */
GstEncodingVideoProfile * gst_encoding_video_profile_new (GstCaps *format,
const gchar *preset,
GstCaps *restriction,
guint presence);
GstEncodingAudioProfile * gst_encoding_audio_profile_new (GstCaps *format,
const gchar *preset,
GstCaps *restriction,
guint presence);
guint gst_encoding_video_profile_get_pass (GstEncodingVideoProfile *prof);
gboolean gst_encoding_video_profile_get_variableframerate (GstEncodingVideoProfile *prof);
void gst_encoding_video_profile_set_pass (GstEncodingVideoProfile *prof,
guint pass);
void gst_encoding_video_profile_set_variableframerate (GstEncodingVideoProfile *prof,
gboolean variableframerate);
G_END_DECLS
#endif /* __GST_PROFILE_H__ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,147 @@
/* GStreamer encoding profile registry
* Copyright (C) 2010 Edward Hervey <edward.hervey@collabora.co.uk>
* (C) 2010 Nokia Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* 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.
*/
#ifndef __GST_PROFILE_REGISTRY_H__
#define __GST_PROFILE_REGISTRY_H__
#include <gst/pbutils/encoding-profile.h>
G_BEGIN_DECLS
/* FIXME/UNKNOWNS
*
* Should encoding categories be well-known strings/quarks ?
*
*/
/**
* GST_ENCODING_CATEGORY_DEVICE:
*
* #GstEncodingTarget category for device-specific targets.
* The name of the target will usually be the contructor and model of the device,
* and that target will contain #GstEncodingProfiles suitable for that device.
*/
#define GST_ENCODING_CATEGORY_DEVICE "device"
/**
* GST_ENCODING_CATEGORY_ONLINE_SERVICE:
*
* #GstEncodingTarget category for online-services.
* The name of the target will usually be the name of the online service
* and that target will contain #GstEncodingProfiles suitable for that online
* service.
*/
#define GST_ENCODING_CATEGORY_ONLINE_SERVICE "online-service"
/**
* GST_ENCODING_CATEGORY_STORAGE_EDITING:
*
* #GstEncodingTarget category for storage, archiving and editing targets.
* Those targets can be lossless and/or provide very fast random access content.
* The name of the target will usually be the container type or editing target,
* and that target will contain #GstEncodingProfiles suitable for editing or
* storage.
*/
#define GST_ENCODING_CATEGORY_STORAGE_EDITING "storage-editing"
/**
* GST_ENCODING_CATEGORY_CAPTURE:
*
* #GstEncodingTarget category for recording and capture.
* Targets within this category are optimized for low latency encoding.
*/
#define GST_ENCODING_CATEGORY_CAPTURE "capture"
/**
* GstEncodingTarget:
*
* Collection of #GstEncodingProfile for a specific target or use-case.
*
* When being stored/loaded, targets come from a specific category, like
* #GST_ENCODING_CATEGORY_DEVICE.
*
* Since: 0.10.32
*/
#define GST_TYPE_ENCODING_TARGET \
(gst_encoding_target_get_type ())
#define GST_ENCODING_TARGET(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ENCODING_TARGET, GstEncodingTarget))
#define GST_IS_ENCODING_TARGET(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ENCODING_TARGET))
typedef struct _GstEncodingTarget GstEncodingTarget;
typedef GstMiniObjectClass GstEncodingTargetClass;
GType gst_encoding_target_get_type (void);
/**
* gst_encoding_target_unref:
* @target: a #GstEncodingTarget
*
* Decreases the reference count of the @target, possibly freeing it.
*
* Since: 0.10.32
*/
#define gst_encoding_target_unref(target) \
(gst_mini_object_unref ((GstMiniObject*) target))
/**
* gst_encoding_target_ref:
* @target: a #GstEncodingTarget
*
* Increases the reference count of the @target.
*
* Since: 0.10.32
*/
#define gst_encoding_target_ref(target) \
(gst_mini_object_ref ((GstMiniObject*) target))
GstEncodingTarget *
gst_encoding_target_new (const gchar *name, const gchar *category,
const gchar *description, const GList *profiles);
const gchar *gst_encoding_target_get_name (GstEncodingTarget *target);
const gchar *gst_encoding_target_get_category (GstEncodingTarget *target);
const gchar *gst_encoding_target_get_description (GstEncodingTarget *target);
const GList *gst_encoding_target_get_profiles (GstEncodingTarget *target);
GstEncodingProfile *gst_encoding_target_get_profile (GstEncodingTarget *target,
const gchar *name);
gboolean
gst_encoding_target_add_profile (GstEncodingTarget *target, GstEncodingProfile *profile);
gboolean gst_encoding_target_save (GstEncodingTarget *target,
GError **error);
gboolean gst_encoding_target_save_to_file (GstEncodingTarget *target,
const gchar *filepath,
GError **error);
GstEncodingTarget *gst_encoding_target_load (const gchar *name,
const gchar *category,
GError **error);
GstEncodingTarget *gst_encoding_target_load_from_file (const gchar *filepath,
GError **error);
GList *gst_encoding_list_available_categories (void);
GList *gst_encoding_list_all_targets (const gchar * categoryname);
G_END_DECLS
#endif /* __GST_PROFILE_REGISTRY_H__ */

View file

@ -377,15 +377,16 @@ gst_discoverer_stream_info_list_free (GList * infos)
/**
* gst_discoverer_info_get_streams:
* @info: a #GstDiscovererInfo
* @streamtype: a #GType of #GstDiscovererStreamInfo
* @streamtype: a #GType derived from #GstDiscovererStreamInfo
*
* Finds the #GstDiscovererStreamInfo contained in @info that match the
* given @streamtype.
*
* Returns: A #GList of matching #GstDiscovererStreamInfo. The caller should
* free it with #gst_discoverer_stream_info_list_free.
* Returns: (transfer full) (element-type Gst.DiscovererStreamInfo): A #GList of
* matching #GstDiscovererStreamInfo. The caller should free it with
* gst_discoverer_stream_info_list_free().
*
* Since 0.10.31
* Since: 0.10.31
*/
GList *
gst_discoverer_info_get_streams (GstDiscovererInfo * info, GType streamtype)
@ -408,10 +409,11 @@ gst_discoverer_info_get_streams (GstDiscovererInfo * info, GType streamtype)
*
* Finds all the #GstDiscovererAudioInfo contained in @info
*
* Returns: A #GList of matching #GstDiscovererStreamInfo. The caller should
* free it with #gst_discoverer_stream_info_list_free.
* Returns: (transfer full) (element-type Gst.DiscovererStreamInfo): A #GList of
* matching #GstDiscovererStreamInfo. The caller should free it with
* gst_discoverer_stream_info_list_free().
*
* Since 0.10.31
* Since: 0.10.31
*/
GList *
gst_discoverer_info_get_audio_streams (GstDiscovererInfo * info)
@ -425,10 +427,11 @@ gst_discoverer_info_get_audio_streams (GstDiscovererInfo * info)
*
* Finds all the #GstDiscovererVideoInfo contained in @info
*
* Returns: A #GList of matching #GstDiscovererStreamInfo. The caller should
* free it with #gst_discoverer_stream_info_list_free.
* Returns: (transfer full) (element-type Gst.DiscovererStreamInfo): A #GList of
* matching #GstDiscovererStreamInfo. The caller should free it with
* gst_discoverer_stream_info_list_free().
*
* Since 0.10.31
* Since: 0.10.31
*/
GList *
gst_discoverer_info_get_video_streams (GstDiscovererInfo * info)
@ -442,10 +445,11 @@ gst_discoverer_info_get_video_streams (GstDiscovererInfo * info)
*
* Finds all the #GstDiscovererContainerInfo contained in @info
*
* Returns: A #GList of matching #GstDiscovererStreamInfo. The caller should
* free it with #gst_discoverer_stream_info_list_free.
* Returns: (transfer full) (element-type Gst.DiscovererStreamInfo): A #GList of
* matching #GstDiscovererStreamInfo. The caller should free it with
* gst_discoverer_stream_info_list_free().
*
* Since 0.10.31
* Since: 0.10.31
*/
GList *
gst_discoverer_info_get_container_streams (GstDiscovererInfo * info)
@ -461,7 +465,7 @@ gst_discoverer_info_get_container_streams (GstDiscovererInfo * info)
* Returns: a human readable name for the stream type of the given @info (ex : "audio",
* "container",...).
*
* Since 0.10.31
* Since: 0.10.31
*/
const gchar *
gst_discoverer_stream_info_get_stream_type_nick (GstDiscovererStreamInfo * info)
@ -493,10 +497,11 @@ gst_discoverer_stream_info_get_stream_type_nick (GstDiscovererStreamInfo * info)
* gst_discoverer_stream_info_get_previous:
* @info: a #GstDiscovererStreamInfo
*
* Returns: the previous #GstDiscovererStreamInfo in a chain. %NULL for starting
* points. Unref with #gst_discoverer_stream_info_unref after usage.
* Returns: (transfer full): the previous #GstDiscovererStreamInfo in a chain.
* %NULL for starting points. Unref with #gst_discoverer_stream_info_unref
* after usage.
*
* Since 0.10.31
* Since: 0.10.31
*/
GstDiscovererStreamInfo *
gst_discoverer_stream_info_get_previous (GstDiscovererStreamInfo * info)
@ -512,10 +517,11 @@ gst_discoverer_stream_info_get_previous (GstDiscovererStreamInfo * info)
* gst_discoverer_stream_info_get_next:
* @info: a #GstDiscovererStreamInfo
*
* Returns: the next #GstDiscovererStreamInfo in a chain. %NULL for final streams.
* Returns: (transfer full): the next #GstDiscovererStreamInfo in a chain. %NULL
* for final streams.
* Unref with #gst_discoverer_stream_info_unref after usage.
*
* Since 0.10.31
* Since: 0.10.31
*/
GstDiscovererStreamInfo *
gst_discoverer_stream_info_get_next (GstDiscovererStreamInfo * info)
@ -532,9 +538,10 @@ gst_discoverer_stream_info_get_next (GstDiscovererStreamInfo * info)
* gst_discoverer_stream_info_get_caps:
* @info: a #GstDiscovererStreamInfo
*
* Returns: the #GstCaps of the stream. Unref with #gst_caps_unref after usage.
* Returns: (transfer full): the #GstCaps of the stream. Unref with
* #gst_caps_unref after usage.
*
* Since 0.10.31
* Since: 0.10.31
*/
GstCaps *
gst_discoverer_stream_info_get_caps (GstDiscovererStreamInfo * info)
@ -550,10 +557,10 @@ gst_discoverer_stream_info_get_caps (GstDiscovererStreamInfo * info)
* gst_discoverer_stream_info_get_tags:
* @info: a #GstDiscovererStreamInfo
*
* Returns: the tags contained in this stream. If you wish to use the tags after
* the life-time of @info you will need to copy them.
* Returns: (transfer none): the tags contained in this stream. If you wish to
* use the tags after the life-time of @info you will need to copy them.
*
* Since 0.10.31
* Since: 0.10.31
*/
const GstTagList *
@ -568,11 +575,11 @@ gst_discoverer_stream_info_get_tags (GstDiscovererStreamInfo * info)
* gst_discoverer_stream_info_get_misc:
* @info: a #GstDiscovererStreamInfo
*
* Returns: additional information regarding the stream (for example codec version,
* profile, etc..). If you wish to use the #GstStructure after the life-time of
* @info you will need to copy it.
* Returns: (transfer none): additional information regarding the stream (for
* example codec version, profile, etc..). If you wish to use the #GstStructure
* after the life-time of @info you will need to copy it.
*
* Since 0.10.31
* Since: 0.10.31
*/
const GstStructure *
gst_discoverer_stream_info_get_misc (GstDiscovererStreamInfo * info)
@ -588,10 +595,11 @@ gst_discoverer_stream_info_get_misc (GstDiscovererStreamInfo * info)
* gst_discoverer_container_info_get_streams:
* @info: a #GstDiscovererStreamInfo
*
* Returns: the list of #GstDiscovererStreamInfo this container stream offers.
* Free with #gst_discoverer_stream_info_list_free after usage.
* Returns: (transfer full) (element-type Gst.DiscovererStreamInfo): the list of
* #GstDiscovererStreamInfo this container stream offers.
* Free with gst_discoverer_stream_info_list_free() after usage.
*
* Since 0.10.31
* Since: 0.10.31
*/
GList *
@ -622,7 +630,7 @@ gst_discoverer_container_info_get_streams (GstDiscovererContainerInfo * info)
*
* Returns: the number of channels in the stream.
*
* Since 0.10.31
* Since: 0.10.31
*/
AUDIO_INFO_ACCESSOR_CODE (channels, guint, 0);
@ -633,7 +641,7 @@ AUDIO_INFO_ACCESSOR_CODE (channels, guint, 0);
*
* Returns: the sample rate of the stream in Hertz.
*
* Since 0.10.31
* Since: 0.10.31
*/
AUDIO_INFO_ACCESSOR_CODE (sample_rate, guint, 0);
@ -644,7 +652,7 @@ AUDIO_INFO_ACCESSOR_CODE (sample_rate, guint, 0);
*
* Returns: the number of bits used per sample in each channel.
*
* Since 0.10.31
* Since: 0.10.31
*/
AUDIO_INFO_ACCESSOR_CODE (depth, guint, 0);
@ -655,7 +663,7 @@ AUDIO_INFO_ACCESSOR_CODE (depth, guint, 0);
*
* Returns: the average or nominal bitrate of the stream in bits/second.
*
* Since 0.10.31
* Since: 0.10.31
*/
AUDIO_INFO_ACCESSOR_CODE (bitrate, guint, 0);
@ -666,7 +674,7 @@ AUDIO_INFO_ACCESSOR_CODE (bitrate, guint, 0);
*
* Returns: the maximum bitrate of the stream in bits/second.
*
* Since 0.10.31
* Since: 0.10.31
*/
AUDIO_INFO_ACCESSOR_CODE (max_bitrate, guint, 0);
@ -684,7 +692,7 @@ AUDIO_INFO_ACCESSOR_CODE (max_bitrate, guint, 0);
*
* Returns: the width of the video stream in pixels.
*
* Since 0.10.31
* Since: 0.10.31
*/
VIDEO_INFO_ACCESSOR_CODE (width, guint, 0);
@ -695,7 +703,7 @@ VIDEO_INFO_ACCESSOR_CODE (width, guint, 0);
*
* Returns: the height of the video stream in pixels.
*
* Since 0.10.31
* Since: 0.10.31
*/
VIDEO_INFO_ACCESSOR_CODE (height, guint, 0);
@ -704,10 +712,9 @@ VIDEO_INFO_ACCESSOR_CODE (height, guint, 0);
* gst_discoverer_video_info_get_depth:
* @info: a #GstDiscovererVideoInfo
*
* Returns: the depth in bits of the video stream (only relevant for
* video streams).
* Returns: the depth in bits of the video stream.
*
* Since 0.10.31
* Since: 0.10.31
*/
VIDEO_INFO_ACCESSOR_CODE (depth, guint, 0);
@ -718,7 +725,7 @@ VIDEO_INFO_ACCESSOR_CODE (depth, guint, 0);
*
* Returns: the framerate of the video stream (numerator).
*
* Since 0.10.31
* Since: 0.10.31
*/
VIDEO_INFO_ACCESSOR_CODE (framerate_num, guint, 0);
@ -729,7 +736,7 @@ VIDEO_INFO_ACCESSOR_CODE (framerate_num, guint, 0);
*
* Returns: the framerate of the video stream (denominator).
*
* Since 0.10.31
* Since: 0.10.31
*/
VIDEO_INFO_ACCESSOR_CODE (framerate_denom, guint, 0);
@ -740,7 +747,7 @@ VIDEO_INFO_ACCESSOR_CODE (framerate_denom, guint, 0);
*
* Returns: the Pixel Aspect Ratio (PAR) of the video stream (numerator).
*
* Since 0.10.31
* Since: 0.10.31
*/
VIDEO_INFO_ACCESSOR_CODE (par_num, guint, 0);
@ -751,7 +758,7 @@ VIDEO_INFO_ACCESSOR_CODE (par_num, guint, 0);
*
* Returns: the Pixel Aspect Ratio (PAR) of the video stream (denominator).
*
* Since 0.10.31
* Since: 0.10.31
*/
VIDEO_INFO_ACCESSOR_CODE (par_denom, guint, 0);
@ -762,7 +769,7 @@ VIDEO_INFO_ACCESSOR_CODE (par_denom, guint, 0);
*
* Returns: %TRUE if the stream is interlaced, else %FALSE.
*
* Since 0.10.31
* Since: 0.10.31
*/
gboolean
gst_discoverer_video_info_is_interlaced (const GstDiscovererVideoInfo * info)
@ -778,7 +785,7 @@ gst_discoverer_video_info_is_interlaced (const GstDiscovererVideoInfo * info)
*
* Returns: the average or nominal bitrate of the video stream in bits/second.
*
* Since 0.10.31
* Since: 0.10.31
*/
VIDEO_INFO_ACCESSOR_CODE (bitrate, guint, 0);
@ -789,7 +796,7 @@ VIDEO_INFO_ACCESSOR_CODE (bitrate, guint, 0);
*
* Returns: the maximum bitrate of the video stream in bits/second.
*
* Since 0.10.31
* Since: 0.10.31
*/
VIDEO_INFO_ACCESSOR_CODE (max_bitrate, guint, 0);
@ -801,7 +808,7 @@ VIDEO_INFO_ACCESSOR_CODE (max_bitrate, guint, 0);
* Returns: #TRUE if the video stream corresponds to an image (i.e. only contains
* one frame).
*
* Since 0.10.31
* Since: 0.10.31
*/
gboolean
gst_discoverer_video_info_is_image (const GstDiscovererVideoInfo * info)
@ -822,10 +829,10 @@ gst_discoverer_video_info_is_image (const GstDiscovererVideoInfo * info)
* gst_discoverer_info_get_uri:
* @info: a #GstDiscovererInfo
*
* Returns: the URI to which this information corresponds to. Copy it if you
* wish to use it after the life-time of @info.
* Returns: (transfer none): the URI to which this information corresponds to.
* Copy it if you wish to use it after the life-time of @info.
*
* Since 0.10.31
* Since: 0.10.31
*/
DISCOVERER_INFO_ACCESSOR_CODE (uri, const gchar *, NULL);
@ -836,7 +843,7 @@ DISCOVERER_INFO_ACCESSOR_CODE (uri, const gchar *, NULL);
*
* Returns: the result of the discovery as a #GstDiscovererResult.
*
* Since 0.10.31
* Since: 0.10.31
*/
DISCOVERER_INFO_ACCESSOR_CODE (result, GstDiscovererResult, GST_DISCOVERER_OK);
@ -845,11 +852,12 @@ DISCOVERER_INFO_ACCESSOR_CODE (result, GstDiscovererResult, GST_DISCOVERER_OK);
* gst_discoverer_info_get_stream_info:
* @info: a #GstDiscovererInfo
*
* Returns: the structure (or topology) of the URI as a #GstDiscovererStreamInfo.
* Returns: (transfer full): the structure (or topology) of the URI as a
* #GstDiscovererStreamInfo.
* This structure can be traversed to see the original hierarchy. Unref with
* #gst_discoverer_stream_info_unref after usage.
* gst_discoverer_stream_info_unref() after usage.
*
* Since 0.10.31
* Since: 0.10.31
*/
GstDiscovererStreamInfo *
@ -866,10 +874,11 @@ gst_discoverer_info_get_stream_info (GstDiscovererInfo * info)
* gst_discoverer_info_get_stream_list:
* @info: a #GstDiscovererInfo
*
* Returns: the list of all streams contained in the #info. Free after usage
* with #gst_discoverer_stream_info_list_free.
* Returns: (transfer full) (element-type Gst.DiscovererStreamInfo): the list of
* all streams contained in the #info. Free after usage
* with gst_discoverer_stream_info_list_free().
*
* Since 0.10.31
* Since: 0.10.31
*/
GList *
gst_discoverer_info_get_stream_list (GstDiscovererInfo * info)
@ -892,20 +901,31 @@ gst_discoverer_info_get_stream_list (GstDiscovererInfo * info)
*
* Returns: the duration of the URI in #GstClockTime (nanoseconds).
*
* Since 0.10.31
* Since: 0.10.31
*/
DISCOVERER_INFO_ACCESSOR_CODE (duration, GstClockTime, GST_CLOCK_TIME_NONE);
/**
* gst_discoverer_info_get_seekable:
* @info: a #GstDiscovererInfo
*
* Returns: the wheter the URI is seekable.
*
* Since: 0.10.32
*/
DISCOVERER_INFO_ACCESSOR_CODE (seekable, gboolean, FALSE);
/**
* gst_discoverer_info_get_misc:
* @info: a #GstDiscovererInfo
*
* Returns: Miscellaneous information stored as a #GstStructure (for example:
* information about missing plugins). If you wish to use the #GstStructure
* after the life-time of @info, you will need to copy it.
* Returns: (transfer none): Miscellaneous information stored as a #GstStructure
* (for example: information about missing plugins). If you wish to use the
* #GstStructure after the life-time of @info, you will need to copy it.
*
* Since 0.10.31
* Since: 0.10.31
*/
DISCOVERER_INFO_ACCESSOR_CODE (misc, const GstStructure *, NULL);
@ -914,10 +934,50 @@ DISCOVERER_INFO_ACCESSOR_CODE (misc, const GstStructure *, NULL);
* gst_discoverer_info_get_tags:
* @info: a #GstDiscovererInfo
*
* Returns: all tags contained in the %URI. If you wish to use the tags after
* the life-time of @info, you will need to copy them.
* Returns: (transfer none): all tags contained in the %URI. If you wish to use
* the tags after the life-time of @info, you will need to copy them.
*
* Since 0.10.31
* Since: 0.10.31
*/
DISCOVERER_INFO_ACCESSOR_CODE (tags, const GstTagList *, NULL);
/**
* gst_discoverer_info_ref:
* @info: a #GstDiscovererInfo
*
* Increments the reference count of @info.
*
* Returns: the same #GstDiscovererInfo object
*
* Since: 0.10.31
*/
/**
* gst_discoverer_info_unref:
* @info: a #GstDiscovererInfo
*
* Decrements the reference count of @info.
*
* Since: 0.10.31
*/
/**
* gst_discoverer_stream_info_ref:
* @info: a #GstDiscovererStreamInfo
*
* Increments the reference count of @info.
*
* Returns: the same #GstDiscovererStreamInfo object
*
* Since: 0.10.31
*/
/**
* gst_discoverer_stream_info_unref:
* @info: a #GstDiscovererStreamInfo
*
* Decrements the reference count of @info.
*
* Since: 0.10.31
*/

View file

@ -36,8 +36,8 @@
* asks for the discovery to begin (through gst_discoverer_start()).
*
* All the information is returned in a #GstDiscovererInfo structure.
*
* Since 0.10.31
*
* Since: 0.10.31
*/
#ifdef HAVE_CONFIG_H
@ -105,6 +105,15 @@ struct _GstDiscovererPrivate
GMainContext *ctx;
guint sourceid;
guint timeoutid;
/* reusable queries */
GstQuery *seeking_query;
/* Handler ids for various callbacks */
gulong pad_added_id;
gulong pad_remove_id;
gulong element_added_id;
gulong bus_cb_id;
};
#define DISCO_LOCK(dc) g_mutex_lock (dc->priv->lock);
@ -215,7 +224,7 @@ gst_discoverer_class_init (GstDiscovererClass * klass)
* @discoverer: the #GstDiscoverer
* @info: the results #GstDiscovererInfo
* @error: (type GLib.Error): #GError, which will be non-NULL if an error
* occured during discovery
* occurred during discovery
*
* Will be emitted when all information on a URI could be discovered.
*/
@ -242,6 +251,7 @@ static void
gst_discoverer_init (GstDiscoverer * dc)
{
GstElement *tmp;
GstFormat format = GST_FORMAT_TIME;
dc->priv = G_TYPE_INSTANCE_GET_PRIVATE (dc, GST_TYPE_DISCOVERER,
GstDiscovererPrivate);
@ -263,27 +273,34 @@ gst_discoverer_init (GstDiscoverer * dc)
GST_LOG_OBJECT (dc, "Adding uridecodebin to pipeline");
gst_bin_add (dc->priv->pipeline, dc->priv->uridecodebin);
g_signal_connect (dc->priv->uridecodebin, "pad-added",
G_CALLBACK (uridecodebin_pad_added_cb), dc);
g_signal_connect (dc->priv->uridecodebin, "pad-removed",
G_CALLBACK (uridecodebin_pad_removed_cb), dc);
dc->priv->pad_added_id =
g_signal_connect_object (dc->priv->uridecodebin, "pad-added",
G_CALLBACK (uridecodebin_pad_added_cb), dc, 0);
dc->priv->pad_remove_id =
g_signal_connect_object (dc->priv->uridecodebin, "pad-removed",
G_CALLBACK (uridecodebin_pad_removed_cb), dc, 0);
GST_LOG_OBJECT (dc, "Getting pipeline bus");
dc->priv->bus = gst_pipeline_get_bus ((GstPipeline *) dc->priv->pipeline);
g_signal_connect (dc->priv->bus, "message", G_CALLBACK (discoverer_bus_cb),
dc);
dc->priv->bus_cb_id =
g_signal_connect_object (dc->priv->bus, "message",
G_CALLBACK (discoverer_bus_cb), dc, 0);
GST_DEBUG_OBJECT (dc, "Done initializing Discoverer");
/* This is ugly. We get the GType of decodebin2 so we can quickly detect
* when a decodebin2 is added to uridecodebin so we can set the
* post-stream-topology setting to TRUE */
g_signal_connect (dc->priv->uridecodebin, "element-added",
G_CALLBACK (uridecodebin_element_added_cb), dc);
dc->priv->element_added_id =
g_signal_connect_object (dc->priv->uridecodebin, "element-added",
G_CALLBACK (uridecodebin_element_added_cb), dc, 0);
tmp = gst_element_factory_make ("decodebin2", NULL);
dc->priv->decodebin2_type = G_OBJECT_TYPE (tmp);
gst_object_unref (tmp);
/* create queries */
dc->priv->seeking_query = gst_query_new_seeking (format);
}
static void
@ -297,9 +314,16 @@ discoverer_reset (GstDiscoverer * dc)
dc->priv->pending_uris = NULL;
}
gst_element_set_state ((GstElement *) dc->priv->pipeline, GST_STATE_NULL);
if (dc->priv->pipeline)
gst_element_set_state ((GstElement *) dc->priv->pipeline, GST_STATE_NULL);
}
#define DISCONNECT_SIGNAL(o,i) G_STMT_START{ \
if ((i) && g_signal_handler_is_connected ((o), (i))) \
g_signal_handler_disconnect ((o), (i)); \
(i) = 0; \
}G_STMT_END
static void
gst_discoverer_dispose (GObject * obj)
{
@ -310,18 +334,34 @@ gst_discoverer_dispose (GObject * obj)
discoverer_reset (dc);
if (G_LIKELY (dc->priv->pipeline)) {
/* Workaround for bug #118536 */
DISCONNECT_SIGNAL (dc->priv->uridecodebin, dc->priv->pad_added_id);
DISCONNECT_SIGNAL (dc->priv->uridecodebin, dc->priv->pad_remove_id);
DISCONNECT_SIGNAL (dc->priv->uridecodebin, dc->priv->element_added_id);
DISCONNECT_SIGNAL (dc->priv->bus, dc->priv->bus_cb_id);
/* pipeline was set to NULL in _reset */
gst_object_unref (dc->priv->pipeline);
gst_object_unref (dc->priv->bus);
dc->priv->pipeline = NULL;
dc->priv->uridecodebin = NULL;
dc->priv->bus = NULL;
}
gst_discoverer_stop (dc);
if (dc->priv->lock) {
g_mutex_free (dc->priv->lock);
dc->priv->lock = NULL;
}
if (dc->priv->seeking_query) {
gst_query_unref (dc->priv->seeking_query);
dc->priv->seeking_query = NULL;
}
G_OBJECT_CLASS (gst_discoverer_parent_class)->dispose (obj);
}
static void
@ -373,12 +413,24 @@ static gboolean
_event_probe (GstPad * pad, GstEvent * event, PrivateStream * ps)
{
if (GST_EVENT_TYPE (event) == GST_EVENT_TAG) {
GstTagList *tl = NULL;
GstTagList *tl = NULL, *tmp;
gst_event_parse_tag (event, &tl);
GST_DEBUG_OBJECT (pad, "tags %" GST_PTR_FORMAT, tl);
DISCO_LOCK (ps->dc);
ps->tags = gst_tag_list_merge (ps->tags, tl, GST_TAG_MERGE_APPEND);
/* If preroll is complete, drop these tags - the collected information is
* possibly already being processed and adding more tags would be racy */
if (G_LIKELY (ps->dc->priv->processing)) {
GST_DEBUG_OBJECT (pad, "private stream %p old tags %" GST_PTR_FORMAT, ps,
ps->tags);
tmp = gst_tag_list_merge (ps->tags, tl, GST_TAG_MERGE_APPEND);
if (ps->tags)
gst_tag_list_free (ps->tags);
ps->tags = tmp;
GST_DEBUG_OBJECT (pad, "private stream %p new tags %" GST_PTR_FORMAT, ps,
tmp);
} else
GST_DEBUG_OBJECT (pad, "Dropping tags since preroll is done");
DISCO_UNLOCK (ps->dc);
}
@ -575,7 +627,8 @@ collect_information (GstDiscoverer * dc, const GstStructure * st,
if (gst_structure_id_has_field (st, _TAGS_QUARK)) {
gst_structure_id_get (st, _TAGS_QUARK,
GST_TYPE_STRUCTURE, &tags_st, NULL);
if (gst_structure_get_uint (tags_st, GST_TAG_BITRATE, &utmp))
if (gst_structure_get_uint (tags_st, GST_TAG_BITRATE, &utmp) ||
gst_structure_get_uint (tags_st, GST_TAG_NOMINAL_BITRATE, &utmp))
info->bitrate = utmp;
if (gst_structure_get_uint (tags_st, GST_TAG_MAXIMUM_BITRATE, &utmp))
@ -627,7 +680,8 @@ collect_information (GstDiscoverer * dc, const GstStructure * st,
if (gst_structure_id_has_field (st, _TAGS_QUARK)) {
gst_structure_id_get (st, _TAGS_QUARK,
GST_TYPE_STRUCTURE, &tags_st, NULL);
if (gst_structure_get_uint (tags_st, GST_TAG_BITRATE, &utmp))
if (gst_structure_get_uint (tags_st, GST_TAG_BITRATE, &utmp) ||
gst_structure_get_uint (tags_st, GST_TAG_NOMINAL_BITRATE, &utmp))
info->bitrate = utmp;
if (gst_structure_get_uint (tags_st, GST_TAG_MAXIMUM_BITRATE, &utmp))
@ -817,12 +871,21 @@ parse_stream_topology (GstDiscoverer * dc, const GstStructure * topology,
res = (GstDiscovererStreamInfo *) cont;
if (gst_structure_id_has_field (topology, _TAGS_QUARK)) {
GstTagList *tmp;
gst_structure_id_get (topology, _TAGS_QUARK,
GST_TYPE_STRUCTURE, &tags, NULL);
cont->parent.tags =
GST_DEBUG ("Merge tags %" GST_PTR_FORMAT, tags);
tmp =
gst_tag_list_merge (cont->parent.tags, (GstTagList *) tags,
GST_TAG_MERGE_APPEND);
gst_tag_list_free (tags);
if (cont->parent.tags)
gst_tag_list_free (cont->parent.tags);
cont->parent.tags = tmp;
GST_DEBUG ("Container info tags %" GST_PTR_FORMAT, tmp);
}
for (i = 0; i < len; i++) {
@ -859,18 +922,31 @@ discoverer_collect (GstDiscoverer * dc)
if (dc->priv->streams) {
/* FIXME : Make this querying optional */
if (TRUE) {
GstElement *pipeline = (GstElement *) dc->priv->pipeline;
GstFormat format = GST_FORMAT_TIME;
gint64 dur;
GST_DEBUG ("Attempting to query duration");
if (gst_element_query_duration ((GstElement *) dc->priv->pipeline,
&format, &dur)) {
if (gst_element_query_duration (pipeline, &format, &dur)) {
if (format == GST_FORMAT_TIME) {
GST_DEBUG ("Got duration %" GST_TIME_FORMAT, GST_TIME_ARGS (dur));
dc->priv->current_info->duration = (guint64) dur;
}
}
if (dc->priv->seeking_query) {
if (gst_element_query (pipeline, dc->priv->seeking_query)) {
gboolean seekable;
gst_query_parse_seeking (dc->priv->seeking_query, &format,
&seekable, NULL, NULL);
if (format == GST_FORMAT_TIME) {
GST_DEBUG ("Got seekable %d", seekable);
dc->priv->current_info->seekable = seekable;
}
}
}
}
if (dc->priv->current_topology)
@ -908,14 +984,34 @@ discoverer_collect (GstDiscoverer * dc)
}
}
static void
get_async_cb (gpointer cb_data, GSource * source, GSourceFunc * func,
gpointer * data)
{
*func = (GSourceFunc) async_timeout_cb;
*data = cb_data;
}
/* Wrapper since GSourceCallbackFuncs don't expect a return value from ref() */
static void
_void_g_object_ref (gpointer object)
{
g_object_ref (G_OBJECT (object));
}
static void
handle_current_async (GstDiscoverer * dc)
{
GSource *source;
static GSourceCallbackFuncs cb_funcs = {
.ref = _void_g_object_ref,
.unref = g_object_unref,
.get = get_async_cb,
};
/* Attach a timeout to the main context */
source = g_timeout_source_new (dc->priv->timeout / GST_MSECOND);
g_source_set_callback (source, (GSourceFunc) async_timeout_cb, dc, NULL);
g_source_set_callback_indirect (source, g_object_ref (dc), &cb_funcs);
dc->priv->timeoutid = g_source_attach (source, dc->priv->ctx);
g_source_unref (source);
}
@ -927,7 +1023,8 @@ handle_message (GstDiscoverer * dc, GstMessage * msg)
{
gboolean done = FALSE;
GST_DEBUG ("got a %s message", GST_MESSAGE_TYPE_NAME (msg));
GST_DEBUG_OBJECT (GST_MESSAGE_SRC (msg), "got a %s message",
GST_MESSAGE_TYPE_NAME (msg));
switch (GST_MESSAGE_TYPE (msg)) {
case GST_MESSAGE_ERROR:{
@ -935,8 +1032,8 @@ handle_message (GstDiscoverer * dc, GstMessage * msg)
gchar *debug;
gst_message_parse_error (msg, &gerr, &debug);
GST_WARNING ("Got an error [debug:%s]", debug);
GST_WARNING ("Got an error [message:%s]", gerr->message);
GST_WARNING_OBJECT (GST_MESSAGE_SRC (msg),
"Got an error [debug:%s], [message:%s]", debug, gerr->message);
dc->priv->current_error = gerr;
g_free (debug);
@ -967,7 +1064,8 @@ handle_message (GstDiscoverer * dc, GstMessage * msg)
GST_DEBUG_OBJECT (GST_MESSAGE_SRC (msg),
"structure %" GST_PTR_FORMAT, msg->structure);
if (sttype == _MISSING_PLUGIN_QUARK) {
GST_DEBUG ("Setting result to MISSING_PLUGINS");
GST_DEBUG_OBJECT (GST_MESSAGE_SRC (msg),
"Setting result to MISSING_PLUGINS");
dc->priv->current_info->result = GST_DISCOVERER_MISSING_PLUGINS;
dc->priv->current_info->misc = gst_structure_copy (msg->structure);
} else if (sttype == _STREAM_TOPOLOGY_QUARK) {
@ -978,15 +1076,20 @@ handle_message (GstDiscoverer * dc, GstMessage * msg)
case GST_MESSAGE_TAG:
{
GstTagList *tl;
GstTagList *tl, *tmp;
gst_message_parse_tag (msg, &tl);
GST_DEBUG ("Got tags %" GST_PTR_FORMAT, tl);
GST_DEBUG_OBJECT (GST_MESSAGE_SRC (msg), "Got tags %" GST_PTR_FORMAT, tl);
/* Merge with current tags */
dc->priv->current_info->tags =
tmp =
gst_tag_list_merge (dc->priv->current_info->tags, tl,
GST_TAG_MERGE_APPEND);
gst_tag_list_free (tl);
if (dc->priv->current_info->tags)
gst_tag_list_free (dc->priv->current_info->tags);
dc->priv->current_info->tags = tmp;
GST_DEBUG_OBJECT (GST_MESSAGE_SRC (msg), "Current info %p, tags %"
GST_PTR_FORMAT, dc->priv->current_info, tmp);
}
break;
@ -1109,7 +1212,10 @@ discoverer_bus_cb (GstBus * bus, GstMessage * msg, GstDiscoverer * dc)
if (dc->priv->processing) {
if (handle_message (dc, msg)) {
GST_DEBUG ("Stopping asynchronously");
/* Serialise with _event_probe() */
DISCO_LOCK (dc);
dc->priv->processing = FALSE;
DISCO_UNLOCK (dc);
discoverer_collect (dc);
discoverer_cleanup (dc);
}
@ -1119,12 +1225,14 @@ discoverer_bus_cb (GstBus * bus, GstMessage * msg, GstDiscoverer * dc)
static gboolean
async_timeout_cb (GstDiscoverer * dc)
{
dc->priv->timeoutid = 0;
GST_DEBUG ("Setting result to TIMEOUT");
dc->priv->current_info->result = GST_DISCOVERER_TIMEOUT;
dc->priv->processing = FALSE;
discoverer_collect (dc);
discoverer_cleanup (dc);
if (!g_source_is_destroyed (g_main_current_source ())) {
dc->priv->timeoutid = 0;
GST_DEBUG ("Setting result to TIMEOUT");
dc->priv->current_info->result = GST_DISCOVERER_TIMEOUT;
dc->priv->processing = FALSE;
discoverer_collect (dc);
discoverer_cleanup (dc);
}
return FALSE;
}
@ -1175,11 +1283,11 @@ beach:
/**
* gst_discoverer_start:
* @discoverer: A #GstDiscoverer
*
*
* Allow asynchronous discovering of URIs to take place.
* A #GMainLoop must be available for #GstDiscoverer to properly work in
* asynchronous mode.
*
*
* Since: 0.10.31
*/
void
@ -1221,8 +1329,8 @@ gst_discoverer_start (GstDiscoverer * discoverer)
*
* Stop the discovery of any pending URIs and clears the list of
* pending URIS (if any).
*
* Since 0.10.31
*
* Since: 0.10.31
*/
void
gst_discoverer_stop (GstDiscoverer * discoverer)
@ -1240,9 +1348,11 @@ gst_discoverer_stop (GstDiscoverer * discoverer)
/* We prevent any further processing by setting the bus to
* flushing and setting the pipeline to READY.
* _reset() will take care of the rest of the cleanup */
gst_bus_set_flushing (discoverer->priv->bus, TRUE);
gst_element_set_state ((GstElement *) discoverer->priv->pipeline,
GST_STATE_READY);
if (discoverer->priv->bus)
gst_bus_set_flushing (discoverer->priv->bus, TRUE);
if (discoverer->priv->pipeline)
gst_element_set_state ((GstElement *) discoverer->priv->pipeline,
GST_STATE_READY);
}
discoverer->priv->running = FALSE;
DISCO_UNLOCK (discoverer);
@ -1278,11 +1388,12 @@ gst_discoverer_stop (GstDiscoverer * discoverer)
* discovery of the @uri will only take place if gst_discoverer_start() has
* been called.
*
* A copy of @uri will be done internally, the caller can safely g_free() afterwards.
* A copy of @uri will be made internally, so the caller can safely g_free()
* afterwards.
*
* Returns: %TRUE if the @uri was succesfully appended to the list of pending
* uris, else %FALSE
*
*
* Since: 0.10.31
*/
gboolean
@ -1311,14 +1422,16 @@ gst_discoverer_discover_uri_async (GstDiscoverer * discoverer,
* gst_discoverer_discover_uri:
* @discoverer: A #GstDiscoverer
* @uri: The URI to run on.
* @err: If an error occured, this field will be filled in.
* @err: If an error occurred, this field will be filled in.
*
* Synchronously discovers the given @uri.
*
* A copy of @uri will be done internally, the caller can safely g_free() afterwards.
* A copy of @uri will be made internally, so the caller can safely g_free()
* afterwards.
*
* Returns: (transfer full): the result of the scanning. Can be %NULL if an
* error occurred.
*
* Returns: see #GstDiscovererInfo. The caller must unref this structure after use.
*
* Since: 0.10.31
*/
GstDiscovererInfo *
@ -1369,11 +1482,11 @@ gst_discoverer_discover_uri (GstDiscoverer * discoverer, const gchar * uri,
*
* Creates a new #GstDiscoverer with the provided timeout.
*
* Returns: The new #GstDiscoverer. Free with gst_object_unref() when done.
* If an error happened when creating the discoverer, @err will be set
* Returns: (transfer full): The new #GstDiscoverer.
* If an error occurred when creating the discoverer, @err will be set
* accordingly and %NULL will be returned. If @err is set, the caller must
* free it when no longer needed using g_error_free().
*
*
* Since: 0.10.31
*/
GstDiscoverer *

View file

@ -38,9 +38,21 @@ GType gst_discoverer_stream_info_get_type (void);
/**
* GstDiscovererStreamInfo:
*
* Base structure for informations concerning a media stream. Depending on the @streamtype,
* One can find more media-specific information in #GstDiscovererAudioInfo,
* #GstDiscovererVideoInfo, #GstDiscovererContainerInfo.
* Base structure for information concerning a media stream. Depending on the
* stream type, one can find more media-specific information in
* #GstDiscovererAudioInfo, #GstDiscovererVideoInfo, and
* #GstDiscovererContainerInfo.
*
* The #GstDiscovererStreamInfo represents the topology of the stream. Siblings
* can be iterated over with gst_discoverer_stream_info_get_next() and
* gst_discoverer_stream_info_get_previous(). Children (sub-streams) of a
* stream can be accessed using the #GstDiscovererContainerInfo API.
*
* As a simple example, if you run #GstDiscoverer on an AVI file with one audio
* and one video stream, you will get a #GstDiscovererContainerInfo
* corresponding to the AVI container, which in turn will have a
* #GstDiscovererAudioInfo sub-stream and a #GstDiscovererVideoInfo sub-stream
* for the audio and video streams respectively.
*
* Since: 0.10.31
*/
@ -102,7 +114,7 @@ guint gst_discoverer_audio_info_get_max_bitrate(const GstDiscovererAudioInfo* in
/**
* GstDiscovererVideoInfo:
*
* #GstDiscovererStreamInfo specific to video streams.
* #GstDiscovererStreamInfo specific to video streams (this includes images).
*
* Since: 0.10.31
*/
@ -179,6 +191,7 @@ GstDiscovererResult gst_discoverer_info_get_result(const GstDiscovererInfo
GstDiscovererStreamInfo* gst_discoverer_info_get_stream_info(GstDiscovererInfo* info);
GList* gst_discoverer_info_get_stream_list(GstDiscovererInfo* info);
GstClockTime gst_discoverer_info_get_duration(const GstDiscovererInfo* info);
gboolean gst_discoverer_info_get_seekable(const GstDiscovererInfo* info);
const GstStructure* gst_discoverer_info_get_misc(const GstDiscovererInfo* info);
const GstTagList* gst_discoverer_info_get_tags(const GstDiscovererInfo* info);

View file

@ -608,8 +608,8 @@ gst_install_plugins_installer_exited (GPid pid, gint status, gpointer data)
* gst_install_plugins_async:
* @details: NULL-terminated array of installer string details (see below)
* @ctx: a #GstInstallPluginsContext, or NULL
* @func: the function to call when the installer program returns
* @user_data: the user data to pass to @func when called, or NULL
* @func: (scope async): the function to call when the installer program returns
* @user_data: (closure): the user data to pass to @func when called, or NULL
*
* Requests plugin installation without blocking. Once the plugins have been
* installed or installation has failed, @func will be called with the result

View file

@ -166,7 +166,7 @@ copy_and_clean_caps (const GstCaps * caps)
* that a source element for a particular URI protocol is missing. This
* function is mainly for use in plugins.
*
* Returns: a new #GstMessage, or NULL on error
* Returns: (transfer full): a new #GstMessage, or NULL on error
*/
GstMessage *
gst_missing_uri_source_message_new (GstElement * element,
@ -199,7 +199,7 @@ gst_missing_uri_source_message_new (GstElement * element,
* that a sink element for a particular URI protocol is missing. This
* function is mainly for use in plugins.
*
* Returns: a new #GstMessage, or NULL on error
* Returns: (transfer full): a new #GstMessage, or NULL on error
*/
GstMessage *
gst_missing_uri_sink_message_new (GstElement * element, const gchar * protocol)
@ -231,7 +231,7 @@ gst_missing_uri_sink_message_new (GstElement * element, const gchar * protocol)
* that a certain required element is missing. This function is mainly for
* use in plugins.
*
* Returns: a new #GstMessage, or NULL on error
* Returns: (transfer full): a new #GstMessage, or NULL on error
*/
GstMessage *
gst_missing_element_message_new (GstElement * element,
@ -263,7 +263,7 @@ gst_missing_element_message_new (GstElement * element,
* that a decoder element for a particular set of (fixed) caps is missing.
* This function is mainly for use in plugins.
*
* Returns: a new #GstMessage, or NULL on error
* Returns: (transfer full): a new #GstMessage, or NULL on error
*/
GstMessage *
gst_missing_decoder_message_new (GstElement * element,
@ -303,7 +303,7 @@ gst_missing_decoder_message_new (GstElement * element,
* that an encoder element for a particular set of (fixed) caps is missing.
* This function is mainly for use in plugins.
*
* Returns: a new #GstMessage, or NULL on error
* Returns: (transfer full): a new #GstMessage, or NULL on error
*/
GstMessage *
gst_missing_encoder_message_new (GstElement * element,

View file

@ -78,6 +78,7 @@ struct _GstDiscovererInfo {
GstClockTime duration;
GstStructure *misc;
GstTagList *tags;
gboolean seekable;
};
/* missing-plugins.c */

View file

@ -29,6 +29,8 @@
#include <gst/pbutils/codec-utils.h>
#include <gst/pbutils/pbutils-enumtypes.h>
#include <gst/pbutils/gstdiscoverer.h>
#include <gst/pbutils/encoding-profile.h>
#include <gst/pbutils/encoding-target.h>
G_BEGIN_DECLS

View file

@ -61,7 +61,8 @@ typelibsdir = $(libdir)/girepository-1.0/
typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib)
%.typelib: %.gir $(INTROSPECTION_COMPILER)
$(AM_V_GEN)$(INTROSPECTION_COMPILER) \
$(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \
$(INTROSPECTION_COMPILER) \
--includedir=$(srcdir) \
--includedir=$(builddir) \
--includedir=$(builddir)/../tag \

View file

@ -717,6 +717,22 @@ gst_riff_create_video_caps (guint32 codec_fcc,
break;
}
case GST_MAKE_FOURCC ('C', 'S', 'C', 'D'):
{
if (strf) {
gint depth = (strf->bit_cnt != 0) ? (gint) strf->bit_cnt : 24;
caps = gst_caps_new_simple ("video/x-camstudio", "depth", G_TYPE_INT,
depth, NULL);
} else {
/* template caps */
caps = gst_caps_new_simple ("video/x-camstudio", NULL);
}
if (codec_name)
*codec_name = g_strdup ("Camstudio");
break;
}
case GST_MAKE_FOURCC ('V', 'C', 'R', '1'):
caps = gst_caps_new_simple ("video/x-ati-vcr",
"vcrversion", G_TYPE_INT, 1, NULL);
@ -1737,6 +1753,7 @@ gst_riff_create_video_template_caps (void)
GST_MAKE_FOURCC ('A', 'S', 'V', '1'),
GST_MAKE_FOURCC ('A', 'S', 'V', '2'),
GST_MAKE_FOURCC ('C', 'L', 'J', 'R'),
GST_MAKE_FOURCC ('C', 'S', 'C', 'D'),
GST_MAKE_FOURCC ('C', 'Y', 'U', 'V'),
GST_MAKE_FOURCC ('D', 'I', 'B', ' '),
GST_MAKE_FOURCC ('D', 'I', 'V', '3'),

View file

@ -57,7 +57,8 @@ typelibsdir = $(libdir)/girepository-1.0/
typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib)
%.typelib: %.gir $(INTROSPECTION_COMPILER)
$(AM_V_GEN)$(INTROSPECTION_COMPILER) \
$(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \
$(INTROSPECTION_COMPILER) \
--includedir=$(srcdir) \
--includedir=$(builddir) \
--includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \

View file

@ -482,12 +482,11 @@ gst_base_rtp_audio_payload_push (GstBaseRTPAudioPayload * baseaudiopayload,
static GstFlowReturn
gst_base_rtp_audio_payload_push_buffer (GstBaseRTPAudioPayload *
baseaudiopayload, GstBuffer * buffer)
baseaudiopayload, GstBuffer * buffer, GstClockTime timestamp)
{
GstBaseRTPPayload *basepayload;
GstBaseRTPAudioPayloadPrivate *priv;
GstBuffer *outbuf;
GstClockTime timestamp;
guint8 *payload;
guint payload_len;
GstFlowReturn ret;
@ -496,7 +495,6 @@ gst_base_rtp_audio_payload_push_buffer (GstBaseRTPAudioPayload *
basepayload = GST_BASE_RTP_PAYLOAD (baseaudiopayload);
payload_len = GST_BUFFER_SIZE (buffer);
timestamp = GST_BUFFER_TIMESTAMP (buffer);
GST_DEBUG_OBJECT (baseaudiopayload, "Pushing %d bytes ts %" GST_TIME_FORMAT,
payload_len, GST_TIME_ARGS (timestamp));
@ -607,7 +605,9 @@ gst_base_rtp_audio_payload_flush (GstBaseRTPAudioPayload * baseaudiopayload,
* anything. */
buffer = gst_adapter_take_buffer (adapter, payload_len);
ret = gst_base_rtp_audio_payload_push_buffer (baseaudiopayload, buffer);
ret =
gst_base_rtp_audio_payload_push_buffer (baseaudiopayload, buffer,
timestamp);
} else {
/* create buffer to hold the payload */
outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0);
@ -814,23 +814,22 @@ gst_base_rtp_audio_payload_handle_buffer (GstBaseRTPPayload *
guint align;
guint size;
gboolean discont;
GstClockTime timestamp;
ret = GST_FLOW_OK;
payload = GST_BASE_RTP_AUDIO_PAYLOAD_CAST (basepayload);
priv = payload->priv;
timestamp = GST_BUFFER_TIMESTAMP (buffer);
discont = GST_BUFFER_IS_DISCONT (buffer);
if (discont) {
GstClockTime timestamp;
GST_DEBUG_OBJECT (payload, "Got DISCONT");
/* flush everything out of the adapter, mark DISCONT */
ret = gst_base_rtp_audio_payload_flush (payload, -1, -1);
priv->discont = TRUE;
timestamp = GST_BUFFER_TIMESTAMP (buffer);
/* get the distance between the timestamp gap and produce the same gap in
* the RTP timestamps */
if (priv->last_timestamp != -1 && timestamp != -1) {
@ -878,7 +877,7 @@ gst_base_rtp_audio_payload_handle_buffer (GstBaseRTPPayload *
/* If buffer fits on an RTP packet, let's just push it through
* this will check against max_ptime and max_mtu */
GST_DEBUG_OBJECT (payload, "Fast packet push");
ret = gst_base_rtp_audio_payload_push_buffer (payload, buffer);
ret = gst_base_rtp_audio_payload_push_buffer (payload, buffer, timestamp);
} else {
/* push the buffer in the adapter */
gst_adapter_push (priv->adapter, buffer);

View file

@ -97,6 +97,8 @@ static void gst_base_rtp_depayload_set_gst_timestamp
(GstBaseRTPDepayload * filter, guint32 rtptime, GstBuffer * buf);
static gboolean gst_base_rtp_depayload_packet_lost (GstBaseRTPDepayload *
filter, GstEvent * event);
static gboolean gst_base_rtp_depayload_handle_event (GstBaseRTPDepayload *
filter, GstEvent * event);
GST_BOILERPLATE (GstBaseRTPDepayload, gst_base_rtp_depayload, GstElement,
GST_TYPE_ELEMENT);
@ -142,6 +144,7 @@ gst_base_rtp_depayload_class_init (GstBaseRTPDepayloadClass * klass)
klass->set_gst_timestamp = gst_base_rtp_depayload_set_gst_timestamp;
klass->packet_lost = gst_base_rtp_depayload_packet_lost;
klass->handle_event = gst_base_rtp_depayload_handle_event;
GST_DEBUG_CATEGORY_INIT (basertpdepayload_debug, "basertpdepayload", 0,
"Base class for RTP Depayloaders");
@ -407,14 +410,12 @@ no_process:
}
static gboolean
gst_base_rtp_depayload_handle_sink_event (GstPad * pad, GstEvent * event)
gst_base_rtp_depayload_handle_event (GstBaseRTPDepayload * filter,
GstEvent * event)
{
GstBaseRTPDepayload *filter;
gboolean res = TRUE;
gboolean forward = TRUE;
filter = GST_BASE_RTP_DEPAYLOAD (GST_OBJECT_PARENT (pad));
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_STOP:
gst_segment_init (&filter->segment, GST_FORMAT_UNDEFINED);
@ -474,6 +475,22 @@ gst_base_rtp_depayload_handle_sink_event (GstPad * pad, GstEvent * event)
return res;
}
static gboolean
gst_base_rtp_depayload_handle_sink_event (GstPad * pad, GstEvent * event)
{
gboolean res = FALSE;
GstBaseRTPDepayload *filter;
GstBaseRTPDepayloadClass *bclass;
filter = GST_BASE_RTP_DEPAYLOAD (GST_OBJECT_PARENT (pad));
bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter);
if (bclass->handle_event)
res = bclass->handle_event (filter, event);
return res;
}
static GstEvent *
create_segment_event (GstBaseRTPDepayload * filter, gboolean update,
GstClockTime position)
@ -496,30 +513,58 @@ create_segment_event (GstBaseRTPDepayload * filter, gboolean update,
return event;
}
static GstFlowReturn
gst_base_rtp_depayload_push_full (GstBaseRTPDepayload * filter,
gboolean do_ts, guint32 rtptime, GstBuffer * out_buf)
typedef struct
{
GstFlowReturn ret;
GstCaps *srccaps;
GstBaseRTPDepayload *depayload;
GstBaseRTPDepayloadClass *bclass;
GstCaps *caps;
gboolean do_ts;
gboolean rtptime;
} HeaderData;
static GstBufferListItem
set_headers (GstBuffer ** buffer, guint group, guint idx, HeaderData * data)
{
GstBaseRTPDepayload *depayload = data->depayload;
*buffer = gst_buffer_make_metadata_writable (*buffer);
gst_buffer_set_caps (*buffer, data->caps);
/* set the timestamp if we must and can */
if (data->bclass->set_gst_timestamp && data->do_ts)
data->bclass->set_gst_timestamp (depayload, data->rtptime, *buffer);
if (G_UNLIKELY (depayload->priv->discont)) {
GST_LOG_OBJECT (depayload, "Marking DISCONT on output buffer");
GST_BUFFER_FLAG_SET (*buffer, GST_BUFFER_FLAG_DISCONT);
depayload->priv->discont = FALSE;
}
return GST_BUFFER_LIST_SKIP_GROUP;
}
static GstFlowReturn
gst_base_rtp_depayload_prepare_push (GstBaseRTPDepayload * filter,
gboolean do_ts, guint32 rtptime, gboolean is_list, gpointer obj)
{
GstBaseRTPDepayloadPrivate *priv;
HeaderData data;
priv = filter->priv;
/* almost certainly required */
out_buf = gst_buffer_make_metadata_writable (out_buf);
data.depayload = filter;
data.caps = GST_PAD_CAPS (filter->srcpad);
data.rtptime = rtptime;
data.do_ts = do_ts;
data.bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter);
/* set the caps if any */
srccaps = GST_PAD_CAPS (filter->srcpad);
if (G_LIKELY (srccaps))
gst_buffer_set_caps (out_buf, srccaps);
bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter);
/* set the timestamp if we must and can */
if (bclass->set_gst_timestamp && do_ts)
bclass->set_gst_timestamp (filter, rtptime, out_buf);
if (is_list) {
GstBufferList **blist = obj;
gst_buffer_list_foreach (*blist, (GstBufferListFunc) set_headers, &data);
} else {
GstBuffer **buf = obj;
set_headers (buf, 0, 0, &data);
}
/* if this is the first buffer send a NEWSEGMENT */
if (G_UNLIKELY (filter->need_newsegment)) {
@ -533,20 +578,7 @@ gst_base_rtp_depayload_push_full (GstBaseRTPDepayload * filter,
GST_DEBUG_OBJECT (filter, "Pushed newsegment event on this first buffer");
}
if (G_UNLIKELY (priv->discont)) {
GST_LOG_OBJECT (filter, "Marking DISCONT on output buffer");
GST_BUFFER_FLAG_SET (out_buf, GST_BUFFER_FLAG_DISCONT);
priv->discont = FALSE;
}
/* push it */
GST_LOG_OBJECT (filter, "Pushing buffer size %d, timestamp %" GST_TIME_FORMAT,
GST_BUFFER_SIZE (out_buf),
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (out_buf)));
ret = gst_pad_push (filter->srcpad, out_buf);
return ret;
return GST_FLOW_OK;
}
/**
@ -569,7 +601,18 @@ GstFlowReturn
gst_base_rtp_depayload_push_ts (GstBaseRTPDepayload * filter, guint32 timestamp,
GstBuffer * out_buf)
{
return gst_base_rtp_depayload_push_full (filter, TRUE, timestamp, out_buf);
GstFlowReturn res;
res =
gst_base_rtp_depayload_prepare_push (filter, TRUE, timestamp, FALSE,
&out_buf);
if (G_LIKELY (res == GST_FLOW_OK))
res = gst_pad_push (filter->srcpad, out_buf);
else
gst_buffer_unref (out_buf);
return res;
}
/**
@ -589,7 +632,44 @@ gst_base_rtp_depayload_push_ts (GstBaseRTPDepayload * filter, guint32 timestamp,
GstFlowReturn
gst_base_rtp_depayload_push (GstBaseRTPDepayload * filter, GstBuffer * out_buf)
{
return gst_base_rtp_depayload_push_full (filter, FALSE, 0, out_buf);
GstFlowReturn res;
res = gst_base_rtp_depayload_prepare_push (filter, FALSE, 0, FALSE, &out_buf);
if (G_LIKELY (res == GST_FLOW_OK))
res = gst_pad_push (filter->srcpad, out_buf);
else
gst_buffer_unref (out_buf);
return res;
}
/**
* gst_base_rtp_depayload_push_list:
* @filter: a #GstBaseRTPDepayload
* @out_list: a #GstBufferList
*
* Push @out_list to the peer of @filter. This function takes ownership of
* @out_list.
*
* Returns: a #GstFlowReturn.
*
* Since: 0.10.32
*/
GstFlowReturn
gst_base_rtp_depayload_push_list (GstBaseRTPDepayload * filter,
GstBufferList * out_list)
{
GstFlowReturn res;
res = gst_base_rtp_depayload_prepare_push (filter, TRUE, 0, TRUE, &out_list);
if (G_LIKELY (res == GST_FLOW_OK))
res = gst_pad_push_list (filter->srcpad, out_list);
else
gst_buffer_list_unref (out_list);
return res;
}
/* convert the PacketLost event form a jitterbuffer to a segment update.

View file

@ -119,8 +119,13 @@ struct _GstBaseRTPDepayloadClass
* The default implementation of this message pushes a segment update. */
gboolean (*packet_lost) (GstBaseRTPDepayload *filter, GstEvent *event);
/* the default implementation does the default actions for events but
* implementation can override.
* Since: 0.10.32 */
gboolean (*handle_event) (GstBaseRTPDepayload * filter, GstEvent * event);
/*< private >*/
gpointer _gst_reserved[GST_PADDING-1];
gpointer _gst_reserved[GST_PADDING-2];
};
GType gst_base_rtp_depayload_get_type (void);
@ -128,6 +133,8 @@ GType gst_base_rtp_depayload_get_type (void);
GstFlowReturn gst_base_rtp_depayload_push (GstBaseRTPDepayload *filter, GstBuffer *out_buf);
GstFlowReturn gst_base_rtp_depayload_push_ts (GstBaseRTPDepayload *filter,
guint32 timestamp, GstBuffer *out_buf);
GstFlowReturn gst_base_rtp_depayload_push_list (GstBaseRTPDepayload *filter, GstBufferList *out_list);
G_END_DECLS

View file

@ -402,15 +402,25 @@ gst_basertppayload_event (GstPad * pad, GstEvent * event)
case GST_EVENT_NEWSEGMENT:
{
gboolean update;
gdouble rate;
gdouble rate, arate;
GstFormat fmt;
gint64 start, stop, position;
GstSegment *segment;
gst_event_parse_new_segment (event, &update, &rate, &fmt, &start, &stop,
&position);
gst_segment_set_newsegment (&basertppayload->segment, update, rate, fmt,
start, stop, position);
segment = &basertppayload->segment;
gst_event_parse_new_segment_full (event, &update, &rate, &arate, &fmt,
&start, &stop, &position);
gst_segment_set_newsegment_full (segment, update, rate, arate, fmt, start,
stop, position);
GST_DEBUG_OBJECT (basertppayload,
"configured NEWSEGMENT update %d, rate %lf, applied rate %lf, "
"format %d, "
"%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %"
G_GINT64_FORMAT ", accum %" G_GINT64_FORMAT, update, rate, arate,
segment->format, segment->start, segment->stop, segment->time,
segment->accum);
/* fallthrough */
}
default:
@ -777,12 +787,16 @@ gst_basertppayload_prepare_push (GstBaseRTPPayload * payload,
rtime = gst_segment_to_running_time (&payload->segment, GST_FORMAT_TIME,
data.timestamp);
GST_LOG_OBJECT (payload,
"Using running_time %" GST_TIME_FORMAT " for RTP timestamp",
GST_TIME_ARGS (rtime));
rtime = gst_util_uint64_scale_int (rtime, payload->clock_rate, GST_SECOND);
if (rtime == -1) {
GST_LOG_OBJECT (payload, "Clipped timestamp, using base RTP timestamp");
rtime = 0;
} else {
GST_LOG_OBJECT (payload,
"Using running_time %" GST_TIME_FORMAT " for RTP timestamp",
GST_TIME_ARGS (rtime));
rtime =
gst_util_uint64_scale_int (rtime, payload->clock_rate, GST_SECOND);
}
/* add running_time in clock-rate units to the base timestamp */
data.rtptime = payload->ts_base + rtime;
} else {
@ -810,8 +824,8 @@ gst_basertppayload_prepare_push (GstBaseRTPPayload * payload,
GST_BUFFER_SIZE (GST_BUFFER (obj)), payload->seqnum, data.rtptime,
GST_TIME_ARGS (data.timestamp));
if (g_atomic_int_compare_and_exchange (&payload->priv->
notified_first_timestamp, 1, 0)) {
if (g_atomic_int_compare_and_exchange (&payload->
priv->notified_first_timestamp, 1, 0)) {
g_object_notify (G_OBJECT (payload), "timestamp");
g_object_notify (G_OBJECT (payload), "seqnum");
}

View file

@ -453,33 +453,20 @@ gst_rtp_buffer_list_validate (GstBufferList * list)
guint8 *packet_payload;
guint payload_size;
guint packet_size;
guint j, n_buffers;
/* each group should consists of 2 buffers: one containing the RTP header
* and the other one the payload, FIXME, relax the requirement of only one
* payload buffer. */
if (gst_buffer_list_iterator_n_buffers (it) != 2)
/* each group should consists of at least 1 buffer: The first buffer always
* contains the complete RTP header. Next buffers contain the payload */
n_buffers = gst_buffer_list_iterator_n_buffers (it);
if (n_buffers < 1)
goto invalid_list;
/* get the RTP header */
/* get the RTP header (and if n_buffers == 1 also the payload) */
rtpbuf = gst_buffer_list_iterator_next (it);
packet_header = GST_BUFFER_DATA (rtpbuf);
if (packet_header == NULL)
goto invalid_list;
/* get the payload */
paybuf = gst_buffer_list_iterator_next (it);
packet_payload = GST_BUFFER_DATA (paybuf);
if (packet_payload == NULL) {
goto invalid_list;
}
payload_size = GST_BUFFER_SIZE (paybuf);
if (payload_size == 0) {
goto invalid_list;
}
/* the size of the RTP packet within the current group */
packet_size = GST_BUFFER_SIZE (rtpbuf) + payload_size;
/* check the sequence number */
if (G_UNLIKELY (i == 0)) {
prev_seqnum = g_ntohs (GST_RTP_HEADER_SEQ (packet_header));
@ -489,6 +476,25 @@ gst_rtp_buffer_list_validate (GstBufferList * list)
goto invalid_list;
}
packet_size = GST_BUFFER_SIZE (rtpbuf);
packet_payload = NULL;
payload_size = 0;
/* get the payload buffers */
for (j = 1; j < n_buffers; j++) {
/* get the payload */
paybuf = gst_buffer_list_iterator_next (it);
if ((packet_payload = GST_BUFFER_DATA (paybuf)) == NULL)
goto invalid_list;
if ((payload_size = GST_BUFFER_SIZE (paybuf)) == 0)
goto invalid_list;
/* the size of the RTP packet within the current group */
packet_size += payload_size;
}
/* validate packet */
if (!validate_data (packet_header, packet_size, packet_payload,
payload_size)) {
@ -739,7 +745,7 @@ gst_rtp_buffer_get_extension_data (GstBuffer * buffer, guint16 * bits,
*
* Returns: True if done.
*
* Since : 0.10.18
* Since: 0.10.18
*/
gboolean
gst_rtp_buffer_set_extension_data (GstBuffer * buffer, guint16 bits,

View file

@ -56,8 +56,8 @@ gir_headers=$(patsubst %,$(srcdir)/%, $(libgstrtspinclude_HEADERS))
gir_headers+=$(patsubst %,$(builddir)/%, $(nodist_libgstrtspinclude_HEADERS))
gir_sources=$(patsubst %,$(srcdir)/%, $(libgstrtsp_@GST_MAJORMINOR@_la_SOURCES))
gir_sources+=$(patsubst %,$(builddir)/%, $(nodist_libgstrtsp_@GST_MAJORMINOR@_la_SOURCES))
gir_cincludes=$(patsubst %,--c-include='gst/audio/%',$(libgstrtspinclude_HEADERS))
gir_cincludes+=$(patsubst %,--c-include='gst/audio/%',$(nodist_libgstrtspinclude_HEADERS))
gir_cincludes=$(patsubst %,--c-include='gst/rtsp/%',$(libgstrtspinclude_HEADERS))
gir_cincludes+=$(patsubst %,--c-include='gst/rtsp/%',$(nodist_libgstrtspinclude_HEADERS))
GstRtsp-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstrtsp-@GST_MAJORMINOR@.la
$(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \
@ -90,7 +90,8 @@ typelibsdir = $(libdir)/girepository-1.0/
typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib)
%.typelib: %.gir $(INTROSPECTION_COMPILER)
$(AM_V_GEN)$(INTROSPECTION_COMPILER) \
$(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \
$(INTROSPECTION_COMPILER) \
--includedir=$(srcdir) \
--includedir=$(builddir) \
--includedir=$(builddir)/../sdp \

View file

@ -96,6 +96,9 @@ typedef enum {
#define GST_TYPE_RTSP_LOWER_TRANS (gst_rtsp_lower_trans_get_type())
GType gst_rtsp_lower_trans_get_type (void);
typedef struct _GstRTSPRange GstRTSPRange;
typedef struct _GstRTSPTransport GstRTSPTransport;
/**
* GstRTSPRange:
* @min: minimum value of the range
@ -103,10 +106,11 @@ GType gst_rtsp_lower_trans_get_type (void);
*
* A type to specify a range.
*/
typedef struct _GstRTSPRange {
struct _GstRTSPRange {
gint min;
gint max;
} GstRTSPRange;
};
/**
* GstRTSPTransport:
@ -128,7 +132,8 @@ typedef struct _GstRTSPRange {
*
* A structure holding the RTSP transport values.
*/
typedef struct _GstRTSPTransport {
struct _GstRTSPTransport {
GstRTSPTransMode trans;
GstRTSPProfile profile;
GstRTSPLowerTrans lower_transport;
@ -151,7 +156,7 @@ typedef struct _GstRTSPTransport {
/* RTP specific */
guint ssrc;
} GstRTSPTransport;
};
GstRTSPResult gst_rtsp_transport_new (GstRTSPTransport **transport);
GstRTSPResult gst_rtsp_transport_init (GstRTSPTransport *transport);

View file

@ -341,3 +341,76 @@ gst_rtsp_url_get_request_uri (const GstRTSPUrl * url)
return uri;
}
static int
hex_to_int (gchar c)
{
if (c >= '0' && c <= '9')
return c - '0';
else if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
else if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
else
return -1;
}
static void
unescape_path_component (gchar * comp)
{
guint len = strlen (comp);
guint i;
for (i = 0; i + 2 < len; i++)
if (comp[i] == '%') {
int a, b;
a = hex_to_int (comp[i + 1]);
b = hex_to_int (comp[i + 2]);
/* The a||b check is to ensure that the byte is not '\0' */
if (a >= 0 && b >= 0 && (a || b)) {
comp[i] = (gchar) (a * 16 + b);
memmove (comp + i + 1, comp + i + 3, len - i - 3);
len -= 2;
comp[len] = '\0';
}
}
}
/**
* gst_rtsp_url_decode_path_components:
* @url: a #GstRTSPUrl
*
* Splits the path of @url on '/' boundaries, decoding the resulting components,
*
* The decoding performed by this routine is "URI decoding", as defined in RFC
* 3986, commonly known as percent-decoding. For example, a string "foo%2fbar"
* will decode to "foo/bar" -- the %2f being replaced by the corresponding byte
* with hex value 0x2f. Note that there is no guarantee that the resulting byte
* sequence is valid in any given encoding. As a special case, %00 is not
* unescaped to NUL, as that would prematurely terminate the string.
*
* Also note that since paths usually start with a slash, the first component
* will usually be the empty string.
*
* Returns: a string vector. g_strfreev() after usage.
*
* Since: 0.10.32
*/
gchar **
gst_rtsp_url_decode_path_components (const GstRTSPUrl * url)
{
gchar **ret;
guint i;
g_return_val_if_fail (url != NULL, NULL);
g_return_val_if_fail (url->abspath != NULL, NULL);
ret = g_strsplit (url->abspath, "/", -1);
for (i = 0; ret[i]; i++)
unescape_path_component (ret[i]);
return ret;
}

View file

@ -92,6 +92,8 @@ GstRTSPResult gst_rtsp_url_parse (const gchar *urlstr, GstRTSPUrl
GstRTSPUrl* gst_rtsp_url_copy (const GstRTSPUrl *url);
void gst_rtsp_url_free (GstRTSPUrl *url);
gchar* gst_rtsp_url_get_request_uri (const GstRTSPUrl *url);
gchar** gst_rtsp_url_decode_path_components
(const GstRTSPUrl *url);
GstRTSPResult gst_rtsp_url_set_port (GstRTSPUrl *url, guint16 port);
GstRTSPResult gst_rtsp_url_get_port (const GstRTSPUrl *url, guint16 *port);

View file

@ -16,7 +16,7 @@ BUILT_GIRSOURCES = GstSdp-@GST_MAJORMINOR@.gir
gir_headers=$(patsubst %,$(srcdir)/%, $(libgstsdpinclude_HEADERS))
gir_sources=$(patsubst %,$(srcdir)/%, $(libgstsdp_@GST_MAJORMINOR@_la_SOURCES))
gir_cincludes=$(patsubst %,--c-include='gst/audio/%',$(libgstsdpinclude_HEADERS))
gir_cincludes=$(patsubst %,--c-include='gst/sdp/%',$(libgstsdpinclude_HEADERS))
GstSdp-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstsdp-@GST_MAJORMINOR@.la
$(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \
@ -45,7 +45,8 @@ typelibsdir = $(libdir)/girepository-1.0/
typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib)
%.typelib: %.gir $(INTROSPECTION_COMPILER)
$(AM_V_GEN)$(INTROSPECTION_COMPILER) \
$(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \
$(INTROSPECTION_COMPILER) \
--includedir=$(srcdir) \
--includedir=$(builddir) \
--includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \

Some files were not shown because too many files have changed in this diff Show more