mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-04 09:42:19 +00:00
Merge branch 'master' into 0.11
Conflicts: configure.ac gst-libs/gst/pbutils/Makefile.am
This commit is contained in:
commit
c6dd11981d
231 changed files with 15783 additions and 2864 deletions
129
NEWS
129
NEWS
|
@ -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:
|
||||
|
||||
|
|
405
RELEASE
405
RELEASE
|
@ -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
2
common
|
@ -1 +1 @@
|
|||
Subproject commit 011bcc8a0fc7f798ee874a7ba899123fb2470e22
|
||||
Subproject commit 1de7f6ab2d4bc1af69f06079cf0f4e2cbbfdc178
|
33
configure.ac
33
configure.ac
|
@ -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
|
||||
|
|
|
@ -12,7 +12,6 @@ SUBDIRS = design libs $(PLUGIN_DOCS_DIRS)
|
|||
DIST_SUBDIRS = design libs plugins
|
||||
|
||||
EXTRA_DIST = \
|
||||
design-audiosinks.txt \
|
||||
version.entities.in
|
||||
|
||||
upload:
|
||||
|
|
|
@ -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 \
|
||||
|
|
571
docs/design/design-encoding.txt
Normal file
571
docs/design/design-encoding.txt
Normal 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
|
||||
|
|
@ -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">
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
46
docs/plugins/inspect/plugin-encoding.xml
Normal file
46
docs/plugins/inspect/plugin-encoding.xml
Normal 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 <edward.hervey@collabora.co.uk></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>
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<description>elements to read from and write to Gnome-VFS uri'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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 <wim.taymans@chello.be></author>
|
||||
<pads>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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)) {
|
||||
if (pad->data_pushed) {
|
||||
GST_LOG_OBJECT (pad->collect.pad, "got discont");
|
||||
packet.packetno++;
|
||||
/* No public API for this; hack things in */
|
||||
pad->stream.pageno++;
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
if (granule == -1) {
|
||||
stream->stored_buffers = g_list_append (stream->stored_buffers,
|
||||
pagebuffer);
|
||||
} else {
|
||||
if (stream->stored_buffers) {
|
||||
int j;
|
||||
|
||||
result = gst_pad_push (ogg->srcpad, GST_BUFFER (pagebuffer));
|
||||
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;
|
||||
} else {
|
||||
/* Normal data page, submit buffer */
|
||||
}
|
||||
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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -53,6 +53,7 @@ struct _GstOggStream
|
|||
/* for oggparse */
|
||||
gboolean in_headers;
|
||||
GList *unknown_pages;
|
||||
GList *stored_buffers;
|
||||
|
||||
gint map;
|
||||
gboolean is_skeleton;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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_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;
|
||||
|
|
|
@ -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@ \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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@` \
|
||||
|
|
|
@ -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@` \
|
||||
|
|
|
@ -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@` \
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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:
|
||||
*
|
||||
* <itemizedlist>
|
||||
* <listitem><para>
|
||||
* 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).
|
||||
* </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
|
||||
*/
|
||||
|
|
|
@ -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 */
|
||||
|
|
966
gst-libs/gst/pbutils/encoding-profile.c
Normal file
966
gst-libs/gst/pbutils/encoding-profile.c
Normal 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;
|
||||
}
|
187
gst-libs/gst/pbutils/encoding-profile.h
Normal file
187
gst-libs/gst/pbutils/encoding-profile.h
Normal 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__ */
|
1204
gst-libs/gst/pbutils/encoding-target.c
Normal file
1204
gst-libs/gst/pbutils/encoding-target.c
Normal file
File diff suppressed because it is too large
Load diff
147
gst-libs/gst/pbutils/encoding-target.h
Normal file
147
gst-libs/gst/pbutils/encoding-target.h
Normal 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__ */
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
*
|
||||
* 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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1222,7 +1330,7 @@ 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,7 +1348,9 @@ 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 */
|
||||
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);
|
||||
}
|
||||
|
@ -1278,7 +1388,8 @@ 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
|
||||
|
@ -1311,13 +1422,15 @@ 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: see #GstDiscovererInfo. The caller must unref this structure after use.
|
||||
* Returns: (transfer full): the result of the scanning. Can be %NULL if an
|
||||
* error occurred.
|
||||
*
|
||||
* Since: 0.10.31
|
||||
*/
|
||||
|
@ -1369,8 +1482,8 @@ 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().
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -78,6 +78,7 @@ struct _GstDiscovererInfo {
|
|||
GstClockTime duration;
|
||||
GstStructure *misc;
|
||||
GstTagList *tags;
|
||||
gboolean seekable;
|
||||
};
|
||||
|
||||
/* missing-plugins.c */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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'),
|
||||
|
|
|
@ -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@` \
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
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);
|
||||
|
||||
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");
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue