Projects
Essentials
gstreamer-plugins-bad-codecs
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 33
View file
gstreamer-plugins-bad-codecs.changes
Changed
@@ -1,4 +1,9 @@ ------------------------------------------------------------------- +Wed May 7 07:44:22 UTC 2025 - Bjørn Lie <zaitor@opensuse.org> + +- Update to version 1.26.1 + +------------------------------------------------------------------- Wed Mar 12 19:35:43 UTC 2025 - Bjørn Lie <zaitor@opensuse.org> - Update to version 1.26.0
View file
gstreamer-plugins-bad-codecs.spec
Changed
@@ -7,7 +7,7 @@ %define _version 1.26.0 Name: gstreamer-plugins-bad-codecs -Version: 1.26.0 +Version: 1.26.1 Release: 0 Summary: Codecs/plugins for gstreamer-plugins-bad License: LGPL-2.1-or-later
View file
_service
Changed
@@ -2,7 +2,7 @@ <service name="download_url"> <param name="host">gstreamer.freedesktop.org</param> <param name="protocol">https</param> - <param name="path">/src/gst-plugins-bad/gst-plugins-bad-1.26.0.tar.xz</param> + <param name="path">/src/gst-plugins-bad/gst-plugins-bad-1.26.1.tar.xz</param> </service> <service name="set_version" mode="buildtime"/> </services>
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ChangeLog -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ChangeLog
Changed
@@ -1,3 +1,706 @@ +=== release 1.26.1 === + +2025-04-24 20:20:14 +0100 Tim-Philipp Müller <tim@centricular.com> + + * NEWS: + * RELEASE: + * gst-plugins-bad.doap: + * meson.build: + Release 1.26.1 + +2025-03-15 23:48:52 +0900 Seungha Yang <seungha@centricular.com> + + * gst-libs/gst/codecparsers/gsth265parser.c: + h265parser: Fix num_long_term_pics bound check + As defined in the spec 7.4.7.1, calculates allowed maximum + value of num_long_term_pics + Fixes ZDI-CAN-26596 + Fixes: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/4285 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8885> + +2025-03-15 22:39:44 +0900 Seungha Yang <seungha@centricular.com> + + * gst-libs/gst/codecparsers/gsth265parser.c: + h265parser: Fix max_dec_pic_buffering_minus1 bound check + Allowed max value is MaxDpbSize - 1 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8885> + +2025-04-17 17:28:17 +0200 Stéphane Cerveau <scerveau@igalia.com> + + * sys/va/gstvaav1enc.c: + vaav1enc: fix mem leaks in _av1_decide_profile + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8876> + +2025-04-15 16:46:23 +0200 Stéphane Cerveau <scerveau@igalia.com> + + * sys/va/gstvavp9enc.c: + vavp9enc: fix mem leaks in _vp9_decide_profile + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8876> + +2025-04-23 09:28:16 +0300 Sebastian Dröge <sebastian@centricular.com> + + * sys/aja/plugin.cpp: + aja: Use the correct location of the AJA NTV2 SDK in the docs + Also there is no longer a proprietary version of it. + Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/4381 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8875> + +2025-04-21 22:59:18 +0200 Jakub Adam <jakub.adam@collabora.com> + + * sys/va/gstvavpp.c: + vapostproc: fix wrong video orientation after restarting the element + After READY -> NULL -> READY state change, the configured video + orientation didn't get applied on the new GstVaFilter instance. + Resettig prev_direction to default value in update_properties ensures + gst_va_filter_set_orientation() isn't inadvertently skipped. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8872> + +2025-04-17 04:40:12 -0600 Jordan Yelloz <jordan.yelloz@collabora.com> + + * gst-libs/gst/mse/gstsourcebuffer.c: + gstsourcebuffer: Reverted ownership change for append method + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8864> + +2025-04-16 21:17:07 +0900 Seungha Yang <seungha@centricular.com> + + * gst-libs/gst/d3d12/gstd3d12converter.cpp: + d3d12converter: Fix cropping when automatic mipmap is enabled + Update vertex buffer and viewport of extra shader pipeline as well + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8853> + +2025-04-10 15:44:54 -0400 Daniel Morin <daniel.morin@collabora.com> + + * docs/plugins/gst_plugins_cache.json: + * gst/tensordecoders/gstssdobjectdetector.c: + tensordecoders: updating element classification + - `TensorDecoder` is clashing with media decoder which cause decodebin use it. + Replacing with `Tensordecoder` to avoid clash + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8839> + +2025-04-10 14:23:59 +0200 Carlos Bentzen <cadubentzen@igalia.com> + + * gst-libs/gst/codecs/gsth266decoder.c: + h266decoder: fix leak parsing SEI messages + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8817> + +2025-04-08 15:08:11 -0400 Detlev Casanova <detlev.casanova@collabora.com> + + * sys/v4l2codecs/gstv4l2codech264dec.c: + * sys/v4l2codecs/gstv4l2codech265dec.c: + * sys/v4l2codecs/gstv4l2codecmpeg2dec.c: + v4l2codecs: Unref the frame before leaving on error + In h264, h265 and mpeg2, make sure that dec_submit_bitstream() doesn't leak + a frame when dec_ensure_output_buffer() fails. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8804> + +2025-04-08 09:30:31 -0400 Detlev Casanova <detlev.casanova@collabora.com> + + * sys/v4l2codecs/gstv4l2codecav1dec.c: + * sys/v4l2codecs/gstv4l2codecvp9dec.c: + v4l2codecs: av1,vp9: Use temporary variable for buffer + This makes the end_picture() function handle the frame in the same way + as in vp8, which also fixes a frame leak when + gst_buffer_pool_acquire_buffer() fails. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8804> + +2025-04-09 09:01:22 -0400 Xavier Claessens <xclaessens@netflix.com> + + * sys/va/meson.build: + Revert "va: h266 requires libva 2.22.0" + This reverts commit 8c017c79c5736c9e45e635df210e08550287646d. + 1.22 was the correct pkg-config version. It's only the subproject + version that was wrong. Since we bumped libva.wrap to 2.22 version, h266 + is now always available when using the subproject. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8802> + +2025-04-07 17:45:28 -0400 Xavier Claessens <xclaessens@netflix.com> + + * sys/va/meson.build: + va: h266 requires libva 2.22.0 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8793> + +2025-04-04 12:18:24 +0200 Guillaume Desmottes <guillaume.desmottes@onestream.live> + + * gst/codecalpha/gstalphacombine.c: + alphacombine: unblock when alpha sink is eos + If the alpha sink receives EOS while the other thread was waiting for a + alpha buffer it was stuck waiting forever. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8790> + +2025-04-02 09:58:26 +0200 Guillaume Desmottes <guillaume.desmottes@onestream.live> + + * gst/codecalpha/gstalphadecodebin.c: + * sys/v4l2codecs/gstv4l2codecalphadecodebin.c: + * sys/va/gstvacodecalphadecodebin.c: + alphadecodebin: use a multiqueue instead of a couple of queues + Fix gapless playback as queues are no longer stopped after the first + eos. + Co-authored-by: Nicolas Dufresne <nicolas.dufresne@collabora.com> + Fix #4165 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8790> + +2025-03-30 13:04:12 +0300 Razvan Grigore <razvan.grigore@vampirebyte.ro> + + * ext/webrtc/gstwebrtcbin.c: + webrtcbin: add missing warning for caps missmatch + This helps debug cases when the remote is offerer and m-line does not match with already existing transceivers. + In this case, it will create new ones with sendrecv direction without any warning. + Similar with code from _create_answer_task + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8784> + +2025-04-03 16:30:52 -0400 Olivier Crête <olivier.crete@collabora.com> + + * docs/plugins/gst_plugins_cache.json: + bad: Update va docs, adding new elements + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8778> + +2025-04-04 12:54:27 -0400 Olivier Crête <olivier.crete@collabora.com> + + * sys/va/gstvacodecalphadecodebin.h: + * sys/va/gstvafilter.c: + * sys/va/gstvavpp.c: + * sys/va/meson.build: + va: Add since markers + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8778> + +2025-04-04 13:20:35 -0400 Olivier Crête <olivier.crete@collabora.com> + + * docs/plugins/gst_plugins_cache.json: + * sys/va/gstvaav1enc.c: + * sys/va/gstvah265enc.c: + * sys/va/gstvavp8enc.c: + * sys/va/gstvavp9enc.c: + va: Remove GstVaFeature marking as a plugin API + It's part of the libgstva library and it's documented there, no need + to duplicate it as it confuses hotdoc. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8778> + +2025-04-03 17:39:45 -0400 Olivier Crête <olivier.crete@collabora.com> + + * sys/va/gstvah264enc.c: + * sys/va/gstvah265enc.c: + * sys/va/gstvavp8dec.c: + * sys/va/gstvavp9dec.c: + va: Add doc section for vah26xlpenc and codecalpha element + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8778> + +2025-04-03 16:31:30 -0400 Olivier Crête <olivier.crete@collabora.com> + + * docs/plugins/gst_plugins_cache.json: + bad: Update wpesrc docs + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8778> + +2025-04-03 17:45:57 -0400 Olivier Crête <olivier.crete@collabora.com> + + * ext/wpe/gstwpevideosrc.cpp: + wpevideosrc: Fix typo in doc + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8778> + +2025-04-03 16:22:08 -0400 Olivier Crête <olivier.crete@collabora.com> + + * docs/plugins/gst_plugins_cache.json: + bad: Update qsv docs + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8778> + +2025-04-04 13:20:09 -0400 Olivier Crête <olivier.crete@collabora.com> + + * sys/qsv/gstqsvdecoder.cpp: + * sys/qsv/gstqsvencoder.cpp: + qsv: Add since marker to device-path property + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8778> + +2025-04-03 16:07:20 -0400 Olivier Crête <olivier.crete@collabora.com> + + * docs/plugins/gst_plugins_cache.json: + * ext/onnx/gstonnx.c: + * ext/onnx/gstonnxclient.h: + * ext/onnx/gstonnxinference.cpp: + bad: Add onnxinference to the docs + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8778> + +2025-04-01 16:10:52 +0530 Nirbheek Chauhan <nirbheek@centricular.com> + + * gst-libs/gst/webrtc/ice.c: + * gst-libs/gst/webrtc/icestream.c: + docs: Fix GstWebRTCICE* class documentation + IceStream is not an actual object, it's GstWebRTCICEStream + Some `Returns:` annotations were improperly formatted and not taking + effect. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8771> + +2025-04-03 09:54:19 -0400 Xavier Claessens <xclaessens@netflix.com> + + * gst/unixfd/gstunixfdsrc.c: + unixfd: Fix wrong memory size when offset > 0 + This is a backport of !8025 that does not require new API. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8770> + +2024-09-10 01:13:25 +0200 Michael Grzeschik <m.grzeschik@pengutronix.de> + + * sys/uvcgadget/gstuvcsink.c: + * sys/uvcgadget/gstuvcsink.h: + * sys/uvcgadget/uvc.c: + uvcsink: Respond to control requests with proper error handling + The complete handling on the control interface is currently dead. + We return with EOPNOTSUPP for the caller to know that a response + to such requests is not valid. The host however may ask + control interface why these control requests were not available. + For this the UVC_VC_REQUEST_ERROR_CODE_CONTROL is used. As an overall + exception for the control interface we just always return 0x06 as + an response which is representing "not implemented". + This patch is a necessary feature to properly pass the UVC Functionality + Test of the USB3CV Compliance Software. + Fixes: 69c17461392d ('uvcgadget: Properly implement GET_INFO control responses') + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8760> + +2025-03-31 18:54:28 +0200 Piotr Brzeziński <piotr@centricular.com> + + * sys/applemedia/avfvideosrc.m: + avfvideosrc: Guess reasonable framerate values for some 3rd party devices + For some third-party devices macOS sometimes reports silly framerates, + like 750003/6250 instead of 120/1. To avoid users having to exactly + pecify those values, we instead report the closest reasonable value in + caps. If it ends up being chosen, the additional logic in + setDeviceCaps() will reverse that process and pass the actual supported + value back to AVF, as most often the rounding causes us to fall just + outside the accepted threshold. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8756> + +2025-03-31 21:56:51 +0900 Seungha Yang <seungha@centricular.com> + + * ext/closedcaption/gsth264ccextractor.c: + * ext/closedcaption/gsth265ccextractor.c: + h264ccextractor,h265ccextractor: Handle gap with unknown pts + Fixing critical warngins + gst_event_new_gap: assertion 'GST_CLOCK_TIME_IS_VALID (timestamp)' failed + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8752> + +2025-02-18 14:12:49 -0700 Jordan Yelloz <jordan.yelloz@collabora.com> + + * docs/plugins/gst_plugins_cache.json: + mse: Updated documentation cache + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8751> + +2025-02-18 13:08:38 -0700 Jordan Yelloz <jordan.yelloz@collabora.com> + + * gst-libs/gst/mse/gstmsesrc-private.h: + * gst-libs/gst/mse/gstmsesrc.c: + gstmsesrc: Added locking, improved seek implementation + The position is no longer duplicated across each pad and pad's segment. The + position is now only updated if it changes in the direction of playback so that + quickly repeated forward seeks do not cause the stream to seek from 0. + Reverse playback is expressly disallowed and an unnecessary extra flush of track + when seeking was removed. + A background task was added to periodically check on the current position and + the media source's buffering levels to keep the ready state up-to-date. The + source buffer no longer needs to trigger this update, it will happen whenever + the element state is READY or higher. + Finally, added proper error reporting when failing to push a buffer and improved + debug logging. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8751> + +2025-02-18 13:08:38 -0700 Jordan Yelloz <jordan.yelloz@collabora.com> + + * gst-libs/gst/mse/gstappendpipeline.c: + gstappendpipeline: Added name to background task + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8751> + +2025-02-18 13:08:37 -0700 Jordan Yelloz <jordan.yelloz@collabora.com> + + * gst-libs/gst/mse/gstsourcebufferlist.c: + gstsourcebufferlist: Added locking + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8751> + +2025-02-18 13:08:37 -0700 Jordan Yelloz <jordan.yelloz@collabora.com> + + * gst-libs/gst/mse/gstsourcebuffer.c: + gstsourcebuffer: Added locking, re-worked track feed task + Since the sample map/track buffer now iterates samples in batches corresponding + to each coded frame group, the logic to feed the tracks is simpler. For media + without delta frames, it's a special case where the coded frame groups are all + size 1. + Now, all it does is skip data until the keyframe group containing the seek point + is found, then feed the track queue with the current sample and all future + samples until EOS or cancellation. + Resync of the iterator when the underlying track is modified is not necessary + because the outer loop attempts to resume feeding track data from where it was + interrupted in case of modification. + Also, the track feed task struct now holds a weak ref to its parent source + buffer to allow the task to cancel itself in any situation where the source + buffer is destroyed before the task is shut down. + Media parsing activity in the append pipeline no longer triggers ready state + recalculation on the msesrc since the msesrc now has a background task that + updates the ready state periodically when it's active which is more efficient in + cases where there is a high volume of samples being processed by the media + parser. + Finally, updated to adapt to track buffer API changes. Some functions previously + passed in a lower bound for sample timestamps. Now the source buffer is + responsible for clipping samples within a desired range of time. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8751> + +2025-02-18 13:08:37 -0700 Jordan Yelloz <jordan.yelloz@collabora.com> + + * gst-libs/gst/mse/gstsourcebuffer.c: + gstsourcebuffer: Added name to track feed task + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8751> + +2025-02-18 13:08:37 -0700 Jordan Yelloz <jordan.yelloz@collabora.com> + + * gst-libs/gst/mse/gstsourcebuffer.c: + gstsourcebuffer: Moved misplaced documentation comment + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8751> + +2025-02-18 13:08:37 -0700 Jordan Yelloz <jordan.yelloz@collabora.com> + + * gst-libs/gst/mse/gstmediasourcetrackbuffer.c: + * tests/check/libs/mse.c: + gstmediasourcetrackbuffer: Improved buffered ranges calculation + Now when the buffered list is requested, the tolerance for merging two ranges + when there's a small gap between them is MAX(0.1sec, max frame duration * 2). + Previously it was hardcoded to 0.01sec. The specification suggests that it + could be something like the max frame duration * 2. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8751> + +2025-02-18 13:08:37 -0700 Jordan Yelloz <jordan.yelloz@collabora.com> + + * gst-libs/gst/mse/gstmediasourcetrackbuffer-private.h: + * gst-libs/gst/mse/gstmediasourcetrackbuffer.c: + gstmediasourcetrackbuffer: Added method to wait until any new data + The source buffer currently has a thread for each track that feeds the track + with all data in the track buffer until EOS is reached. + Each pass over the track buffer currently waits for the EOS to appear when it's + done iterating the track buffer which is too restrictive. + When the source buffer reaches the end of the track buffer, it should wait for + any new data to be processed -- not just an EOS -- then check for cancellation + if the deadline expires without new data. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8751> + +2025-02-18 13:08:37 -0700 Jordan Yelloz <jordan.yelloz@collabora.com> + + * gst-libs/gst/mse/gstmediasourcetrackbuffer-private.h: + * gst-libs/gst/mse/gstmediasourcetrackbuffer.c: + gstmediasourcetrackbuffer: Removed start time filtering from sample iterator + This adapts to the changes to the sample map since gst_iterator_filter() is a + simpler way for callers to clip the returned samples to a desired time range. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8751> + +2025-02-18 13:08:37 -0700 Jordan Yelloz <jordan.yelloz@collabora.com> + + * gst-libs/gst/mse/gstmediasourcetrackbuffer-private.h: + * gst-libs/gst/mse/gstmediasourcetrackbuffer.c: + gstmediasourcetrackbuffer: Removed unused code + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8751> + +2025-02-18 13:08:37 -0700 Jordan Yelloz <jordan.yelloz@collabora.com> + + * gst-libs/gst/mse/gstmediasourcetrack-private.h: + * gst-libs/gst/mse/gstmediasourcetrack.c: + * tests/check/libs/mse.c: + gstmediasourcetrack: Removed unused try_push() method + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8751> + +2025-02-18 13:08:37 -0700 Jordan Yelloz <jordan.yelloz@collabora.com> + + * gst-libs/gst/mse/gstmediasourcetrack.c: + * tests/check/libs/mse.c: + gstmediasourcetrack: Ref the sample inside push() method + This simplifies cleanup for the caller since the push method already cleans up + the sample when it is consumed by playback or if it fails to be added to the + queue. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8751> + +2025-02-18 13:08:37 -0700 Jordan Yelloz <jordan.yelloz@collabora.com> + + * gst-libs/gst/mse/gstmediasourcesamplemap-private.h: + * gst-libs/gst/mse/gstmediasourcesamplemap.c: + * tests/check/libs/mse.c: + gstmediasourcesamplemap: Re-worked sample iteration and removal + Both operations now work on coded frame groups (GOPs). This simplifies queueing + of video data. There is rarely any point of dealing with individual video frames + when iterating in DTS order, it's most meaningful to decode or delete whole + coded frame groups at a time, so the sample map will now do that when iterating + by DTS. When iterating in PTS order, the existing behavior is preserved since + that is used for informational purposes, not media processing. + A new private boxed type for coded frame groups was added to provide each data + item to the source buffer. Another possible solution would be creation of a new + GstSample representing the whole group by merging all the samples in a group + into a single sample containing a GstBufferList. + Also, start time filtering was removed from the API since gst_iterator_filter() + can be used by callers to achieve the same result. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8751> + +2025-02-18 13:08:37 -0700 Jordan Yelloz <jordan.yelloz@collabora.com> + + * gst-libs/gst/mse/gstmediasource.c: + gstmediasource: Added locking + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8751> + +2025-02-18 13:08:37 -0700 Jordan Yelloz <jordan.yelloz@collabora.com> + + * gst-libs/gst/mse/gstmediasource.c: + gstmediasource: Added caller-allocates annotation to get_live_seekable_range() + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8751> + +2025-02-18 13:08:37 -0700 Jordan Yelloz <jordan.yelloz@collabora.com> + + * gst-libs/gst/mse/gstmselogging-private.h: + * gst-libs/gst/mse/gstmselogging.c: + gstmselogging: Added helper function to get nicknames of enum values + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8751> + +2025-03-27 15:38:42 +0100 Guillaume Desmottes <guillaume.desmottes@onestream.live> + + * gst/codecalpha/gstalphadecodebin.c: + codecalpha: name both queues + Make it easier to debug from logs. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8750> + +2025-03-21 11:41:11 +0900 Dongyun Seo <dongyun.seo@lge.com> + + * gst-libs/gst/vulkan/gstvkformat.c: + vkformat: fix build error + fix build error when VK_KHR_format_feature_flags2 is not defined. + Co-authored-by: Victor Jaquez vjaquez@igalia.com + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8749> + +2025-03-25 03:04:52 +0900 Seungha Yang <seungha@centricular.com> + + * ext/closedcaption/gstcodecccinserter.c: + codecccinserter: Fix event double free + Need to steal GstVideoCodecFrame.events before unref + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8707> + +2025-03-25 03:02:57 +0900 Seungha Yang <seungha@centricular.com> + + * ext/closedcaption/gsth265reorder.c: + h265ccinserter: Fix broken SPS/PPS link + Apply the same h265decoder change to h265ccinserter + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8707> + +2025-03-25 02:09:49 +0900 Seungha Yang <seungha@centricular.com> + + * gst-libs/gst/codecs/gsth265decoder.c: + h265decoder: Fix broken SPS/PPS link + Because of 2 pass nalu handling in decoder, link between + slice header and SPS/PPS can be broken at the second pass + if SPS/PPS got updated after slice header in the same AU + Fixes: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/4323 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8707> + +2025-03-25 02:41:29 +0900 Seungha Yang <seungha@centricular.com> + + * gst-libs/gst/codecparsers/gsth265parser-private.h: + * gst-libs/gst/codecparsers/gsth265parser.c: + h265parser: Add private method to update slice header + Adding a method to allow linking already parsed slice header + with parser's own sps/pps + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8707> + +2025-03-25 01:58:42 +0900 Seungha Yang <seungha@centricular.com> + + * gst-libs/gst/codecparsers/gsth265parser.c: + h265parser: Allow updating SPS/PPS without parent parameter set + h265parser defers linking parameter sets until slice header is parsed. + Thus valid SPS/PPS parsed by h265parser can have no linked + parent parameter set. Apply this behavior to + gst_h265_parser_update_{sps,pps} too + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8707> + +2025-03-29 19:03:13 +0200 Artem Martus <artemmartus2012@gmail.com> + + * ext/webrtc/gstwebrtcbin.c: + * tests/check/elements/webrtcbin.c: + webrtcbin: ensure RTX entry for all formats + Properly implement RFC 4588 by ensuring each media format + has its own RTX payload type with unique 'apt' parameter, + rather than only mapping the first format. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8742> + +2025-03-30 13:10:42 +0300 Sebastian Dröge <sebastian@centricular.com> + + * sys/va/gstvacaps.c: + va: Skip codecs that report maximum width or height lower than minimum + This happens on F42 with the JPEG decoders for some reason and trying to + actually use them with any resolution simply gives a "resolution not supported" + error. + A minimum of 64 is correctly reported though and trying to create caps with an + int range of 64, 0 gives critical warnings. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8737> + +2025-03-14 22:03:53 -0400 Doug Nazar <nazard@nazar.ca> + + * sys/bluez/gsta2dpsink.c: + a2dpsink: Free various props during cleanup + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8714> + +2025-03-14 22:01:44 -0400 Doug Nazar <nazard@nazar.ca> + + * sys/aja/gstajasink.cpp: + * sys/aja/gstajasrc.cpp: + aja: Free various props during cleanup + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8714> + +2025-03-14 22:01:05 -0400 Doug Nazar <nazard@nazar.ca> + + * gst/librfb/gstrfbsrc.c: + * gst/librfb/rfbdecoder.c: + rfbsrc: Free various props before being set & during cleanup + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8714> + +2025-03-14 21:59:13 -0400 Doug Nazar <nazard@nazar.ca> + + * gst/frei0r/gstfrei0r.c: + frei0r: Free various props before being set + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8714> + +2025-03-14 21:58:14 -0400 Doug Nazar <nazard@nazar.ca> + + * gst/faceoverlay/gstfaceoverlay.c: + faceoverlay: Free various props during cleanup + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8714> + +2025-03-14 19:38:54 -0400 Doug Nazar <nazard@nazar.ca> + + * ext/wayland/gstwaylandsink.c: + waylandsink: Free various props before being set + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8714> + +2025-03-14 19:38:03 -0400 Doug Nazar <nazard@nazar.ca> + + * ext/qroverlay/gstdebugqroverlay.c: + * ext/qroverlay/gstqroverlay.c: + qroverlay: Free various props before set & during cleanup + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8714> + +2025-03-14 19:37:39 -0400 Doug Nazar <nazard@nazar.ca> + + * ext/openal/gstopenalsrc.c: + openalsrc: Free various props before being set + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8714> + +2025-03-14 19:35:49 -0400 Doug Nazar <nazard@nazar.ca> + + * ext/lcevcencoder/gstlcevcencoder.c: + lcevcencoder: Free various props before during cleanup + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8714> + +2025-03-14 19:25:48 -0400 Doug Nazar <nazard@nazar.ca> + + * ext/dash/gstmpdadaptationsetnode.c: + * ext/dash/gstmpdperiodnode.c: + * ext/dash/gstmpdrepresentationbasenode.c: + * ext/dash/gstmpdrepresentationnode.c: + * ext/dash/gstmpdsegmenttemplatenode.c: + * ext/dash/gstmpdsegmenturlnode.c: + dash: Free various props before set & during cleanup + In addition several members were being freed via xmlFree() even though + being created via g_value_dup_string(). Switch to g_free(). + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8714> + +2025-03-14 19:22:20 -0400 Doug Nazar <nazard@nazar.ca> + + * ext/curl/gstcurlhttpsrc.c: + curlhttpsrc: Free various props before set & during cleanup + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8714> + +2025-03-14 19:14:43 -0400 Doug Nazar <nazard@nazar.ca> + + * ext/gtk/gstgtkwaylandsink.c: + * gst-libs/gst/mse/gstmediasourcetrack.c: + * gst-libs/gst/va/gstvadisplay_drm.c: + * sys/directshow/dshowdeviceprovider.cpp: + * sys/directsound/gstdirectsounddevice.c: + * sys/mediafoundation/gstmfdevice.cpp: + * sys/uvch264/gstuvch264deviceprovider.c: + * sys/wasapi/gstwasapidevice.c: + * sys/wasapi2/gstwasapi2device.c: + * sys/winks/ksdeviceprovider.c: + all: Annotate *_set_property() contructor only props without free + Properties that are marked constructor only aren't required to be freed + before g_value_dup_string() as they can only be called once during construction. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8714> + +2025-03-23 00:19:50 +0100 Jan Tojnar <jtojnar@gmail.com> + + * gst-libs/gst/analytics/meson.build: + gst-analytics: Add gst-video to Requires in pkg-config + `gst/analytics/analytics.h` includes `gst/analytics/gstanalyticssegmentationmtd.h`, + which in turn `gst/video/video-info.h` but `gst-video-1.0` was only listed + in `Requires.private` field of `gst-analytics-1.0.pc`. + This would cause projects linking against `gst-analytics-1.0.pc` to fail to find + the headers when using alternative interpretation of pkg-config specification + that only considers private dependencies for include path during static builds, + such as the case e.g. on Nix. + https://gitlab.freedesktop.org/pkg-config/pkg-config/-/issues/28 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8708> + +2025-03-26 15:32:05 +0200 Sebastian Dröge <sebastian@centricular.com> + + * ext/dash/gstdashsink.c: + dashsink: Make sure to use a non-NULL pad name when requesting a pad from splitmuxsink + If the caller passed in "audio_%u" instead of a concrete pad name into + gst_element_request_pad_simple() then the pad name will be NULL. In that case + use the pad template name for requesting the pad from splitmuxsink. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8711> + +2025-03-13 16:27:44 +0100 Víctor Manuel Jáquez Leal <vjaquez@igalia.com> + + * ext/vulkan/vkh264dec.c: + * ext/vulkan/vkh265dec.c: + * ext/vulkan/vksink.c: + vulkan: fix memory leak at dynamic registering + Also it cleans up a bit the code. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8650> + +2025-03-13 17:22:12 +0100 Piotr Brzeziński <piotr@centricular.com> + + * sys/applemedia/vtenc.c: + vtenc: Reset restart flag when creating session in set_format() + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8644> + +2025-03-06 17:23:11 +0100 Piotr Brzeziński <piotr@centricular.com> + + * sys/applemedia/vtenc.c: + * sys/applemedia/vtenc.h: + vtenc: Avoid deadlocking when changing properties on the fly + VT supports changing properties on the fly, and old code attempted to + support that. Perhaps 10 years ago that worked, but these days + VTSessionSetProperty will always wait for the output callback to finish + before proceeding. This means that it's very prone to deadlocking, as + property setters will take the object lock, the callback thread will + take the stream lock, and the main (streaming) thread attempts to take + both, resulting in a deadlock. + New version uses something similar to other encoders (e.g. x264enc) - + changing a property when a session is already created will just flag it + to be reconfigured upon the next encode call. This is done in similar + fashion to how restarting the session upon an error works. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8644> + +2025-01-22 15:02:03 +0100 Marc Leeman <marc.leeman@gmail.com> + + * gst-libs/gst/cuda/meson.build: + meson.build: test for and link against libatomic if it exists + It's needed on some platforms for some subset (or all) atomic operations and + checking for the cases when it's actually needed is quite complex. + Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/4300 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8647> + +2025-03-08 12:07:11 +0000 Philippe Normand <philn@igalia.com> + + * gst/codecalpha/gstalphacombine.c: + alphacombine: De-couple flush-start/stop events handling + There is no guarantee that any FLUSH_STOP event is preceded by a FLUSH_START. + The element now stops flushing once it has received a FLUSH_STOP on all its sink + pads. + Fixes #4174 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8629> + +2025-03-11 20:23:16 +0000 Tim-Philipp Müller <tim@centricular.com> + + * meson.build: + Back to development after 1.26.0 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8618> + === release 1.26.0 === 2025-03-11 20:14:44 +0000 Tim-Philipp Müller <tim@centricular.com>
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/NEWS -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/NEWS
Changed
@@ -2,9 +2,11 @@ GStreamer 1.26.0 was originally released on 11 March 2025. +The latest bug-fix release in the stable 1.26 series is 1.26.1 and was released on 24 April 2025. + See https://gstreamer.freedesktop.org/releases/1.26/ for the latest version of this document. -Last updated: Tuesday 11 March 2025, 20:00 UTC (log) +Last updated: Thursday 24 April 2025, 16:00 UTC (log) ## Introduction @@ -34,7 +36,7 @@ - OpenGL integration improvements, esp. in glcolorconvert, gldownload, glupload - Qt5/Qt6 QML GL sinks now support direct DMABuf import from hardware decoders - CUDA: New compositor, Jetson NVMM memory support, stream-ordered allocator -- NVCODEC AV1 video encoder element, and ndsdewarp +- NVCODEC AV1 video encoder element, and nvdsdewarp - New Direct3D12 integration support library - New d3d12swapchainsink and d3d12deinterlace elements and D3D12 sink/source for zero-copy IPC - Decklink HDR support (PQ + HLG) and frame scheduling enhancements @@ -1259,6 +1261,26 @@ - GstBuffer now uses C11 atomics for 64 bit atomic operations if available, which may require linking to libatomic on some systems, but this is not done automatically yet, see issue #4177. +## Statistics + +- 4496 commits + +- 2203 Merge requests merged + +- 794 Issues closed + +- 215+ Contributors + +- ~33% of all commits and Merge Requests were in Rust modules/code + +- 4950 files changed + +- 515252 lines added + +- 201503 lines deleted + +- 313749 lines added (net) + Contributors Aaron Boxer, Adrian Perez de Castro, Adrien De Coninck, Alan Coopersmith, Albert Sjolund, Alexander Slobodeniuk, Alex Ashley, @@ -1297,6 +1319,255 @@ suitable for a stable branch, but no new features or intrusive changes will be added to a bug-fix release usually. The 1.26.x bug-fix releases will be made from the git 1.26 branch, which is a stable release series branch. +1.26.1 + +The first 1.26 bug-fix release (1.26.1) was released on 24 April 2025. + +This release only contains bugfixes and security fixes and it should be safe to update from 1.26.0. + +Highlighted bugfixes in 1.26.1 + +- awstranslate and speechmatics plugin improvements +- decodebin3 fixes and urisourcebin/playbin3 stability improvements +- Closed captions: CEA-708 generation and muxing fixes, and H.264/H.265 caption extractor fixes +- dav1d AV1 decoder: RGB support, plus colorimetry, renegotiation and buffer pool handling fixes +- Fix regression when rendering VP9 with alpha +- H.265 decoder base class and caption inserter SPS/PPS handling fixes +- hlssink3 and hlsmultivariantsink feature enhancements +- Matroska v4 support in muxer, seeking fixes in demuxer +- macOS: framerate guessing for cameras or capture devices where the OS reports silly framerates +- MP4 demuxer uncompressed video handling improvements and sample table handling fixes +- oggdemux: seeking improvements in streaming mode +- unixfdsrc: fix gst_memory_resize warnings +- Plugin loader fixes, especially for Windows +- QML6 GL source renegotiation fixes +- RTP and RTSP stability fixes +- Thread-safety improvements for the Media Source Extension (MSE) library +- v4l2videodec: fix A/V sync issues after decoding errors +- Various improvements and fixes for the fragmented and non-fragmented MP4 muxers +- Video encoder base class segment and buffer timestamp handling fixes +- Video time code support for 119.88 fps and drop-frames-related conversion fixes +- WebRTC: Retransmission entry creation fixes and better audio level header extension compatibility +- YUV4MPEG encoder improvments +- dots-viewer: make work locally without network access +- gst-python: fix compatibility with PyGObject >= 3.52.0 +- Cerbero: recipe updates, compatibility fixes for Python < 3.10; Windows Android cross-build improvements +- Various bug fixes, build fixes, memory leak fixes, and other stability and reliability improvements + +gstreamer + +- Correctly handle whitespace paths when executing gst-plugin-scanner +- Ensure properties are freed before (re)setting with g_value_dup_string() and during cleanup +- cmake: Fix PKG_CONFIG_PATH formatting for Windows cross-builds +- macos: Move macos function documentation to the .h so the introspection has the information +- meson.build: test for and link against libatomic if it exists +- pluginloader-win32: Fix helper executable path under devenv +- pluginloader: fix pending_plugins Glist use-after-free issue +- unixfdsrc: Complains about resize of memory area +- tracers: dots: fix debug log + +gst-plugins-base + +- Ensure properties are freed before (re)setting with g_value_dup_string() and during cleanup +- alsadeviceprovider: Fix leak of Alsa longname +- audioaggregator: fix error added in !8416 when chaining up +- audiobasesink: Fix custom slaving driftsamples calculation and add custom audio clock slaving callback example +- decodebin3: Don’t avoid parsebin even if we have a matching decoder +- decodebin3: Doesn’t plug parsebin for AAC from tsdemux +- gl: eglimage: warn the reason of export failure +- glcolorconvert: fix YUVA<->RGBA conversions +- glcolorconvert: regression when rendering alpha vp9 +- gldownload: Unref glcontext after usage +- meson.build: test for and link against libatomic if it exists +- oggdemux: Don’t push new packets if there is a pending seek +- urisourcebin: Make parsebin activation more reliable +- urisourcebin: deadlock between parsebin and typefind +- videoencoder: Use the correct segment and buffer timestamp in the chain function +- videotimecode: Fix conversion of timecode to datetime with drop-frame timecodes and handle 119.88 fps correctly in all + places + +gst-plugins-good + +- Ensure properties are freed before (re)setting with g_value_dup_string() and during cleanup +- gst-plugins-good: Matroska mux v4 support +- matroska-demux: Prevent corrupt cluster duplication +- qml6glsrc: update buffer pool on renegotiation +- qt6: Add a missing newline in unsupported platform message +- qtdemux: Fix stsc size check in qtdemux_merge_sample_table() +- qtdemux: Next Iteration Of Uncompressed MP4 Decoder +- qtdemux: unref simple caps after use +- rtspsrc: Do not emit signal ‘no-more-pads’ too early +- rtspsrc: Don’t error out on not-linked too early +- rtpsession: Do not push events while holding SESSION_LOCK +- rtpsession: deadlock when gst_rtp_session_send_rtcp () is forwarding eos +- v4l2: drop frame for frames that cannot be decoded +- v4l2videodec: AV unsync for streams with many frames that cannot be decoded +- v4l2object: fix memory leak +- v4l2object: fix type mismatch when ioctl takes int +- y4menc: fix Y41B format +- y4menc: handle frames with GstVideoMeta + +gst-plugins-bad + +- Add missing Requires in pkg-config +- Ensure properties are freed before (re)setting with g_value_dup_string() and during cleanup +- Update docs +- aja: Use the correct location of the AJA NTV2 SDK in the docs +- alphacombine: De-couple flush-start/stop events handling +- alphadecodebin: use a multiqueue instead of a couple of queues +- avfvideosrc: Guess reasonable framerate values for some 3rd party devices +- codecalpha: name both queues +- d3d12converter: Fix cropping when automatic mipmap is enabled +- dashsink: Make sure to use a non-NULL pad name when requesting a pad from splitmuxsink +- docs: Fix GstWebRTCICE* class documentation +- h264ccextractor, h265ccextractor: Handle gap with unknown pts +- h265decoder, h265ccinserter: Fix broken SPS/PPS link +- h265parser: Fix num_long_term_pics bound check +- Segmentation fault in H265 decoder +- h266decoder: fix leak parsing SEI messages +- meson.build: test for and link against libatomic if it exists +- mse: Improved Thread Safety of API +- mse: Revert ownership transfer API change in gst_source_buffer_append_buffer() +- tensordecoders: updating element classification +- unixfd: Fix wrong memory size when offset > 0 +- uvcsink: Respond to control requests with proper error handling +- v4l2codecs: unref frame in all error paths of end_picture +- va: Skip codecs that report maximum width or height lower than minimum +- vapostproc: fix wrong video orientation after restarting the element +- vavp9enc: fix mem leaks in _vp9_decide_profile +- vkformat: fix build error +- vtenc: Avoid deadlocking when changing properties on the fly +- vulkan: fix memory leak at dynamic registering +- webrtc: enhance rtx entry creation +- webrtcbin: add missing warning for caps missmatch +- ZDI-CAN-26596: New Vulnerability Report (Security) + +gst-plugins-ugly + +- No changes + +GStreamer Rust plugins + +- Bump MSRV to 1.83 +- Allow any windows-sys version >= 0.52 and <= 0.59 +- aws/polly: add GstScaletempoTargetDurationMeta to output buffers +- awstranslate: improve message posted on bus +- cdg: typefind: Division by zero fix +- cea708mux: Improve support for overflowing input captions +- colordetect: Change to videofilter base class +- dav1ddec: Drain decoder on caps changes if necessary +- dav1ddec: Only update unknown parts of the upstream colorimetry and not all of it +- dav1ddec: Support RGB encoded AV1 +- dav1ddec: Use downstream buffer pool for copying if video meta is not supported +- dav1ddec: Use max-frame-delay value from the decoder instead of calculating it +- dav1ddec: Use max-frame-delay value from the decoder instead of calculating it +- doc: Update to latest way of generating hotdoc config files +- Fix gtk4 compile +- Fix various clippy 1.86 warnings and update gstreamer-rs / gtk-rs dependencies +- fmp4mux: Add a couple of minor new features +- fmp4mux: Add manual-split mode that is triggered by serialized downstream events +- fmp4mux: Add send-force-keyunit property +- fmp4mux: Fix latency configuration for properties set during construction +- fmp4mux: Improve split-at-running-time handling +- fmp4mux/mp4mux: Handle the case of multiple tags per taglist correctly +- fmp4mux: Write a v0 tfdt box if the decode time is small enough +- gstwebrtc-api: Add TypeScript type definitions, build ESM for broader compatibility, improve JSDocs +- hlsmultivariantsink: Allow users to specify playlist and segment location +- hlssink3 - Add Support for NTP timestamp from buffer +- livesync: Notify in/out/drop/duplicate properties on change +- livesync: Only notify drop/duplicate properties +- meson: Require gst 1.18 features for dav1d +- mp4mux: Don’t write composition time offsets if they’re all zero +- mp4mux, fmp4mux: Use correct timescales for edit lists +- mpegtslivesrc: increase threshold for PCR <-> PTS DISCONT +- mpegtslivesrc: Use a separate mutex for the properties +- mux: use smaller number of samples for testing +- net/aws: punctuation-related improvements to our span_tokenize_items function +- pcap_writer: Mark target-factory and pad-path props as construct-only +- speechmatics: Handle multiple stream-start event +- tracers: buffer-lateness: don’t panic on add overflow + reduce graph legend entry font size a bit +- tracers: Update to etherparse 0.17 +- transcriberbin: make auto passthrough work when transcriber is a bin +- ts-jitterbuffer: improve scheduling of lost events +- tttocea708: fix origin-row handling for roll-up in CEA-708 +- Update Cargo.lock to remove old windows-targets 0.48.5 +- Update dependencies +- Update gtk-rs / gstreamer-rs dependencies and update for API changes +- Update to bitstream-io 3 +- uriplaylistbin: skip cache test when offline +- webrtc: Port to reqwest 0.12 +- webrtcsink: Fix compatibility with audio level header extension + +gst-libav + +- No changes + +gst-rtsp-server + +- Ensure properties are freed before (re)setting with g_value_dup_string() and during cleanup + +gstreamer-vaapi + +- No changes + +gstreamer-sharp + +- No changes + +gst-python + +- gst-python: fix compatibility with PyGObject >= 3.52.0 +- gst-python: Segmentation Fault since PyGObject >= 3.52.0 due to missing _introspection_module attribute + +gst-editing-services + +- Ensure properties are freed before (re)setting with g_value_dup_string() and during cleanup + +gst-devtools, gst-validate + gst-integration-testsuites + +- Add missing Requires in pkg-config +- devtools: dots-viewer: Bundle js dependencies using webpack +- devtools: dots-viewer: Update dependencies and make windows dependencies conditional + +gst-examples + +- examples: Update Rust dependencies +- examples: webrtc: rust: Move from async-std to tokio + +gstreamer-docs + +- Update docs + +Development build environment + +- No changes + +Cerbero build tool and packaging changes in 1.26.1 + +- FindGStreamerMobile: Override pkg-config on Windows -> Android cross builds +- Fix BuildTools not using recipes_remotes and recipes_commits +- bootstrap, meson: Use pathlib.Path.glob to allow Python < 3.10 +- Use of ‘glob(…, root_dir)’ requires Python >=3.10, cerbero enforces >= 3.7 +- harfbuzz: update to 10.4.0 +- Update fontconfig to 2.16.1, pango to 1.56.2 + +Contributors to 1.26.1 + +Alexander Slobodeniuk, Alyssa Ross, Artem Martus, Arun Raghavan, Brad Hards, Carlos Bentzen, Carlos Rafael Giani, Daniel Morin, +David Smitmanis, Detlev Casanova, Dongyun Seo, Doug Nazar, dukesook, Edward Hervey, eipachte, Eli Mallon, François Laignel, +Guillaume Desmottes, Gustav Fahlen, Hou Qi, Jakub Adam, Jan Schmidt, Jan Tojnar, Jordan Petridis, Jordan Yelloz, L. E. Segovia, +Marc Leeman, Marek Olejnik, Mathieu Duponchelle, Matteo Bruni, Matthew Waters, Michael Grzeschik, Nirbheek Chauhan, Ognyan +Tonchev, Olivier Blin, Olivier Crête, Philippe Normand, Piotr Brzeziński, Razvan Grigore, Robert Mader, Sanchayan Maity, +Sebastian Dröge, Seungha Yang, Shengqi Yu (喻盛琪), Stefan Andersson, Stéphane Cerveau, Thibault Saunier, Tim-Philipp Müller, +tomaszmi, Víctor Manuel Jáquez Leal, Xavier Claessens, + +… and many others who have contributed bug reports, translations, sent suggestions or helped testing. Thank you all! + +List of merge requests and issues fixed in 1.26.1 + +- List of Merge Requests applied in 1.26.1 +- List of Issues fixed in 1.26.1 + Schedule for 1.28 Our next major feature release will be 1.28, and 1.27 will be the unstable development version leading up to the stable 1.28
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/RELEASE -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/RELEASE
Changed
@@ -1,4 +1,4 @@ -This is GStreamer gst-plugins-bad 1.26.0. +This is GStreamer gst-plugins-bad 1.26.1. The GStreamer team is thrilled to announce a new major feature release of your favourite cross-platform multimedia framework!
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/docs/plugins/gst_plugins_cache.json -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/docs/plugins/gst_plugins_cache.json
Changed
@@ -228202,7 +228202,7 @@ "construct": false, "construct-only": false, "controllable": false, - "default": "18446744073709551615", + "default": "0", "max": "18446744073709551615", "min": "0", "mutable": "null", @@ -235257,6 +235257,178 @@ "tracers": {}, "url": "Unknown package origin" }, + "onnx": { + "description": "ONNX neural network plugin", + "elements": { + "onnxinference": { + "author": "Aaron Boxer <aaron.boxer@collabora.com>", + "description": "Apply neural network to video frames and create tensor output", + "hierarchy": + "GstOnnxInference", + "GstBaseTransform", + "GstElement", + "GstObject", + "GInitiallyUnowned", + "GObject" + , + "klass": "Filter/Effect/Video", + "pad-templates": { + "sink": { + "caps": "video/x-raw:\n format: { RGB, RGBA, BGR, BGRA }\n width: 1, 2147483647 \n height: 1, 2147483647 \n framerate: 0/1, 2147483647/1 \n", + "direction": "sink", + "presence": "always" + }, + "src": { + "caps": "video/x-raw:\n format: { RGB, RGBA, BGR, BGRA }\n width: 1, 2147483647 \n height: 1, 2147483647 \n framerate: 0/1, 2147483647/1 \n", + "direction": "src", + "presence": "always" + } + }, + "properties": { + "execution-provider": { + "blurb": "ONNX execution provider", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "cpu (0)", + "mutable": "null", + "readable": true, + "type": "GstOnnxExecutionProvider", + "writable": true + }, + "input-image-format": { + "blurb": "Input image format", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "hwc (0)", + "mutable": "null", + "readable": true, + "type": "GstMlInputImageFormat", + "writable": true + }, + "input-tensor-offset": { + "blurb": "offset each tensor value by this value", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "0", + "max": "3.40282e+38", + "min": "-3.40282e+38", + "mutable": "null", + "readable": true, + "type": "gfloat", + "writable": true + }, + "input-tensor-scale": { + "blurb": "Divide each tensor value by this value", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "1", + "max": "3.40282e+38", + "min": "1.17549e-38", + "mutable": "null", + "readable": true, + "type": "gfloat", + "writable": true + }, + "model-file": { + "blurb": "ONNX model file", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "NULL", + "mutable": "null", + "readable": true, + "type": "gchararray", + "writable": true + }, + "optimization-level": { + "blurb": "ONNX optimization level", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "disable-all (0)", + "mutable": "null", + "readable": true, + "type": "GstOnnxOptimizationLevel", + "writable": true + } + }, + "rank": "primary" + } + }, + "filename": "gstonnx", + "license": "LGPL", + "other-types": { + "GstMlInputImageFormat": { + "kind": "enum", + "values": + { + "desc": "Height Width Channel (HWC) a.k.a. interleaved image data format", + "name": "hwc", + "value": "0" + }, + { + "desc": "Channel Height Width (CHW) a.k.a. planar image data format", + "name": "chw", + "value": "1" + } + + }, + "GstOnnxExecutionProvider": { + "kind": "enum", + "values": + { + "desc": "CPU execution provider", + "name": "cpu", + "value": "0" + }, + { + "desc": "CUDA execution provider", + "name": "cuda", + "value": "1" + } + + }, + "GstOnnxOptimizationLevel": { + "kind": "enum", + "values": + { + "desc": "Disable all optimization", + "name": "disable-all", + "value": "0" + }, + { + "desc": "Enable basic optimizations (redundant node removals))", + "name": "enable-basic", + "value": "1" + }, + { + "desc": "Enable extended optimizations (redundant node removals + node fusions)", + "name": "enable-extended", + "value": "2" + }, + { + "desc": "Enable all possible optimizations", + "name": "enable-all", + "value": "3" + } + + } + }, + "package": "GStreamer Bad Plug-ins", + "source": "gst-plugins-bad", + "tracers": {}, + "url": "Unknown package origin" + }, "openal": { "description": "OpenAL plugin library", "elements": { @@ -240282,7 +240454,7 @@ "writable": true } }, - "rank": "primary" + "rank": "none" }, "qsvh265dec": { "author": "Seungha Yang <seungha@centricular.com>", @@ -240615,7 +240787,7 @@ "writable": true } }, - "rank": "primary" + "rank": "none" }, "qsvjpegdec": { "author": "Seungha Yang <seungha@centricular.com>", @@ -240688,7 +240860,7 @@ "writable": true } }, - "rank": "primary" + "rank": "none" }, "qsvvp9dec": { "author": "Seungha Yang <seungha@centricular.com>", @@ -240927,6 +241099,18 @@ "readable": true, "type": "gint64", "writable": false + }, + "device-path": { + "blurb": "DRM device path", + "conditionally-available": true, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "NULL", + "mutable": "null", + "readable": true, + "type": "gchararray", + "writable": false } } }, @@ -240958,6 +241142,18 @@ "type": "gint64", "writable": false }, + "device-path": { + "blurb": "DRM device path", + "conditionally-available": true, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "NULL", + "mutable": "null", + "readable": true, + "type": "gchararray", + "writable": false + }, "low-latency": { "blurb": "Enables low-latency encoding", "conditionally-available": false, @@ -247832,7 +248028,7 @@ "GInitiallyUnowned", "GObject" , - "klass": "TensorDecoder/Video", + "klass": "Tensordecoder/Video", "pad-templates": { "sink": { "caps": "video/x-raw:\n", @@ -250999,6 +251195,330 @@ }, "rank": "none" }, + "vah264lpenc": { + "author": "He Junyan <junyan.he@intel.com>", + "description": "VA-API based H.264 low power video encoder", + "hierarchy": + "GstVaH264LPEnc", + "GstVaBaseEnc", + "GstVideoEncoder", + "GstElement", + "GstObject", + "GInitiallyUnowned", + "GObject" + , + "interfaces": + "GstPreset" + , + "klass": "Codec/Encoder/Video/Hardware", + "pad-templates": { + "sink": { + "caps": "video/x-raw(memory:VAMemory):\n format: { NV12 }\n width: 1, 2147483647 \n height: 1, 2147483647 \n framerate: 0/1, 2147483647/1 \nvideo/x-raw:\n format: { NV12 }\n width: 1, 2147483647 \n height: 1, 2147483647 \n framerate: 0/1, 2147483647/1 \n", + "direction": "sink", + "presence": "always" + }, + "src": { + "caps": "video/x-h264:\n", + "direction": "src", + "presence": "always" + } + }, + "properties": { + "aud": { + "blurb": "Insert AU (Access Unit) delimeter for each frame", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "false", + "mutable": "null", + "readable": true, + "type": "gboolean", + "writable": true + }, + "b-frames": { + "blurb": "Number of B frames between I and P reference frames", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "0", + "max": "31", + "min": "0", + "mutable": "null", + "readable": true, + "type": "guint", + "writable": true + }, + "b-pyramid": { + "blurb": "Enable the b-pyramid reference structure in the GOP", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "false", + "mutable": "null", + "readable": true, + "type": "gboolean", + "writable": true + }, + "bitrate": { + "blurb": "The desired bitrate expressed in kbps (0: auto-calculate)", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "0", + "max": "2048000", + "min": "0", + "mutable": "playing", + "readable": true, + "type": "guint", + "writable": true + }, + "cabac": { + "blurb": "Enable CABAC entropy coding mode", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "true", + "mutable": "null", + "readable": true, + "type": "gboolean", + "writable": true + }, + "cc-insert": { + "blurb": "Insert CEA-708 Closed Captions", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "true", + "mutable": "null", + "readable": true, + "type": "gboolean", + "writable": true + }, + "cpb-size": { + "blurb": "The desired max CPB size in Kb (0: auto-calculate)", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "0", + "max": "2048000", + "min": "0", + "mutable": "playing", + "readable": true, + "type": "guint", + "writable": true + }, + "dct8x8": { + "blurb": "Enable adaptive use of 8x8 transforms in I-frames", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "true", + "mutable": "null", + "readable": true, + "type": "gboolean", + "writable": true + }, + "i-frames": { + "blurb": "Force the number of I frames insertion within one GOP, not including the first IDR frame", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "0", + "max": "1023", + "min": "0", + "mutable": "null", + "readable": true, + "type": "guint", + "writable": true + }, + "key-int-max": { + "blurb": "The maximal distance between two keyframes. It decides the size of GOP (0: auto-calculate)", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "0", + "max": "1024", + "min": "0", + "mutable": "null", + "readable": true, + "type": "guint", + "writable": true + }, + "max-qp": { + "blurb": "Maximum quantizer value for each frame", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "51", + "max": "51", + "min": "0", + "mutable": "null", + "readable": true, + "type": "guint", + "writable": true + }, + "mbbrc": { + "blurb": "Macroblock level Bitrate Control. Not available in CQP mode", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "auto (2)", + "mutable": "null", + "readable": true, + "type": "GstVaFeature", + "writable": true + }, + "min-qp": { + "blurb": "Minimum quantizer value for each frame", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "1", + "max": "51", + "min": "0", + "mutable": "null", + "readable": true, + "type": "guint", + "writable": true + }, + "num-slices": { + "blurb": "Number of slices per frame", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "1", + "max": "200", + "min": "1", + "mutable": "null", + "readable": true, + "type": "guint", + "writable": true + }, + "qpb": { + "blurb": "The quantizer value for B frame. Available only in CQP mode", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "26", + "max": "51", + "min": "0", + "mutable": "playing", + "readable": true, + "type": "guint", + "writable": true + }, + "qpi": { + "blurb": "The quantizer value for I frame. In CQP mode, it specifies the QP of I frame. In ICQ and QVBR modes, it specifies a quality factor. In other modes, it is ignored", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "26", + "max": "51", + "min": "0", + "mutable": "playing", + "readable": true, + "type": "guint", + "writable": true + }, + "qpp": { + "blurb": "The quantizer value for P frame. Available only in CQP mode", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "26", + "max": "51", + "min": "0", + "mutable": "playing", + "readable": true, + "type": "guint", + "writable": true + }, + "rate-control": { + "blurb": "The desired rate control mode for the encoder", + "conditionally-available": true, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "cqp (16)", + "mutable": "playing", + "readable": true, + "type": "GstVaEncoderRateControl_H264_LP_renderD128", + "writable": true + }, + "ref-frames": { + "blurb": "Number of reference frames, including both the forward and the backward", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "3", + "max": "16", + "min": "0", + "mutable": "null", + "readable": true, + "type": "guint", + "writable": true + }, + "target-percentage": { + "blurb": "The percentage for 'target bitrate'/'maximum bitrate' (Only in VBR)", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "66", + "max": "100", + "min": "50", + "mutable": "playing", + "readable": true, + "type": "guint", + "writable": true + }, + "target-usage": { + "blurb": "The target usage to control and balance the encoding speed/quality", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "4", + "max": "7", + "min": "1", + "mutable": "playing", + "readable": true, + "type": "guint", + "writable": true + }, + "trellis": { + "blurb": "Enable the trellis quantization method", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "false", + "mutable": "null", + "readable": true, + "type": "gboolean", + "writable": true + } + }, + "rank": "none" + }, "vah265dec": { "author": "Nicolas Dufresne <nicolas.dufresne@collabora.com>", "description": "VA-API based H.265 video decoder", @@ -251356,6 +251876,322 @@ }, "rank": "none" }, + "vah265lpenc": { + "author": "He Junyan <junyan.he@intel.com>", + "description": "VA-API based H.265 low power video encoder", + "hierarchy": + "GstVaH265LPEnc", + "GstVaBaseEnc", + "GstVideoEncoder", + "GstElement", + "GstObject", + "GInitiallyUnowned", + "GObject" + , + "interfaces": + "GstPreset" + , + "klass": "Codec/Encoder/Video/Hardware", + "pad-templates": { + "sink": { + "caps": "video/x-raw(memory:VAMemory):\n format: { NV12 }\n width: 1, 2147483647 \n height: 1, 2147483647 \n framerate: 0/1, 2147483647/1 \nvideo/x-raw:\n format: { NV12 }\n width: 1, 2147483647 \n height: 1, 2147483647 \n framerate: 0/1, 2147483647/1 \n", + "direction": "sink", + "presence": "always" + }, + "src": { + "caps": "video/x-h265:\n", + "direction": "src", + "presence": "always" + } + }, + "properties": { + "aud": { + "blurb": "Insert AU (Access Unit) delimeter for each frame", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "false", + "mutable": "null", + "readable": true, + "type": "gboolean", + "writable": true + }, + "b-frames": { + "blurb": "Number of B frames between I and P reference frames", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "0", + "max": "31", + "min": "0", + "mutable": "null", + "readable": true, + "type": "guint", + "writable": true + }, + "b-pyramid": { + "blurb": "Enable the b-pyramid reference structure in the GOP", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "false", + "mutable": "null", + "readable": true, + "type": "gboolean", + "writable": true + }, + "bitrate": { + "blurb": "The desired bitrate expressed in kbps (0: auto-calculate)", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "0", + "max": "2048000", + "min": "0", + "mutable": "playing", + "readable": true, + "type": "guint", + "writable": true + }, + "cpb-size": { + "blurb": "The desired max CPB size in Kb (0: auto-calculate)", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "0", + "max": "2048000", + "min": "0", + "mutable": "playing", + "readable": true, + "type": "guint", + "writable": true + }, + "i-frames": { + "blurb": "Force the number of I frames insertion within one GOP, not including the first IDR frame", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "0", + "max": "1023", + "min": "0", + "mutable": "null", + "readable": true, + "type": "guint", + "writable": true + }, + "key-int-max": { + "blurb": "The maximal distance between two keyframes. It decides the size of GOP (0: auto-calculate)", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "0", + "max": "1024", + "min": "0", + "mutable": "null", + "readable": true, + "type": "guint", + "writable": true + }, + "max-qp": { + "blurb": "Maximum quantizer value for each frame", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "51", + "max": "51", + "min": "0", + "mutable": "null", + "readable": true, + "type": "guint", + "writable": true + }, + "mbbrc": { + "blurb": "Macroblock level Bitrate Control. It is not compatible with CQP", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "auto (2)", + "mutable": "null", + "readable": true, + "type": "GstVaFeature", + "writable": true + }, + "min-qp": { + "blurb": "Minimum quantizer value for each frame", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "1", + "max": "51", + "min": "0", + "mutable": "null", + "readable": true, + "type": "guint", + "writable": true + }, + "num-slices": { + "blurb": "Number of slices per frame", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "1", + "max": "200", + "min": "1", + "mutable": "null", + "readable": true, + "type": "guint", + "writable": true + }, + "num-tile-cols": { + "blurb": "The number of columns for tile encoding", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "1", + "max": "20", + "min": "1", + "mutable": "null", + "readable": true, + "type": "guint", + "writable": true + }, + "num-tile-rows": { + "blurb": "The number of rows for tile encoding", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "1", + "max": "22", + "min": "1", + "mutable": "null", + "readable": true, + "type": "guint", + "writable": true + }, + "qpb": { + "blurb": "The quantizer value for B frame. This is available only in CQP mode", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "26", + "max": "51", + "min": "0", + "mutable": "playing", + "readable": true, + "type": "guint", + "writable": true + }, + "qpi": { + "blurb": "The quantizer value for I frame. In CQP mode, it specifies the QP of I frame. In ICQ and QVBR modes, it specifies a quality factor. In other modes, it is ignored", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "26", + "max": "51", + "min": "0", + "mutable": "playing", + "readable": true, + "type": "guint", + "writable": true + }, + "qpp": { + "blurb": "The quantizer value for P frame. This is available only in CQP mode", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "26", + "max": "51", + "min": "0", + "mutable": "playing", + "readable": true, + "type": "guint", + "writable": true + }, + "rate-control": { + "blurb": "The desired rate control mode for the encoder", + "conditionally-available": true, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "cqp (16)", + "mutable": "playing", + "readable": true, + "type": "GstVaEncoderRateControl_H265_LP_renderD128", + "writable": true + }, + "ref-frames": { + "blurb": "Number of reference frames, including both the forward and the backward", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "3", + "max": "15", + "min": "0", + "mutable": "null", + "readable": true, + "type": "guint", + "writable": true + }, + "target-percentage": { + "blurb": "The percentage for 'target bitrate'/'maximum bitrate' (Only in VBR)", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "66", + "max": "100", + "min": "50", + "mutable": "playing", + "readable": true, + "type": "guint", + "writable": true + }, + "target-usage": { + "blurb": "The target usage to control and balance the encoding speed/quality", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "4", + "max": "7", + "min": "1", + "mutable": "playing", + "readable": true, + "type": "guint", + "writable": true + }, + "trellis": { + "blurb": "Enable the trellis quantization method", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "false", + "mutable": "null", + "readable": true, + "type": "gboolean", + "writable": true + } + }, + "rank": "none" + }, "vajpegdec": { "author": "Víctor Jáquez <vjaquez@igalia.com>", "description": "VA-API based JPEG image decoder", @@ -251397,6 +252233,52 @@ }, "rank": "none" }, + "vajpegenc": { + "author": "He Junyan <junyan.he@intel.com>", + "description": "VA-API based JPEG video encoder", + "hierarchy": + "GstVaJpegEnc", + "GstVaBaseEnc", + "GstVideoEncoder", + "GstElement", + "GstObject", + "GInitiallyUnowned", + "GObject" + , + "interfaces": + "GstPreset" + , + "klass": "Codec/Encoder/Video/Hardware", + "pad-templates": { + "sink": { + "caps": "video/x-raw(memory:VAMemory):\n format: { NV12 }\n width: 1, 2147483647 \n height: 1, 2147483647 \n framerate: 0/1, 2147483647/1 \nvideo/x-raw:\n format: { NV12 }\n width: 1, 2147483647 \n height: 1, 2147483647 \n framerate: 0/1, 2147483647/1 \n", + "direction": "sink", + "presence": "always" + }, + "src": { + "caps": "image/jpeg:\n", + "direction": "src", + "presence": "always" + } + }, + "properties": { + "quality": { + "blurb": "Quality factor for encoding", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "50", + "max": "100", + "min": "0", + "mutable": "null", + "readable": true, + "type": "guint", + "writable": true + } + }, + "rank": "none" + }, "vampeg2dec": { "author": "He Junyan <junyan.he@intel.com>", "description": "VA-API based Mpeg2 video decoder", @@ -251479,6 +252361,60 @@ "type": "gboolean", "writable": true }, + "auto-contrast": { + "blurb": "Enable auto contrast", + "conditionally-available": true, + "construct": false, + "construct-only": false, + "controllable": true, + "default": "false", + "mutable": "playing", + "readable": true, + "type": "gboolean", + "writable": true + }, + "brightness": { + "blurb": "Color brightness value", + "conditionally-available": true, + "construct": false, + "construct-only": false, + "controllable": true, + "default": "0", + "max": "100", + "min": "-100", + "mutable": "playing", + "readable": true, + "type": "gfloat", + "writable": true + }, + "contrast": { + "blurb": "Color contrast value", + "conditionally-available": true, + "construct": false, + "construct-only": false, + "controllable": true, + "default": "1", + "max": "10", + "min": "0", + "mutable": "playing", + "readable": true, + "type": "gfloat", + "writable": true + }, + "denoise": { + "blurb": "Noise reduction factor", + "conditionally-available": true, + "construct": false, + "construct-only": false, + "controllable": true, + "default": "0", + "max": "64", + "min": "0", + "mutable": "playing", + "readable": true, + "type": "gfloat", + "writable": true + }, "disable-passthrough": { "blurb": "Forces passing buffers through the postprocessor", "conditionally-available": false, @@ -251491,6 +252427,32 @@ "type": "gboolean", "writable": true }, + "hdr-tone-mapping": { + "blurb": "Enable HDR to SDR tone mapping", + "conditionally-available": true, + "construct": false, + "construct-only": false, + "controllable": true, + "default": "false", + "mutable": "playing", + "readable": true, + "type": "gboolean", + "writable": true + }, + "hue": { + "blurb": "Color hue value", + "conditionally-available": true, + "construct": false, + "construct-only": false, + "controllable": true, + "default": "0", + "max": "180", + "min": "-180", + "mutable": "playing", + "readable": true, + "type": "gfloat", + "writable": true + }, "interpolation-method": { "blurb": "Interpolation method to use for scaling", "conditionally-available": true, @@ -251503,6 +252465,20 @@ "type": "GstVaInterpolationMethod", "writable": true }, + "saturation": { + "blurb": "Color saturation value", + "conditionally-available": true, + "construct": false, + "construct-only": false, + "controllable": true, + "default": "1", + "max": "10", + "min": "0", + "mutable": "playing", + "readable": true, + "type": "gfloat", + "writable": true + }, "scale-method": { "blurb": "Scale method to use", "conditionally-available": true, @@ -251514,10 +252490,80 @@ "readable": true, "type": "GstVaScaleMethod", "writable": true + }, + "sharpen": { + "blurb": "Sharpening/blurring filter", + "conditionally-available": true, + "construct": false, + "construct-only": false, + "controllable": true, + "default": "44", + "max": "64", + "min": "0", + "mutable": "playing", + "readable": true, + "type": "gfloat", + "writable": true + }, + "skin-tone": { + "blurb": "Skin Tone Enhancenment filter", + "conditionally-available": true, + "construct": false, + "construct-only": false, + "controllable": true, + "default": "3", + "max": "9", + "min": "0", + "mutable": "playing", + "readable": true, + "type": "gfloat", + "writable": true + }, + "video-direction": { + "blurb": "Video direction: rotation and flipping", + "conditionally-available": true, + "construct": false, + "construct-only": false, + "controllable": true, + "default": "identity (0)", + "mutable": "playing", + "readable": true, + "type": "GstVideoOrientationMethod", + "writable": true } }, "rank": "none" }, + "vavp8alphadecodebin": { + "author": "Cheung Yik Pang <pang.cheung@harmonicinc.com>", + "description": "Wrapper bin to decode VP8 with alpha stream.", + "hierarchy": + "GstVaVp8AlphaDecodeBin", + "GstVaCodecAlphaDecodeBin", + "GstBin", + "GstElement", + "GstObject", + "GInitiallyUnowned", + "GObject" + , + "interfaces": + "GstChildProxy" + , + "klass": "Codec/Decoder/Video/Hardware", + "pad-templates": { + "sink": { + "caps": "video/x-vp8:\n codec-alpha: true\n alignment: frame\n", + "direction": "sink", + "presence": "always" + }, + "src": { + "caps": "ANY", + "direction": "src", + "presence": "always" + } + }, + "rank": "primary + 11" + }, "vavp8dec": { "author": "He Junyan <junyan.he@intel.com>", "description": "VA-API based VP8 video decoder", @@ -251557,7 +252603,37 @@ "writable": false } }, - "rank": "none" + "rank": "primary + 1" + }, + "vavp9alphadecodebin": { + "author": "Cheung Yik Pang <pang.cheung@harmonicinc.com>", + "description": "Wrapper bin to decode VP9 with alpha stream.", + "hierarchy": + "GstVaVp9AlphaDecodeBin", + "GstVaCodecAlphaDecodeBin", + "GstBin", + "GstElement", + "GstObject", + "GInitiallyUnowned", + "GObject" + , + "interfaces": + "GstChildProxy" + , + "klass": "Codec/Decoder/Video/Hardware", + "pad-templates": { + "sink": { + "caps": "video/x-vp9:\n codec-alpha: true\n alignment: frame\n", + "direction": "sink", + "presence": "always" + }, + "src": { + "caps": "ANY", + "direction": "src", + "presence": "always" + } + }, + "rank": "primary + 11" }, "vavp9dec": { "author": "Víctor Jáquez <vjaquez@igalia.com>", @@ -251668,6 +252744,20 @@ } } }, + "GstVaCodecAlphaDecodeBin": { + "hierarchy": + "GstVaCodecAlphaDecodeBin", + "GstBin", + "GstElement", + "GstObject", + "GInitiallyUnowned", + "GObject" + , + "interfaces": + "GstChildProxy" + , + "kind": "object" + }, "GstVaCompositorPad": { "hierarchy": "GstVaCompositorPad", @@ -251792,6 +252882,16 @@ } }, + "GstVaEncoderRateControl_H264_LP_renderD128": { + "kind": "enum", + "values": + { + "desc": "Constant Quantizer", + "name": "cqp", + "value": "16" + } + + }, "GstVaEncoderRateControl_H264_renderD128": { "kind": "enum", "values": @@ -251806,6 +252906,31 @@ "value": "4" }, { + "desc": "Video Conferencing Mode (Non HRD compliant)", + "name": "vcm", + "value": "8" + }, + { + "desc": "Constant Quantizer", + "name": "cqp", + "value": "16" + }, + { + "desc": "Intelligent Constant Quality", + "name": "icq", + "value": "64" + }, + { + "desc": "Quality defined VBR", + "name": "qvbr", + "value": "1024" + } + + }, + "GstVaEncoderRateControl_H265_LP_renderD128": { + "kind": "enum", + "values": + { "desc": "Constant Quantizer", "name": "cqp", "value": "16" @@ -251826,29 +252951,24 @@ "value": "4" }, { + "desc": "Video Conferencing Mode (Non HRD compliant)", + "name": "vcm", + "value": "8" + }, + { "desc": "Constant Quantizer", "name": "cqp", "value": "16" - } - - }, - "GstVaFeature": { - "kind": "enum", - "values": - { - "desc": "GST_VA_FEATURE_DISABLED", - "name": "disabled", - "value": "0" }, { - "desc": "GST_VA_FEATURE_ENABLED", - "name": "enabled", - "value": "1" + "desc": "Intelligent Constant Quality", + "name": "icq", + "value": "64" }, { - "desc": "GST_VA_FEATURE_AUTO", - "name": "auto", - "value": "2" + "desc": "Quality defined VBR", + "name": "qvbr", + "value": "1024" } }, @@ -256154,7 +257274,7 @@ "construct": false, "construct-only": false, "controllable": false, - "default": "NULL", + "default": "about:blank", "mutable": "null", "readable": true, "type": "gchararray", @@ -256183,6 +257303,17 @@ , "return-type": "void", "when": "last" + }, + "run-javascript": { + "action": true, + "args": + { + "name": "arg0", + "type": "gchararray" + } + , + "return-type": "void", + "when": "last" } } }, @@ -256227,7 +257358,7 @@ "construct": false, "construct-only": false, "controllable": false, - "default": "NULL", + "default": "about:blank", "mutable": "null", "readable": true, "type": "gchararray", @@ -256255,6 +257386,17 @@ } , "return-type": "void", + "when": "last" + }, + "run-javascript": { + "action": true, + "args": + { + "name": "arg0", + "type": "gchararray" + } + , + "return-type": "void", "when": "last" } }
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/closedcaption/gstcodecccinserter.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/closedcaption/gstcodecccinserter.c
Changed
@@ -552,6 +552,7 @@ if (!klass->push (self, frame, &latency)) { GST_ERROR_OBJECT (self, "Couldn't process frame"); priv->current_frame_events = frame->events; + frame->events = NULL; gst_video_codec_frame_unref (frame); /* TODO: return error in case of too many decoding error */ return GST_FLOW_OK;
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/closedcaption/gsth264ccextractor.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/closedcaption/gsth264ccextractor.c
Changed
@@ -446,12 +446,14 @@ dur = GST_BUFFER_DURATION (frame->input_buffer); if (!front_buf) { - GstEvent *gap; - GST_VIDEO_CODEC_FRAME_SET_DECODE_ONLY (frame); ret = gst_video_decoder_finish_frame (videodec, frame); - gap = gst_event_new_gap (pts, dur); - gst_pad_push_event (videodec->srcpad, gap); + + if (GST_CLOCK_TIME_IS_VALID (pts)) { + GstEvent *gap = gst_event_new_gap (pts, dur); + gst_pad_push_event (videodec->srcpad, gap); + } + return ret; }
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/closedcaption/gsth265ccextractor.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/closedcaption/gsth265ccextractor.c
Changed
@@ -420,12 +420,14 @@ dur = GST_BUFFER_DURATION (frame->input_buffer); if (!front_buf) { - GstEvent *gap; - GST_VIDEO_CODEC_FRAME_SET_DECODE_ONLY (frame); ret = gst_video_decoder_finish_frame (videodec, frame); - gap = gst_event_new_gap (pts, dur); - gst_pad_push_event (videodec->srcpad, gap); + + if (GST_CLOCK_TIME_IS_VALID (pts)) { + GstEvent *gap = gst_event_new_gap (pts, dur); + gst_pad_push_event (videodec->srcpad, gap); + } + return ret; }
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/closedcaption/gsth265reorder.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/closedcaption/gsth265reorder.c
Changed
@@ -27,6 +27,7 @@ #include "gsth265reorder.h" #include "gsth264reorder.h" #include <gst/codecs/gsth265picture.h> +#include <gst/codecparsers/gsth265parser-private.h> #include <string.h> GST_DEBUG_CATEGORY_STATIC (gst_h265_reorder_debug); @@ -52,6 +53,7 @@ guint nal_length_size; gboolean is_hevc; GstH265Parser *parser; + GstH265Parser *preproc_parser; GstH265Dpb *dpb; guint8 field_seq_flag; @@ -131,10 +133,13 @@ { union { + GstH265VPS vps; GstH265SPS sps; + GstH265PPS pps; GstH265Slice slice; } unit; - gboolean is_slice; + GstH265NalUnitType nalu_type; + guint pps_id; } GstH265ReorderNalUnit; static void gst_h265_reorder_finalize (GObject * object); @@ -155,13 +160,26 @@ "h265reorder"); } +static inline gboolean +is_slice_nalu (GstH265NalUnitType type) +{ + if ((type >= GST_H265_NAL_SLICE_TRAIL_N && + type <= GST_H265_NAL_SLICE_RASL_R) || + (type >= GST_H265_NAL_SLICE_BLA_W_LP && + type <= GST_H265_NAL_SLICE_CRA_NUT)) { + return TRUE; + } + + return FALSE; +} + static void gst_h265_reorder_clear_nalu (GstH265ReorderNalUnit * nalu) { if (!nalu) return; - if (nalu->is_slice) + if (is_slice_nalu (nalu->nalu_type)) gst_h265_slice_hdr_free (&nalu->unit.slice.header); memset (nalu, 0, sizeof (GstH265ReorderNalUnit)); @@ -171,6 +189,7 @@ gst_h265_reorder_init (GstH265Reorder * self) { self->parser = gst_h265_parser_new (); + self->preproc_parser = gst_h265_parser_new (); self->dpb = gst_h265_dpb_new (); self->frame_queue = g_ptr_array_new_with_free_func ( @@ -209,6 +228,7 @@ GstH265Reorder *self = GST_H265_REORDER (object); gst_h265_parser_free (self->parser); + gst_h265_parser_free (self->preproc_parser); g_ptr_array_unref (self->frame_queue); g_ptr_array_unref (self->output_queue); g_array_unref (self->nalu); @@ -413,7 +433,7 @@ GArray *messages = NULL; guint i; - pres = gst_h265_parser_parse_sei (self->parser, nalu, &messages); + pres = gst_h265_parser_parse_sei (self->preproc_parser, nalu, &messages); if (pres != GST_H265_PARSER_OK) { GST_WARNING_OBJECT (self, "Failed to parse SEI, result %d", pres); @@ -523,7 +543,8 @@ memset (&slice, 0, sizeof (GstH265Slice)); - pres = gst_h265_parser_parse_slice_hdr (self->parser, nalu, &slice.header); + pres = gst_h265_parser_parse_slice_hdr (self->preproc_parser, + nalu, &slice.header); if (pres != GST_H265_PARSER_OK) return pres; @@ -567,7 +588,9 @@ self->no_output_of_prior_pics_flag = TRUE; decoder_nalu.unit.slice = slice; - decoder_nalu.is_slice = TRUE; + decoder_nalu.nalu_type = nalu->type; + decoder_nalu.pps_id = slice.header.pps->id; + g_array_append_val (self->nalu, decoder_nalu); return GST_H265_PARSER_OK; @@ -585,21 +608,33 @@ GST_LOG_OBJECT (self, "Parsed nal type: %d, offset %d, size %d", nalu->type, nalu->offset, nalu->size); + memset (&decoder_nalu, 0, sizeof (GstH265ReorderNalUnit)); + decoder_nalu.nalu_type = nalu->type; + switch (nalu->type) { case GST_H265_NAL_VPS: - ret = gst_h265_parser_parse_vps (self->parser, nalu, &vps); + ret = gst_h265_parser_parse_vps (self->preproc_parser, nalu, &vps); + if (ret != GST_H265_PARSER_OK) + break; + + decoder_nalu.unit.vps = vps; + g_array_append_val (self->nalu, decoder_nalu); break; case GST_H265_NAL_SPS: - ret = gst_h265_parser_parse_sps (self->parser, nalu, &sps, TRUE); + ret = gst_h265_parser_parse_sps (self->preproc_parser, nalu, &sps, TRUE); if (ret != GST_H265_PARSER_OK) break; - memset (&decoder_nalu, 0, sizeof (GstH265ReorderNalUnit)); decoder_nalu.unit.sps = sps; g_array_append_val (self->nalu, decoder_nalu); break; case GST_H265_NAL_PPS: - ret = gst_h265_parser_parse_pps (self->parser, nalu, &pps); + ret = gst_h265_parser_parse_pps (self->preproc_parser, nalu, &pps); + if (ret != GST_H265_PARSER_OK) + break; + + decoder_nalu.unit.pps = pps; + g_array_append_val (self->nalu, decoder_nalu); break; case GST_H265_NAL_PREFIX_SEI: case GST_H265_NAL_SUFFIX_SEI: @@ -642,10 +677,35 @@ gst_h265_reorder_decode_nalu (GstH265Reorder * self, GstH265ReorderNalUnit * nalu) { - if (nalu->is_slice) - return gst_h265_reorder_process_slice (self, &nalu->unit.slice); + GstH265ParserResult rst; - return TRUE; + switch (nalu->nalu_type) { + case GST_H265_NAL_VPS: + gst_h265_parser_update_vps (self->parser, &nalu->unit.vps); + return TRUE; + case GST_H265_NAL_SPS: + gst_h265_parser_update_sps (self->parser, &nalu->unit.sps); + return TRUE; + case GST_H265_NAL_PPS: + gst_h265_parser_update_pps (self->parser, &nalu->unit.pps); + return TRUE; + default: + if (!is_slice_nalu (nalu->nalu_type)) { + GST_WARNING_OBJECT (self, "Unexpected nal type %d", nalu->nalu_type); + return TRUE; + } + break; + } + + rst = gst_h265_parser_link_slice_hdr (self->parser, + &nalu->unit.slice.header, nalu->pps_id); + + if (rst != GST_H265_PARSER_OK) { + GST_ERROR_OBJECT (self, "Couldn't update slice header"); + return FALSE; + } + + return gst_h265_reorder_process_slice (self, &nalu->unit.slice); } static gboolean @@ -686,6 +746,7 @@ GST_WARNING_OBJECT (self, "Failed to parse VPS"); goto out; } + gst_h265_parser_update_vps (self->preproc_parser, &vps); break; case GST_H265_NAL_SPS: pres = gst_h265_parser_parse_sps (parser, nalu, &sps, TRUE); @@ -693,6 +754,7 @@ GST_WARNING_OBJECT (self, "Failed to parse SPS"); goto out; } + gst_h265_parser_update_sps (self->preproc_parser, &sps); break; case GST_H265_NAL_PPS: pres = gst_h265_parser_parse_pps (parser, nalu, &pps); @@ -700,6 +762,7 @@ GST_WARNING_OBJECT (self, "Failed to parse PPS"); goto out; } + gst_h265_parser_update_pps (self->preproc_parser, &pps); break; default: break;
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/curl/gstcurlhttpsrc.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/curl/gstcurlhttpsrc.c
Changed
@@ -566,6 +566,7 @@ source->strict_ssl = g_value_get_boolean (value); break; case PROP_SSL_CA_FILE: + g_free (source->custom_ca_file); source->custom_ca_file = g_value_dup_string (value); break; case PROP_RETRIES: @@ -1476,6 +1477,11 @@ g_mutex_unlock (&src->uri_mutex); g_mutex_clear (&src->uri_mutex); + g_free (src->username); + src->username = NULL; + g_free (src->password); + src->password = NULL; + g_free (src->proxy_uri); src->proxy_uri = NULL; g_free (src->no_proxy_list); @@ -1495,6 +1501,9 @@ g_free (src->user_agent); src->user_agent = NULL; + g_free (src->custom_ca_file); + src->custom_ca_file = NULL; + g_mutex_clear (&src->buffer_mutex); g_cond_clear (&src->buffer_cond);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/dash/gstdashsink.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/dash/gstdashsink.c
Changed
@@ -1066,6 +1066,9 @@ stream->adaptation_set_id = ADAPTATION_SET_ID_SUBTITLE; } + if (!split_pad_name) + split_pad_name = templ->name_template; + if (pad_name) stream->representation_id = g_strdup (pad_name); else
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/dash/gstmpdadaptationsetnode.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/dash/gstmpdadaptationsetnode.c
Changed
@@ -77,8 +77,7 @@ if (self->lang) xmlFree (self->lang); - if (self->contentType) - xmlFree (self->contentType); + g_free (self->contentType); g_slice_free (GstXMLRatio, self->par); g_slice_free (GstXMLConditionalUintType, self->segmentAlignment); g_slice_free (GstXMLConditionalUintType, self->subsegmentAlignment);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/dash/gstmpdperiodnode.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/dash/gstmpdperiodnode.c
Changed
@@ -88,8 +88,7 @@ { GstMPDPeriodNode *self = GST_MPD_PERIOD_NODE (object); - if (self->id) - xmlFree (self->id); + g_free (self->id); gst_mpd_segment_base_node_free (self->SegmentBase); gst_mpd_segment_list_node_free (self->SegmentList); gst_mpd_segment_template_node_free (self->SegmentTemplate);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/dash/gstmpdrepresentationbasenode.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/dash/gstmpdrepresentationbasenode.c
Changed
@@ -190,22 +190,16 @@ GstMPDRepresentationBaseNode *self = GST_MPD_REPRESENTATION_BASE_NODE (object); - if (self->profiles) - xmlFree (self->profiles); + g_free (self->profiles); g_slice_free (GstXMLRatio, self->sar); g_slice_free (GstXMLFrameRate, self->frameRate); g_slice_free (GstXMLFrameRate, self->minFrameRate); g_slice_free (GstXMLFrameRate, self->maxFrameRate); - if (self->audioSamplingRate) - xmlFree (self->audioSamplingRate); - if (self->mimeType) - xmlFree (self->mimeType); - if (self->segmentProfiles) - xmlFree (self->segmentProfiles); - if (self->codecs) - xmlFree (self->codecs); - if (self->scanType) - xmlFree (self->scanType); + g_free (self->audioSamplingRate); + g_free (self->mimeType); + g_free (self->segmentProfiles); + g_free (self->codecs); + g_free (self->scanType); g_list_free_full (self->FramePacking, (GDestroyNotify) gst_mpd_descriptor_type_node_free); g_list_free_full (self->AudioChannelConfiguration,
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/dash/gstmpdrepresentationnode.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/dash/gstmpdrepresentationnode.c
Changed
@@ -82,8 +82,7 @@ { GstMPDRepresentationNode *self = GST_MPD_REPRESENTATION_NODE (object); - if (self->id) - xmlFree (self->id); + g_free (self->id); g_strfreev (self->dependencyId); g_strfreev (self->mediaStreamStructureId); g_list_free_full (self->SubRepresentations,
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/dash/gstmpdsegmenttemplatenode.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/dash/gstmpdsegmenttemplatenode.c
Changed
@@ -42,15 +42,19 @@ GstMPDSegmentTemplateNode *self = GST_MPD_SEGMENT_TEMPLATE_NODE (object); switch (prop_id) { case PROP_MPD_SEGMENT_TEMPLATE_MEDIA: + g_free (self->media); self->media = g_value_dup_string (value); break; case PROP_MPD_SEGMENT_TEMPLATE_INDEX: + g_free (self->index); self->index = g_value_dup_string (value); break; case PROP_MPD_SEGMENT_TEMPLATE_INITIALIZATION: + g_free (self->initialization); self->initialization = g_value_dup_string (value); break; case PROP_MPD_SEGMENT_TEMPLATE_BITSTREAM_SWITCHING: + g_free (self->bitstreamSwitching); self->bitstreamSwitching = g_value_dup_string (value); break; default: @@ -88,14 +92,10 @@ { GstMPDSegmentTemplateNode *self = GST_MPD_SEGMENT_TEMPLATE_NODE (object); - if (self->media) - xmlFree (self->media); - if (self->index) - xmlFree (self->index); - if (self->initialization) - xmlFree (self->initialization); - if (self->bitstreamSwitching) - xmlFree (self->bitstreamSwitching); + g_free (self->media); + g_free (self->index); + g_free (self->initialization); + g_free (self->bitstreamSwitching); G_OBJECT_CLASS (gst_mpd_segment_template_node_parent_class)->finalize (object);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/dash/gstmpdsegmenturlnode.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/dash/gstmpdsegmenturlnode.c
Changed
@@ -69,8 +69,7 @@ { GstMPDSegmentURLNode *self = GST_MPD_SEGMENT_URL_NODE (object); - if (self->media) - xmlFree (self->media); + g_free (self->media); g_slice_free (GstXMLRange, self->mediaRange); if (self->index) xmlFree (self->index);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/gtk/gstgtkwaylandsink.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/gtk/gstgtkwaylandsink.c
Changed
@@ -414,6 +414,7 @@ FALSE); break; case PROP_DRM_DEVICE: + /* G_PARAM_CONSTRUCT_ONLY */ GST_OBJECT_LOCK (self); priv->drm_device = g_value_dup_string (value); GST_OBJECT_UNLOCK (self);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/lcevcencoder/gstlcevcencoder.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/lcevcencoder/gstlcevcencoder.c
Changed
@@ -213,6 +213,7 @@ GstLcevcEncoderPrivate *priv = gst_lcevc_encoder_get_instance_private (eil); g_clear_pointer (&priv->plugin_name, g_free); + g_clear_pointer (&priv->plugin_props, g_free); G_OBJECT_CLASS (parent_class)->finalize (obj); }
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/onnx/gstonnx.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/onnx/gstonnx.c
Changed
@@ -24,6 +24,18 @@ #include "config.h" #endif +/** + * SECTION:plugin-onnx + * @title: ONNX + * @short_description: A plugin for ONNX-Runtime + * + * A plugin containing the inference elements using the ONNX Runtime project. + * + * See https://onnxruntime.ai/ + * + * Since: 1.20 + */ + #include "gstonnxinference.h" static gboolean
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/onnx/gstonnxclient.h -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/onnx/gstonnxclient.h
Changed
@@ -30,6 +30,12 @@ GST_DEBUG_CATEGORY_EXTERN (onnx_inference_debug); +/** + * GstOnnxOptimizationLevel: + * + * Since: 1.20 + */ + typedef enum { GST_ONNX_OPTIMIZATION_LEVEL_DISABLE_ALL, @@ -38,6 +44,12 @@ GST_ONNX_OPTIMIZATION_LEVEL_ENABLE_ALL, } GstOnnxOptimizationLevel; +/** + * GstOnnxExecutionProvider: + * + * Since: 1.20 + */ + typedef enum { GST_ONNX_EXECUTION_PROVIDER_CPU,
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/onnx/gstonnxinference.cpp -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/onnx/gstonnxinference.cpp
Changed
@@ -54,7 +54,7 @@ * to enable users to easily add and remove meta data from json files. It can also dump * the names of all output layers, which can then be used to craft the json meta data file. * - * + * Since: 1.20 */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -331,6 +331,13 @@ GST_DEBUG_FUNCPTR (gst_onnx_inference_transform_caps); basetransform_class->set_caps = GST_DEBUG_FUNCPTR (gst_onnx_inference_set_caps); + + gst_type_mark_as_plugin_api (GST_TYPE_ONNX_OPTIMIZATION_LEVEL, + (GstPluginAPIFlags) 0); + gst_type_mark_as_plugin_api (GST_TYPE_ONNX_EXECUTION_PROVIDER, + (GstPluginAPIFlags) 0); + gst_type_mark_as_plugin_api (GST_TYPE_ML_MODEL_INPUT_IMAGE_FORMAT, + (GstPluginAPIFlags) 0); } static void
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/openal/gstopenalsrc.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/openal/gstopenalsrc.c
Changed
@@ -232,9 +232,11 @@ switch (prop_id) { case PROP_DEVICE: + g_free (openalsrc->default_device); openalsrc->default_device = g_value_dup_string (value); break; case PROP_DEVICE_NAME: + g_free (openalsrc->default_device_name); openalsrc->default_device_name = g_value_dup_string (value); break; default:
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/qroverlay/gstdebugqroverlay.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/qroverlay/gstdebugqroverlay.c
Changed
@@ -102,6 +102,7 @@ GST_RANK_NONE, GST_TYPE_DEBUG_QR_OVERLAY, qroverlay_element_init (plugin)); +static void gst_debug_qr_overlay_finalize (GObject * object); static void gst_debug_qr_overlay_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_debug_qr_overlay_get_property (GObject * object, guint prop_id, @@ -120,6 +121,7 @@ GST_DEBUG_CATEGORY_INIT (gst_debug_qr_overlay_debug, "debugqroverlay", 0, "Qrcode overlay element"); + gobject_class->finalize = gst_debug_qr_overlay_finalize; gobject_class->set_property = gst_debug_qr_overlay_set_property; gobject_class->get_property = gst_debug_qr_overlay_get_property; @@ -178,6 +180,18 @@ } static void +gst_debug_qr_overlay_finalize (GObject * object) +{ + GstDebugQROverlay *filter = GST_DEBUG_QR_OVERLAY (object); + + g_free (filter->extra_data_name); + g_free (filter->extra_data_str); + g_strfreev (filter->extra_data_array); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void gst_debug_qr_overlay_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { @@ -191,6 +205,7 @@ filter->extra_data_span_buffers = g_value_get_int64 (value); break; case PROP_EXTRA_DATA_NAME: + g_clear_pointer (&filter->extra_data_name, g_free); filter->extra_data_name = g_value_dup_string (value); break; case PROP_EXTRA_DATA_ARRAY:
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/qroverlay/gstqroverlay.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/qroverlay/gstqroverlay.c
Changed
@@ -121,6 +121,16 @@ } static void +gst_qr_overlay_finalize (GObject * object) +{ + GstQROverlay *self = GST_QR_OVERLAY (object); + + g_free (self->data); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void gst_qr_overlay_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { @@ -129,6 +139,7 @@ switch (prop_id) { case PROP_DATA: GST_OBJECT_LOCK (self); + g_free (self->data); self->data = g_value_dup_string (value); self->data_changed = TRUE; GST_OBJECT_UNLOCK (self); @@ -164,7 +175,7 @@ gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; - + gobject_class->finalize = gst_qr_overlay_finalize; gobject_class->set_property = gst_qr_overlay_set_property; gobject_class->get_property = gst_qr_overlay_get_property;
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/vulkan/vkh264dec.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/vulkan/vkh264dec.c
Changed
@@ -47,7 +47,6 @@ typedef struct _GstVulkanH264Decoder GstVulkanH264Decoder; typedef struct _GstVulkanH264DecoderClass GstVulkanH264DecoderClass; -typedef struct _GstVulkanH264Decoder GstVulkanH264Decoder; typedef struct _GstVulkanH264Picture GstVulkanH264Picture; typedef struct _SPS SPS; typedef struct _PPS PPS; @@ -1356,11 +1355,9 @@ GST_VULKAN_H264_DECODER_CLASS (g_klass); struct CData *cdata = class_data; gchar *long_name; - const gchar *name, *desc; + const gchar *name; name = "Vulkan H.264 decoder"; - desc = "A H.264 video decoder based on Vulkan"; - if (cdata->description) long_name = g_strdup_printf ("%s on %s", name, cdata->description); else @@ -1369,12 +1366,11 @@ vk_h264_class->device_index = cdata->device_index; gst_element_class_set_metadata (element_class, long_name, - "Codec/Decoder/Video/Hardware", desc, + "Codec/Decoder/Video/Hardware", "A H.264 video decoder based on Vulkan", "Víctor Jáquez <vjaquez@igalia.com>"); parent_class = g_type_class_peek_parent (g_klass); - gst_element_class_add_static_pad_template (element_class, &gst_vulkan_h264dec_sink_template); @@ -1410,6 +1406,10 @@ GST_DEBUG_FUNCPTR (gst_vulkan_h264_decoder_end_picture); h264decoder_class->output_picture = GST_DEBUG_FUNCPTR (gst_vulkan_h264_decoder_output_picture); + + g_free (long_name); + g_free (cdata->description); + g_free (cdata); } gboolean
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/vulkan/vkh265dec.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/vulkan/vkh265dec.c
Changed
@@ -46,13 +46,11 @@ typedef struct _GstVulkanH265Decoder GstVulkanH265Decoder; typedef struct _GstVulkanH265DecoderClass GstVulkanH265DecoderClass; -typedef struct _GstVulkanH265Decoder GstVulkanH265Decoder; typedef struct _GstVulkanH265Picture GstVulkanH265Picture; typedef struct _VPS VPS; typedef struct _SPS SPS; typedef struct _PPS PPS; - struct _SPS { StdVideoH265SequenceParameterSet sps; @@ -1675,11 +1673,9 @@ GST_VULKAN_H265_DECODER_CLASS (g_klass); struct CData *cdata = class_data; gchar *long_name; - const gchar *name, *desc; + const gchar *name; name = "Vulkan H.265 decoder"; - desc = "A H.265 video decoder based on Vulkan"; - if (cdata->description) long_name = g_strdup_printf ("%s on %s", name, cdata->description); else @@ -1688,7 +1684,7 @@ vk_h265_class->device_index = cdata->device_index; gst_element_class_set_metadata (element_class, long_name, - "Codec/Decoder/Video/Hardware", desc, + "Codec/Decoder/Video/Hardware", "A H.265 video decoder based on Vulkan", "Víctor Jáquez <vjaquez@igalia.com>"); parent_class = g_type_class_peek_parent (g_klass); @@ -1726,6 +1722,10 @@ GST_DEBUG_FUNCPTR (gst_vulkan_h265_decoder_end_picture); h265decoder_class->output_picture = GST_DEBUG_FUNCPTR (gst_vulkan_h265_decoder_output_picture); + + g_free (long_name); + g_free (cdata->description); + g_free (cdata); } gboolean
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/vulkan/vksink.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/vulkan/vksink.c
Changed
@@ -136,10 +136,9 @@ element_class = GST_ELEMENT_CLASS (g_klass); struct CData *cdata = class_data; gchar *long_name; - const gchar *name, *desc; + const gchar *name; name = "Vulkan Video sink"; - desc = "A videosink based on Vulkan"; if (cdata->description) long_name = g_strdup_printf ("%s on %s", name, cdata->description); @@ -167,7 +166,8 @@ GST_TYPE_VULKAN_DEVICE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); gst_element_class_set_metadata (element_class, long_name, - "Sink/Video", desc, "Matthew Waters <matthew@centricular.com>"); + "Sink/Video", "A videosink based on Vulkan", + "Matthew Waters <matthew@centricular.com>"); parent_class = g_type_class_peek_parent (g_klass); @@ -186,6 +186,10 @@ gstvideosink_class->show_frame = GST_DEBUG_FUNCPTR (gst_vulkan_sink_show_frame); + + g_free (long_name); + g_free (cdata->description); + g_free (cdata); } static gpointer
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/wayland/gstwaylandsink.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/wayland/gstwaylandsink.c
Changed
@@ -294,6 +294,7 @@ switch (prop_id) { case PROP_DISPLAY: GST_OBJECT_LOCK (self); + g_free (self->display_name); self->display_name = g_value_dup_string (value); GST_OBJECT_UNLOCK (self); break; @@ -307,6 +308,7 @@ FALSE); break; case PROP_DRM_DEVICE: + /* G_PARAM_CONSTRUCT_ONLY */ GST_OBJECT_LOCK (self); self->drm_device = g_value_dup_string (value); GST_OBJECT_UNLOCK (self);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/webrtc/gstwebrtcbin.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/webrtc/gstwebrtcbin.c
Changed
@@ -3065,11 +3065,9 @@ { gboolean ret = TRUE; - if (trans->local_rtx_ssrc_map) - gst_structure_free (trans->local_rtx_ssrc_map); - - trans->local_rtx_ssrc_map = - gst_structure_new_empty ("application/x-rtp-ssrc-map"); + if (!trans->local_rtx_ssrc_map) + trans->local_rtx_ssrc_map = + gst_structure_new_empty ("application/x-rtp-ssrc-map"); if (trans->do_nack) { struct media_payload_map_item *item; @@ -3640,8 +3638,9 @@ gst_clear_structure (&extmap); - { - const GstStructure *s = gst_caps_get_structure (caps, 0); + // create rtx entry for each format type + for (i = 0; i < gst_caps_get_size (caps); i++) { + const GstStructure *s = gst_caps_get_structure (caps, i); gint clockrate = -1; gint rtx_target_pt; guint rtx_target_ssrc = -1; @@ -6510,19 +6509,27 @@ if (trans_caps) { GstCaps *offer_caps = _rtp_caps_from_media (media); GstCaps *caps = gst_caps_intersect (offer_caps, trans_caps); - gst_caps_unref (offer_caps); - gst_caps_unref (trans_caps); if (caps) { if (!gst_caps_is_empty (caps)) { GST_LOG_OBJECT (webrtc, "found compatible transceiver %" GST_PTR_FORMAT " for offer media %u", trans, i); gst_caps_unref (caps); + gst_caps_unref (offer_caps); + gst_caps_unref (trans_caps); break; + } else { + GST_LOG_OBJECT (webrtc, + "tried but failed to intersect caps from" + " offer for m-line %d (%" GST_PTR_FORMAT + ") with caps from codec preferences and transceiver %" + GST_PTR_FORMAT, i, offer_caps, trans_caps); } gst_caps_unref (caps); caps = NULL; } + gst_caps_unref (offer_caps); + gst_caps_unref (trans_caps); } trans = NULL; }
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/ext/wpe/gstwpevideosrc.cpp -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/ext/wpe/gstwpevideosrc.cpp
Changed
@@ -957,7 +957,7 @@ G_TYPE_NONE, 1, G_TYPE_BYTES); /** - * GstWpeSrc::run-javascript: + * GstWpeVideoSrc::run-javascript: * @src: the object which received the signal * @script: the script to run *
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/analytics/meson.build -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/analytics/meson.build
Changed
@@ -39,7 +39,7 @@ link_args : '-lm') pkgconfig.generate(gstanalytics, - libraries : gst_dep, gstbase_dep, '-lm', + libraries : gst_dep, gstbase_dep, gstvideo_dep, '-lm', variables : pkgconfig_variables, subdirs : pkgconfig_subdirs, name : pkg_name,
View file
_service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/codecparsers/gsth265parser-private.h
Added
@@ -0,0 +1,32 @@ +/* GStreamer + * Copyright (C) 2025 Seungha Yang <seungha@centricular.com> + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include <gst/gst.h> +#include <gst/codecparsers/gsth265parser.h> + +G_BEGIN_DECLS + +GST_CODEC_PARSERS_API +GstH265ParserResult gst_h265_parser_link_slice_hdr (GstH265Parser * parser, + GstH265SliceHdr * slice, + guint pps_id); + +G_END_DECLS
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/codecparsers/gsth265parser.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/codecparsers/gsth265parser.c
Changed
@@ -66,10 +66,13 @@ #include "nalutils.h" #include "gsth265parser.h" +#include "gsth265parser-private.h" #include <gst/base/gstbytereader.h> #include <gst/base/gstbitreader.h> +#define MAX_DPB_SIZE 16 + #ifndef GST_DISABLE_GST_DEBUG #define GST_CAT_DEFAULT gst_h265_debug_category_get() static GstDebugCategory * @@ -1894,7 +1897,7 @@ for (i = (vps->sub_layer_ordering_info_present_flag ? 0 : vps->max_sub_layers_minus1); i <= vps->max_sub_layers_minus1; i++) { - READ_UE_MAX (&nr, vps->max_dec_pic_buffering_minus1i, G_MAXUINT32 - 1); + READ_UE_MAX (&nr, vps->max_dec_pic_buffering_minus1i, MAX_DPB_SIZE - 1); READ_UE_MAX (&nr, vps->max_num_reorder_picsi, vps->max_dec_pic_buffering_minus1i); READ_UE_MAX (&nr, vps->max_latency_increase_plus1i, G_MAXUINT32 - 1); @@ -2081,7 +2084,7 @@ for (i = (sps->sub_layer_ordering_info_present_flag ? 0 : sps->max_sub_layers_minus1); i <= sps->max_sub_layers_minus1; i++) { - READ_UE_MAX (&nr, sps->max_dec_pic_buffering_minus1i, 16); + READ_UE_MAX (&nr, sps->max_dec_pic_buffering_minus1i, MAX_DPB_SIZE - 1); READ_UE_MAX (&nr, sps->max_num_reorder_picsi, sps->max_dec_pic_buffering_minus1i); READ_UE_MAX (&nr, sps->max_latency_increase_plus1i, G_MAXUINT32 - 1); @@ -2804,6 +2807,8 @@ READ_UINT8 (&nr, slice->colour_plane_id, 2); if (!GST_H265_IS_NAL_TYPE_IDR (nalu->type)) { + const GstH265ShortTermRefPicSet *ref_pic_sets = NULL; + READ_UINT16 (&nr, slice->pic_order_cnt_lsb, (sps->log2_max_pic_order_cnt_lsb_minus4 + 4)); @@ -2820,24 +2825,56 @@ slice->short_term_ref_pic_set_size = (nal_reader_get_pos (&nr) - pos) - (8 * (nal_reader_get_epb_count (&nr) - epb_pos)); + + ref_pic_sets = &slice->short_term_ref_pic_sets; } else if (sps->num_short_term_ref_pic_sets > 1) { /* 7.4.7.1 short_term_ref_pic_set_idx */ const guint n = gst_util_ceil_log2 (sps->num_short_term_ref_pic_sets); READ_UINT8 (&nr, slice->short_term_ref_pic_set_idx, n); CHECK_ALLOWED_MAX (slice->short_term_ref_pic_set_idx, sps->num_short_term_ref_pic_sets - 1); + ref_pic_sets = + &sps->short_term_ref_pic_setslice->short_term_ref_pic_set_idx; + } else { + ref_pic_sets = &sps->short_term_ref_pic_set0; } if (sps->long_term_ref_pics_present_flag) { guint32 limit; guint pos = nal_reader_get_pos (&nr); guint epb_pos = nal_reader_get_epb_count (&nr); + gint max_num_long_term_pics = 0; + gint TwoVersionsOfCurrDecPicFlag = 0; - if (sps->num_long_term_ref_pics_sps > 0) + if (sps->num_long_term_ref_pics_sps > 0) { READ_UE_MAX (&nr, slice->num_long_term_sps, sps->num_long_term_ref_pics_sps); + } + + /* 7.4.3.3.3 */ + if (pps->pps_scc_extension_flag && + pps->pps_scc_extension_params.pps_curr_pic_ref_enabled_flag && + (sps->sample_adaptive_offset_enabled_flag || + !pps->deblocking_filter_disabled_flag || + pps->deblocking_filter_override_enabled_flag)) { + TwoVersionsOfCurrDecPicFlag = 1; + } + + /* Calculated upper bound num_long_term_pics can have. 7.4.7.1 */ + max_num_long_term_pics = + /* sps_max_dec_pic_buffering_minus1TemporalId, allowed max is + * MaxDpbSize - 1 */ + MAX_DPB_SIZE - 1 + - (gint) slice->num_long_term_sps + - (gint) ref_pic_sets->NumNegativePics + - (gint) ref_pic_sets->NumPositivePics - + TwoVersionsOfCurrDecPicFlag; + if (max_num_long_term_pics < 0) { + GST_WARNING ("Invalid stream, too many reference pictures"); + goto error; + } - READ_UE_MAX (&nr, slice->num_long_term_pics, 16); + READ_UE_MAX (&nr, slice->num_long_term_pics, max_num_long_term_pics); limit = slice->num_long_term_sps + slice->num_long_term_pics; for (i = 0; i < limit; i++) { if (i < slice->num_long_term_sps) { @@ -3403,19 +3440,14 @@ return GST_H265_PARSER_ERROR; } - if (sps->vps) { - GstH265VPS *vps = gst_h265_parser_get_vps (parser, sps->vps->id); - if (!vps || vps != sps->vps) { - GST_WARNING ("Linked VPS is not identical to internal VPS"); - return GST_H265_PARSER_BROKEN_LINK; - } - } - GST_DEBUG ("Updating sequence parameter set with id: %d", sps->id); parser->spssps->id = *sps; parser->last_sps = &parser->spssps->id; + if (sps->vps) + parser->spssps->id.vps = gst_h265_parser_get_vps (parser, sps->vps->id); + return GST_H265_PARSER_OK; } @@ -3434,8 +3466,6 @@ GstH265ParserResult gst_h265_parser_update_pps (GstH265Parser * parser, GstH265PPS * pps) { - GstH265SPS *sps; - g_return_val_if_fail (parser != NULL, GST_H265_PARSER_ERROR); g_return_val_if_fail (pps != NULL, GST_H265_PARSER_ERROR); g_return_val_if_fail (pps->id < GST_H265_MAX_PPS_COUNT, @@ -3446,22 +3476,14 @@ return GST_H265_PARSER_ERROR; } - if (!pps->sps) { - GST_WARNING ("No linked SPS struct"); - return GST_H265_PARSER_BROKEN_LINK; - } - - sps = gst_h265_parser_get_sps (parser, pps->sps->id); - if (!sps || sps != pps->sps) { - GST_WARNING ("Linked SPS is not identical to internal SPS"); - return GST_H265_PARSER_BROKEN_LINK; - } - GST_DEBUG ("Updating picture parameter set with id: %d", pps->id); parser->ppspps->id = *pps; parser->last_pps = &parser->ppspps->id; + if (pps->sps) + parser->ppspps->id.sps = gst_h265_parser_get_sps (parser, pps->sps->id); + return GST_H265_PARSER_OK; } @@ -5148,3 +5170,32 @@ #undef READ_CONFIG_UINT16 #undef SKIP_CONFIG_BITS } + +GstH265ParserResult +gst_h265_parser_link_slice_hdr (GstH265Parser * parser, GstH265SliceHdr * slice, + guint pps_id) +{ + GstH265ParserResult ret; + GstH265PPS *pps; + + g_return_val_if_fail (parser, GST_H265_PARSER_ERROR); + g_return_val_if_fail (slice, GST_H265_PARSER_ERROR); + g_return_val_if_fail (pps_id < GST_H265_MAX_PPS_COUNT, GST_H265_PARSER_ERROR); + + pps = gst_h265_parser_get_pps (parser, pps_id); + if (!pps) { + GST_WARNING + ("couldn't find associated picture parameter set with id: %d", pps_id); + return GST_H265_PARSER_BROKEN_LINK; + } + + ret = gst_h265_parser_fill_pps (parser, pps); + if (ret != GST_H265_PARSER_OK) { + GST_WARNING ("couldn't fill pps id: %d", pps_id); + return ret; + } + + slice->pps = pps; + + return GST_H265_PARSER_OK; +}
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/codecs/gsth265decoder.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/codecs/gsth265decoder.c
Changed
@@ -32,6 +32,7 @@ #include <gst/base/base.h> #include "gsth265decoder.h" +#include <gst/codecparsers/gsth265parser-private.h> GST_DEBUG_CATEGORY (gst_h265_decoder_debug); #define GST_CAT_DEFAULT gst_h265_decoder_debug @@ -67,6 +68,7 @@ GstH265DecoderFormat in_format; GstH265DecoderAlign align; GstH265Parser *parser; + GstH265Parser *preproc_parser; GstH265Dpb *dpb; /* 0: frame or field-pair interlaced stream @@ -144,10 +146,13 @@ { union { + GstH265VPS vps; GstH265SPS sps; + GstH265PPS pps; GstH265Slice slice; } unit; - gboolean is_slice; + GstH265NalUnitType nalu_type; + guint pps_id; } GstH265DecoderNalUnit; typedef struct @@ -266,6 +271,7 @@ GstH265DecoderPrivate *priv = self->priv; priv->parser = gst_h265_parser_new (); + priv->preproc_parser = gst_h265_parser_new (); priv->dpb = gst_h265_dpb_new (); priv->new_bitstream = TRUE; priv->prev_nal_is_eos = FALSE; @@ -290,6 +296,11 @@ priv->parser = NULL; } + if (priv->preproc_parser) { + gst_h265_parser_free (priv->preproc_parser); + priv->preproc_parser = NULL; + } + if (priv->dpb) { gst_h265_dpb_free (priv->dpb); priv->dpb = NULL; @@ -626,7 +637,7 @@ GArray *messages = NULL; guint i; - pres = gst_h265_parser_parse_sei (priv->parser, nalu, &messages); + pres = gst_h265_parser_parse_sei (priv->preproc_parser, nalu, &messages); if (pres != GST_H265_PARSER_OK) { GST_WARNING_OBJECT (self, "Failed to parse SEI, result %d", pres); @@ -904,7 +915,8 @@ memset (&slice, 0, sizeof (GstH265Slice)); - pres = gst_h265_parser_parse_slice_hdr (priv->parser, nalu, &slice.header); + pres = gst_h265_parser_parse_slice_hdr (priv->preproc_parser, + nalu, &slice.header); if (pres != GST_H265_PARSER_OK) return pres; @@ -948,7 +960,9 @@ priv->no_output_of_prior_pics_flag = TRUE; decoder_nalu.unit.slice = slice; - decoder_nalu.is_slice = TRUE; + decoder_nalu.nalu_type = nalu->type; + decoder_nalu.pps_id = slice.header.pps->id; + g_array_append_val (priv->nalu, decoder_nalu); return GST_H265_PARSER_OK; @@ -967,21 +981,33 @@ GST_LOG_OBJECT (self, "Parsed nal type: %d, offset %d, size %d", nalu->type, nalu->offset, nalu->size); + memset (&decoder_nalu, 0, sizeof (GstH265DecoderNalUnit)); + decoder_nalu.nalu_type = nalu->type; + switch (nalu->type) { case GST_H265_NAL_VPS: - ret = gst_h265_parser_parse_vps (priv->parser, nalu, &vps); + ret = gst_h265_parser_parse_vps (priv->preproc_parser, nalu, &vps); + if (ret != GST_H265_PARSER_OK) + break; + + decoder_nalu.unit.vps = vps; + g_array_append_val (priv->nalu, decoder_nalu); break; case GST_H265_NAL_SPS: - ret = gst_h265_parser_parse_sps (priv->parser, nalu, &sps, TRUE); + ret = gst_h265_parser_parse_sps (priv->preproc_parser, nalu, &sps, TRUE); if (ret != GST_H265_PARSER_OK) break; - memset (&decoder_nalu, 0, sizeof (GstH265DecoderNalUnit)); decoder_nalu.unit.sps = sps; g_array_append_val (priv->nalu, decoder_nalu); break; case GST_H265_NAL_PPS: - ret = gst_h265_parser_parse_pps (priv->parser, nalu, &pps); + ret = gst_h265_parser_parse_pps (priv->preproc_parser, nalu, &pps); + if (ret != GST_H265_PARSER_OK) + break; + + decoder_nalu.unit.pps = pps; + g_array_append_val (priv->nalu, decoder_nalu); break; case GST_H265_NAL_PREFIX_SEI: case GST_H265_NAL_SUFFIX_SEI: @@ -1020,14 +1046,53 @@ return ret; } +static inline gboolean +is_slice_nalu (GstH265NalUnitType type) +{ + if ((type >= GST_H265_NAL_SLICE_TRAIL_N && + type <= GST_H265_NAL_SLICE_RASL_R) || + (type >= GST_H265_NAL_SLICE_BLA_W_LP && + type <= GST_H265_NAL_SLICE_CRA_NUT)) { + return TRUE; + } + + return FALSE; +} + static GstFlowReturn gst_h265_decoder_decode_nalu (GstH265Decoder * self, GstH265DecoderNalUnit * nalu) { - if (nalu->is_slice) - return gst_h265_decoder_process_slice (self, &nalu->unit.slice); + GstH265DecoderPrivate *priv = self->priv; + GstH265ParserResult rst; - return GST_FLOW_OK; + switch (nalu->nalu_type) { + case GST_H265_NAL_VPS: + gst_h265_parser_update_vps (priv->parser, &nalu->unit.vps); + return GST_FLOW_OK; + case GST_H265_NAL_SPS: + gst_h265_parser_update_sps (priv->parser, &nalu->unit.sps); + return GST_FLOW_OK; + case GST_H265_NAL_PPS: + gst_h265_parser_update_pps (priv->parser, &nalu->unit.pps); + return GST_FLOW_OK; + default: + if (!is_slice_nalu (nalu->nalu_type)) { + GST_WARNING_OBJECT (self, "Unexpected nal type %d", nalu->nalu_type); + return GST_FLOW_OK; + } + break; + } + + rst = gst_h265_parser_link_slice_hdr (priv->parser, + &nalu->unit.slice.header, nalu->pps_id); + + if (rst != GST_H265_PARSER_OK) { + GST_ERROR_OBJECT (self, "Couldn't update slice header"); + return GST_FLOW_ERROR; + } + + return gst_h265_decoder_process_slice (self, &nalu->unit.slice); } static void @@ -1112,6 +1177,7 @@ GST_WARNING_OBJECT (self, "Failed to parse VPS"); goto out; } + gst_h265_parser_update_vps (priv->preproc_parser, &vps); break; case GST_H265_NAL_SPS: pres = gst_h265_parser_parse_sps (parser, nalu, &sps, TRUE); @@ -1119,6 +1185,7 @@ GST_WARNING_OBJECT (self, "Failed to parse SPS"); goto out; } + gst_h265_parser_update_sps (priv->preproc_parser, &sps); break; case GST_H265_NAL_PPS: pres = gst_h265_parser_parse_pps (parser, nalu, &pps); @@ -1126,6 +1193,7 @@ GST_WARNING_OBJECT (self, "Failed to parse PPS"); goto out; } + gst_h265_parser_update_pps (priv->preproc_parser, &pps); break; default: break; @@ -2055,7 +2123,7 @@ gsize consumed; do { - pres = gst_h265_parser_identify_and_split_nalu_hevc (priv->parser, + pres = gst_h265_parser_identify_and_split_nalu_hevc (priv->preproc_parser, map.data, offset, map.size, priv->nal_length_size, priv->split_nalu, &consumed); if (pres != GST_H265_PARSER_OK) @@ -2075,7 +2143,7 @@ offset += consumed; } while (pres == GST_H265_PARSER_OK); } else { - pres = gst_h265_parser_identify_nalu (priv->parser, + pres = gst_h265_parser_identify_nalu (priv->preproc_parser, map.data, 0, map.size, &nalu); if (pres == GST_H265_PARSER_NO_NAL_END) @@ -2086,7 +2154,7 @@ if (pres != GST_H265_PARSER_OK) break; - pres = gst_h265_parser_identify_nalu (priv->parser, + pres = gst_h265_parser_identify_nalu (priv->preproc_parser, map.data, nalu.offset + nalu.size, map.size, &nalu); if (pres == GST_H265_PARSER_NO_NAL_END) pres = GST_H265_PARSER_OK; @@ -2142,7 +2210,7 @@ if (!nalu) return; - if (nalu->is_slice) + if (is_slice_nalu (nalu->nalu_type)) gst_h265_slice_hdr_free (&nalu->unit.slice.header); memset (nalu, 0, sizeof (GstH265DecoderNalUnit));
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/codecs/gsth266decoder.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/codecs/gsth266decoder.c
Changed
@@ -450,7 +450,7 @@ } /* TODO: */ - + g_clear_pointer (&messages, g_array_unref); return GST_H266_PARSER_OK; }
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/cuda/meson.build -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/cuda/meson.build
Changed
@@ -48,15 +48,12 @@ subdir_done() endif -# Linux ARM would need -latomic for std::atomic<int64_t> -if host_system == 'linux' and host_machine.cpu_family() in 'aarch64', 'arm' - libatomic_dep = cxx.find_library('atomic', required: get_option('cuda-nvmm')) - if not libatomic_dep.found() - subdir_done() - endif - - gstcuda_platform_dep += libatomic_dep -endif +# Check for libatomic for use of C11 atomics: some architectures need +# to link explicitly to this library. +# TODO: Once meson 1.7 is in use, this can be updated to +# dependency('atomic') +atomic_dep = cxx.find_library('atomic', required: false) +gstcuda_platform_dep += atomic_dep cuda_win32_headers = 'initguid.h',
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/d3d12/gstd3d12converter.cpp -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/d3d12/gstd3d12converter.cpp
Changed
@@ -1264,23 +1264,11 @@ } static gboolean -gst_d3d12_converter_update_src_rect (GstD3D12Converter * self) +gst_d3d12_converter_update_ctx_src_rect (GstD3D12Converter * self, + ConvertCtxPtr & ctx, VertexData vertex_data4) { - auto priv = self->priv; - VertexData vertex_data4; HRESULT hr; - FLOAT u0, u1, v0, v1, off_u, off_v; - gint texture_width = priv->input_texture_width; - gint texture_height = priv->input_texture_height; - - if (!priv->update_src_rect) - return TRUE; - - priv->update_src_rect = FALSE; - GST_DEBUG_OBJECT (self, "Updating vertex buffer"); - - auto ctx = priv->main_ctx; if (!ctx->vertex_upload) { D3D12_HEAP_PROPERTIES heap_prop = CD3DX12_HEAP_PROPERTIES (D3D12_HEAP_TYPE_UPLOAD); @@ -1296,6 +1284,36 @@ } } + guint8 *data; + CD3DX12_RANGE range (0, 0); + hr = ctx->vertex_upload->Map (0, &range, (void **) &data); + if (!gst_d3d12_result (hr, self->device)) { + GST_ERROR_OBJECT (self, "Couldn't map vertex buffer, hr: 0x%x", (guint) hr); + return FALSE; + } + + memcpy (data, vertex_data, g_vertex_buf_size); + ctx->vertex_upload->Unmap (0, nullptr); + + return TRUE; +} + +static gboolean +gst_d3d12_converter_update_src_rect (GstD3D12Converter * self) +{ + auto priv = self->priv; + VertexData vertex_data4; + FLOAT u0, u1, v0, v1, off_u, off_v; + gint texture_width = priv->input_texture_width; + gint texture_height = priv->input_texture_height; + + if (!priv->update_src_rect) + return TRUE; + + priv->update_src_rect = FALSE; + + GST_DEBUG_OBJECT (self, "Updating vertex buffer"); + /* * (u0, v0) -- (u1, v0) * | | @@ -1352,16 +1370,15 @@ vertex_data3.texture.u = u1; vertex_data3.texture.v = v1; - guint8 *data; - CD3DX12_RANGE range (0, 0); - hr = ctx->vertex_upload->Map (0, &range, (void **) &data); - if (!gst_d3d12_result (hr, self->device)) { - GST_ERROR_OBJECT (self, "Couldn't map vertex buffer, hr: 0x%x", (guint) hr); + if (!gst_d3d12_converter_update_ctx_src_rect (self, priv->main_ctx, + vertex_data)) { return FALSE; } - memcpy (data, vertex_data, g_vertex_buf_size); - ctx->vertex_upload->Unmap (0, nullptr); + if (priv->post_mipgen_ctx) { + return gst_d3d12_converter_update_ctx_src_rect (self, priv->post_mipgen_ctx, + vertex_data); + } return TRUE; } @@ -1506,6 +1523,14 @@ break; } + if (priv->post_mipgen_ctx) { + auto other_comm = priv->post_mipgen_ctx->comm; + for (guint i = 0; i < GST_VIDEO_MAX_PLANES; i++) { + other_comm->viewporti = comm->viewporti; + other_comm->scissor_recti = comm->scissor_recti; + } + } + priv->update_dest_rect = FALSE; return TRUE;
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/mse/gstappendpipeline.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/mse/gstappendpipeline.c
Changed
@@ -683,6 +683,9 @@ background_task_start (BackgroundTask * task) { gst_bus_set_flushing (task->bus, FALSE); + gchar *name = g_strdup_printf ("%s:bg", GST_OBJECT_NAME (task->pipeline)); + g_object_set (task->task, "name", name, NULL); + g_clear_pointer (&name, g_free); return gst_task_start (task->task); }
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/mse/gstmediasource.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/mse/gstmediasource.c
Changed
@@ -105,7 +105,10 @@ #define DEFAULT_POSITION GST_CLOCK_TIME_NONE #define DEFAULT_DURATION GST_CLOCK_TIME_NONE -static void rebuild_active_source_buffers (GstMediaSource * self); +static void rebuild_active_source_buffers_unlocked (GstMediaSource * self); +static void detach_unlocked (GstMediaSource * self); +static void set_duration_unlocked (GstMediaSource * self, + GstClockTime duration); /** * gst_media_source_is_type_supported: @@ -178,7 +181,7 @@ { GstMediaSource *self = (GstMediaSource *) object; - gst_media_source_detach (self); + detach_unlocked (self); g_clear_object (&self->active_buffers); @@ -471,16 +474,37 @@ g_return_if_fail (GST_IS_MEDIA_SOURCE (self)); g_return_if_fail (GST_IS_MSE_SRC (element)); - if (is_attached (self)) - gst_media_source_detach (self); + GST_OBJECT_LOCK (self); + if (is_attached (self)) { + detach_unlocked (self); + } - self->element = gst_object_ref_sink (element); + self->element = gst_object_ref (element); gst_mse_src_attach (element, self); self->ready_state = GST_MEDIA_SOURCE_READY_STATE_OPEN; + GST_OBJECT_UNLOCK (self); + schedule_event (self, ON_SOURCE_OPEN); } +static void +detach_unlocked (GstMediaSource * self) +{ + self->ready_state = GST_MEDIA_SOURCE_READY_STATE_CLOSED; + set_duration_unlocked (self, GST_CLOCK_TIME_NONE); + + gst_source_buffer_list_remove_all (self->active_buffers); + empty_buffers (self); + + if (is_attached (self)) { + gst_mse_src_detach (self->element); + gst_clear_object (&self->element); + } + + schedule_event (self, ON_SOURCE_CLOSE); +} + /** * gst_media_source_detach: * @self: #GstMediaSource instance @@ -494,18 +518,9 @@ { g_return_if_fail (GST_IS_MEDIA_SOURCE (self)); - self->ready_state = GST_MEDIA_SOURCE_READY_STATE_CLOSED; - gst_media_source_set_duration (self, GST_CLOCK_TIME_NONE, NULL); - - gst_source_buffer_list_remove_all (self->active_buffers); - empty_buffers (self); - - if (is_attached (self)) { - gst_mse_src_detach (self->element); - gst_clear_object (&self->element); - } - - schedule_event (self, ON_SOURCE_CLOSE); + GST_OBJECT_LOCK (self); + detach_unlocked (self); + GST_OBJECT_UNLOCK (self); } /** @@ -595,7 +610,12 @@ gst_media_source_get_ready_state (GstMediaSource * self) { g_return_val_if_fail (GST_IS_MEDIA_SOURCE (self), DEFAULT_READY_STATE); - return self->ready_state; + + GST_OBJECT_LOCK (self); + GstMediaSourceReadyState ready_state = self->ready_state; + GST_OBJECT_UNLOCK (self); + + return ready_state; } /** @@ -611,9 +631,14 @@ gst_media_source_get_position (GstMediaSource * self) { g_return_val_if_fail (GST_IS_MEDIA_SOURCE (self), DEFAULT_POSITION); - if (is_attached (self)) - return gst_mse_src_get_position (self->element); - return DEFAULT_POSITION; + + GST_OBJECT_LOCK (self); + GstClockTime position = + is_attached (self) ? gst_mse_src_get_position (self->element) : + DEFAULT_POSITION; + GST_OBJECT_UNLOCK (self); + + return position; } /** @@ -631,9 +656,22 @@ gst_media_source_get_duration (GstMediaSource * self) { g_return_val_if_fail (GST_IS_MEDIA_SOURCE (self), DEFAULT_DURATION); - if (self->ready_state == GST_MEDIA_SOURCE_READY_STATE_CLOSED) - return GST_CLOCK_TIME_NONE; - return self->duration; + + GST_OBJECT_LOCK (self); + GstClockTime duration = + self->ready_state == + GST_MEDIA_SOURCE_READY_STATE_CLOSED ? GST_CLOCK_TIME_NONE : + self->duration; + GST_OBJECT_UNLOCK (self); + + return duration; +} + +static void +set_duration_unlocked (GstMediaSource * self, GstClockTime duration) +{ + self->duration = duration; + update_duration (self); } /** @@ -654,8 +692,12 @@ GError ** error) { g_return_val_if_fail (GST_IS_MEDIA_SOURCE (self), FALSE); + + GST_OBJECT_LOCK (self); self->duration = duration; update_duration (self); + GST_OBJECT_UNLOCK (self); + g_object_notify_by_pspec (G_OBJECT (self), propertiesPROP_DURATION); return TRUE; } @@ -665,8 +707,12 @@ gpointer user_data) { GstMediaSource *self = GST_MEDIA_SOURCE (user_data); + + GST_OBJECT_LOCK (self); + if (!is_attached (self)) { GST_DEBUG_OBJECT (self, "received init segment while detached, ignoring"); + GST_OBJECT_UNLOCK (self); return; } @@ -683,6 +729,8 @@ gst_object_unref (buf); } + GST_OBJECT_UNLOCK (self); + gst_mse_src_emit_streams (self->element, (GstMediaSourceTrack **) all_tracks->pdata, all_tracks->len); @@ -731,9 +779,8 @@ } static void -rebuild_active_source_buffers (GstMediaSource * self) +rebuild_active_source_buffers_unlocked (GstMediaSource * self) { - // TODO: Lock the source buffer lists GST_DEBUG_OBJECT (self, "rebuilding active source buffers"); GHashTable *previously_active = source_buffer_list_as_set (self->active_buffers); @@ -777,7 +824,10 @@ on_active_state_changed (GstSourceBuffer * source_buffer, gpointer user_data) { GstMediaSource *self = GST_MEDIA_SOURCE (user_data); - rebuild_active_source_buffers (self); + + GST_OBJECT_LOCK (self); + rebuild_active_source_buffers_unlocked (self); + GST_OBJECT_UNLOCK (self); } /** @@ -815,11 +865,13 @@ return NULL; } + GST_OBJECT_LOCK (self); + if (self->ready_state != GST_MEDIA_SOURCE_READY_STATE_OPEN) { g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_INVALID_STATE, "media source is not open"); - return NULL; + goto error; } GstSourceBufferCallbacks callbacks = { @@ -835,12 +887,18 @@ g_propagate_prefixed_error (error, source_buffer_error, "failed to create source buffer"); gst_clear_object (&buf); - return NULL; + goto error; } gst_source_buffer_list_append (self->buffers, buf); + GST_OBJECT_UNLOCK (self); + return buf; + +error: + GST_OBJECT_UNLOCK (self); + return NULL; } /** @@ -866,11 +924,13 @@ g_return_val_if_fail (GST_IS_MEDIA_SOURCE (self), FALSE); g_return_val_if_fail (GST_IS_SOURCE_BUFFER (buffer), FALSE); + GST_OBJECT_LOCK (self); + if (!gst_source_buffer_list_contains (self->buffers, buffer)) { g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_NOT_FOUND, "the supplied source buffer was not found in this media source"); - return FALSE; + goto error; } if (gst_source_buffer_get_updating (buffer)) @@ -881,7 +941,13 @@ gst_object_unparent (GST_OBJECT (buffer)); gst_source_buffer_list_remove (self->buffers, buffer); + GST_OBJECT_UNLOCK (self); + return TRUE; + +error: + GST_OBJECT_UNLOCK (self); + return FALSE; } static void @@ -917,23 +983,27 @@ { g_return_val_if_fail (GST_IS_MEDIA_SOURCE (self), FALSE); + GST_OBJECT_LOCK (self); + if (self->ready_state != GST_MEDIA_SOURCE_READY_STATE_OPEN) { g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_INVALID_STATE, "media source is not open"); - return FALSE; + goto error; } if (is_updating (self)) { g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_INVALID_STATE, "some buffers are still updating"); - return FALSE; + goto error; } self->ready_state = GST_MEDIA_SOURCE_READY_STATE_ENDED; schedule_event (self, ON_SOURCE_ENDED); + GST_OBJECT_UNLOCK (self); + switch (eos_error) { case GST_MEDIA_SOURCE_EOS_ERROR_NETWORK: network_error (self); @@ -948,6 +1018,10 @@ } return TRUE; + +error: + GST_OBJECT_UNLOCK (self); + return FALSE; } /** @@ -973,24 +1047,33 @@ GstClockTime start, GstClockTime end, GError ** error) { g_return_val_if_fail (GST_IS_MEDIA_SOURCE (self), FALSE); + + GST_OBJECT_LOCK (self); + if (self->ready_state != GST_MEDIA_SOURCE_READY_STATE_OPEN) { g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_INVALID_STATE, "media source is not open"); - return FALSE; + goto error; } if (start > end) { g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_TYPE, "bad time range: start must be earlier than end"); - return FALSE; + goto error; } self->live_seekable_range.start = start; self->live_seekable_range.end = end; + GST_OBJECT_UNLOCK (self); + return TRUE; + +error: + GST_OBJECT_UNLOCK (self); + return FALSE; } /** @@ -1015,22 +1098,30 @@ { g_return_val_if_fail (GST_IS_MEDIA_SOURCE (self), FALSE); + GST_OBJECT_LOCK (self); + if (self->ready_state != GST_MEDIA_SOURCE_READY_STATE_OPEN) { g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_INVALID_STATE, "media source is not open"); - return FALSE; + goto error; } reset_live_seekable_range (self); + GST_OBJECT_UNLOCK (self); + return TRUE; + +error: + GST_OBJECT_UNLOCK (self); + return FALSE; } /** * gst_media_source_get_live_seekable_range: * @self: #GstMediaSource instance - * @range: (out) (transfer none): time range + * @range: (out caller-allocates) (transfer none): time range * * Get the live seekable range of @self. Will fill in the supplied @range with * the current live seekable range. @@ -1044,20 +1135,26 @@ g_return_if_fail (GST_IS_MEDIA_SOURCE (self)); g_return_if_fail (range != NULL); + GST_OBJECT_LOCK (self); range->start = self->live_seekable_range.start; range->end = self->live_seekable_range.end; + GST_OBJECT_UNLOCK (self); } void gst_media_source_seek (GstMediaSource * self, GstClockTime time) { g_return_if_fail (GST_IS_MEDIA_SOURCE (self)); + + GST_OBJECT_LOCK (self); for (guint i = 0;; i++) { GstSourceBuffer *buf = gst_source_buffer_list_index (self->buffers, i); if (buf == NULL) { - return; + goto done; } gst_source_buffer_seek (buf, time); gst_object_unref (buf); } +done: + GST_OBJECT_UNLOCK (self); }
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/mse/gstmediasourcesamplemap-private.h -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/mse/gstmediasourcesamplemap-private.h
Changed
@@ -23,7 +23,6 @@ #pragma once #include <gst/gst.h> -#include <glib-object.h> #include <gst/mse/mse-prelude.h> G_BEGIN_DECLS @@ -31,6 +30,22 @@ #define GST_TYPE_MEDIA_SOURCE_SAMPLE_MAP \ (gst_media_source_sample_map_get_type()) +#define GST_TYPE_MEDIA_SOURCE_CODED_FRAME_GROUP \ + (gst_media_source_coded_frame_group_get_type()) + +#define gst_value_get_media_source_coded_frame_group(v) \ + (GstMediaSourceCodedFrameGroup *)(g_value_get_boxed (v)) + +#define gst_value_take_media_source_coded_frame_group(v, g) \ + g_value_take_boxed ((v), (g)) + +typedef struct { + GstClockTime start; + GstClockTime end; + gsize size; + GList *samples; +} GstMediaSourceCodedFrameGroup; + GST_MSE_PRIVATE G_DECLARE_FINAL_TYPE (GstMediaSourceSampleMap, gst_media_source_sample_map, GST, MEDIA_SOURCE_SAMPLE_MAP, GstObject); @@ -51,16 +66,6 @@ GstClockTime earliest, GstClockTime latest); GST_MSE_PRIVATE -gsize -gst_media_source_sample_map_remove_range_from_start (GstMediaSourceSampleMap - * self, GstClockTime latest_dts); - -GST_MSE_PRIVATE -gsize -gst_media_source_sample_map_remove_range_from_end (GstMediaSourceSampleMap - * self, GstClockTime earliest_dts); - -GST_MSE_PRIVATE gboolean gst_media_source_sample_map_contains (GstMediaSourceSampleMap * self, GstSample * sample); @@ -81,14 +86,23 @@ GST_MSE_PRIVATE GstIterator * -gst_media_source_sample_map_iter_samples_by_dts (GstMediaSourceSampleMap * map, - GMutex * lock, guint32 * master_cookie, GstClockTime start_dts, - GstSample * start_sample); +gst_media_source_sample_map_iter_samples_by_dts (GstMediaSourceSampleMap * self, + GMutex * lock, guint32 * master_cookie); GST_MSE_PRIVATE GstIterator * -gst_media_source_sample_map_iter_samples_by_pts (GstMediaSourceSampleMap * map, - GMutex * lock, guint32 * master_cookie, GstClockTime start_pts, - GstSample *start_sample); +gst_media_source_sample_map_iter_samples_by_pts (GstMediaSourceSampleMap * self, + GMutex * lock, guint32 * master_cookie); + +GST_MSE_PRIVATE +GType gst_media_source_coded_frame_group_get_type (void); + +GST_MSE_PRIVATE +GstMediaSourceCodedFrameGroup * +gst_media_source_coded_frame_group_copy (GstMediaSourceCodedFrameGroup * group); + +GST_MSE_PRIVATE +void +gst_media_source_coded_frame_group_free (GstMediaSourceCodedFrameGroup * group); G_END_DECLS
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/mse/gstmediasourcesamplemap.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/mse/gstmediasourcesamplemap.c
Changed
@@ -27,6 +27,16 @@ #include "gstmediasourcesamplemap-private.h" #include "gstmselogging-private.h" +G_DEFINE_BOXED_TYPE (GstMediaSourceCodedFrameGroup, + gst_media_source_coded_frame_group, + gst_media_source_coded_frame_group_copy, + gst_media_source_coded_frame_group_free); + +#define TIME_RANGE_FORMAT \ + "%" GST_TIMEP_FORMAT "..%" GST_TIMEP_FORMAT ")" +#define TIME_RANGE_ARGS(a, b) &(a), &(b) +#define CODED_FRAME_GROUP_ARGS(g) TIME_RANGE_ARGS ((g)->start, (g)->end) + struct _GstMediaSourceSampleMap { GstObject parent_instance; @@ -41,12 +51,16 @@ G_DEFINE_TYPE (GstMediaSourceSampleMap, gst_media_source_sample_map, GST_TYPE_OBJECT); +static GstMediaSourceCodedFrameGroup *new_coded_frame_group_from_memory (const + GstMediaSourceCodedFrameGroup * src); static gint compare_pts (GstSample * a, GstSample * b, gpointer user_data); -static GSequenceIter *find_sample_containing_dts (GstMediaSourceSampleMap * - self, GstClockTime dts); -static GSequenceIter *find_sample_containing_pts (GstMediaSourceSampleMap * - self, GstClockTime pts); -static GSequenceIter *find_sequentially (GSequence * sequence, gpointer item); +static GSequenceIter *next_coded_frame_group (GSequenceIter * it, GValue * val); + +static inline GstClockTime +sample_duration (GstSample * sample) +{ + return GST_BUFFER_DURATION (gst_sample_get_buffer (sample)); +} static inline GstClockTime sample_dts (GstSample * sample) @@ -55,6 +69,12 @@ } static inline GstClockTime +sample_dts_end (GstSample * sample) +{ + return sample_dts (sample) + sample_duration (sample); +} + +static inline GstClockTime sample_pts (GstSample * sample) { return GST_BUFFER_PTS (gst_sample_get_buffer (sample)); @@ -66,15 +86,11 @@ return gst_buffer_get_size (gst_sample_get_buffer (sample)); } -static gboolean -iter_is_delta_unit (GSequenceIter * iter) +static inline gboolean +sample_is_key_unit (GstSample * sample) { - if (g_sequence_iter_is_end (iter)) { - return TRUE; - } - GstSample *sample = g_sequence_get (iter); GstBuffer *buffer = gst_sample_get_buffer (sample); - return GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); + return !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); } static gint @@ -198,6 +214,115 @@ return g_hash_table_contains (self->samples, sample); } +static GSequenceIter * +next_key_unit (GSequenceIter * it) +{ + for (; !g_sequence_iter_is_end (it); it = g_sequence_iter_next (it)) { + GstSample *sample = g_sequence_get (it); + if (sample_is_key_unit (sample)) { + break; + } + } + return it; +} + +static GSequenceIter * +next_coded_frame_group (GSequenceIter * it, GValue * val) +{ + it = next_key_unit (it); + if (g_sequence_iter_is_end (it)) { + return it; + } + GstSample *head = g_sequence_get (it); + g_return_val_if_fail (sample_is_key_unit (head), NULL); + GstMediaSourceCodedFrameGroup group = { + .start = sample_dts (head), + .end = sample_dts_end (head), + .samples = g_list_prepend (NULL, gst_sample_ref (head)), + .size = 1, + }; + it = g_sequence_iter_next (it); + for (; !g_sequence_iter_is_end (it); it = g_sequence_iter_next (it)) { + GstSample *sample = g_sequence_get (it); + if (sample_is_key_unit (sample)) { + goto done; + } + group.end = sample_dts_end (sample), group.size++; + group.samples = g_list_prepend (group.samples, gst_sample_ref (sample)); + } +done: + group.samples = g_list_reverse (group.samples); + GstMediaSourceCodedFrameGroup *box = + new_coded_frame_group_from_memory (&group); + gst_value_take_media_source_coded_frame_group (val, box); + return it; +} + +static GSequenceIter * +find_start_point (GstMediaSourceSampleMap * self, GSequenceIter * it, + GList ** to_remove, GstClockTime earliest, GstClockTime latest) +{ + while (TRUE) { + GValue value = G_VALUE_INIT; + g_value_init (&value, GST_TYPE_MEDIA_SOURCE_CODED_FRAME_GROUP); + it = next_coded_frame_group (it, &value); + GstMediaSourceCodedFrameGroup *group = + gst_value_get_media_source_coded_frame_group (&value); + if (group == NULL) { + GST_TRACE_OBJECT (self, + "reached end of coded frames before finding start point"); + goto done; + } + + if (group->start >= earliest && group->end <= latest) { + GST_TRACE_OBJECT (self, "found start point for %" GST_TIMEP_FORMAT ": " + TIME_RANGE_FORMAT, &earliest, CODED_FRAME_GROUP_ARGS (group)); + *to_remove = g_list_prepend (*to_remove, + gst_media_source_coded_frame_group_copy (group)); + goto done; + } + + g_value_unset (&value); + continue; + done: + g_value_unset (&value); + return it; + } + return it; +} + +static GSequenceIter * +find_end_point (GstMediaSourceSampleMap * self, GSequenceIter * it, GList ** + to_remove, GstClockTime latest) +{ + while (TRUE) { + GValue value = G_VALUE_INIT; + g_value_init (&value, GST_TYPE_MEDIA_SOURCE_CODED_FRAME_GROUP); + it = next_coded_frame_group (it, &value); + GstMediaSourceCodedFrameGroup *group = + gst_value_get_media_source_coded_frame_group (&value); + if (group == NULL) { + GST_TRACE_OBJECT (self, + "reached end of coded frames before finding end point"); + goto done; + } + if (group->end >= latest) { + GST_TRACE_OBJECT (self, "found end point for %" GST_TIMEP_FORMAT ": " + TIME_RANGE_FORMAT, &latest, CODED_FRAME_GROUP_ARGS (group)); + goto done; + } + *to_remove = g_list_prepend (*to_remove, + gst_media_source_coded_frame_group_copy (group)); + g_value_unset (&value); + continue; + + done: + g_value_unset (&value); + return it; + } + return it; +} + gsize gst_media_source_sample_map_remove_range (GstMediaSourceSampleMap * self, GstClockTime earliest, GstClockTime latest) @@ -205,54 +330,43 @@ g_return_val_if_fail (GST_IS_MEDIA_SOURCE_SAMPLE_MAP (self), 0); g_return_val_if_fail (earliest <= latest, 0); - GSequenceIter *start_by_dts = find_sample_containing_dts (self, earliest); - GSequenceIter *end_by_dts = find_sample_containing_dts (self, latest); + GST_TRACE_OBJECT (self, "request remove range " TIME_RANGE_FORMAT, + TIME_RANGE_ARGS (earliest, latest)); - GstSample *start = g_sequence_get (start_by_dts); - GstSample *end = g_sequence_get (end_by_dts); + GSequenceIter *it = g_sequence_get_begin_iter (self->samples_by_dts); - GstClockTime start_time = - start == NULL ? GST_CLOCK_TIME_NONE : sample_dts (start); - GstClockTime end_time = end == NULL ? start_time : sample_dts (end); + GList *to_remove = NULL; - GST_TRACE_OBJECT (self, "remove range %" GST_TIMEP_FORMAT ",%" - GST_TIMEP_FORMAT ")", &start_time, &end_time); + it = find_start_point (self, it, &to_remove, earliest, latest); - GList *to_remove = NULL; - while (g_sequence_iter_compare (start_by_dts, end_by_dts) < 1) { - GstSample *sample = g_sequence_get (start_by_dts); - to_remove = g_list_prepend (to_remove, sample); - start_by_dts = g_sequence_iter_next (start_by_dts); + if (to_remove == NULL) { + return 0; } + + it = find_end_point (self, it, &to_remove, latest); + + to_remove = g_list_reverse (to_remove); + gsize bytes_removed = 0; - for (GList * iter = to_remove; iter != NULL; iter = g_list_next (iter)) { - GstSample *sample = iter->data; - bytes_removed += sample_buffer_size (sample); - gst_media_source_sample_map_remove (self, sample); + for (GList * group_iter = to_remove; group_iter != NULL; + group_iter = g_list_next (group_iter)) { + GstMediaSourceCodedFrameGroup *group = group_iter->data; + for (GList * sample_iter = group->samples; sample_iter != NULL; + sample_iter = g_list_next (sample_iter)) { + GstSample *sample = sample_iter->data; + bytes_removed += sample_buffer_size (sample); + gst_media_source_sample_map_remove (self, sample); + } } - g_list_free (to_remove); + g_list_free_full (to_remove, + (GDestroyNotify) gst_media_source_coded_frame_group_free); GST_TRACE_OBJECT (self, "removed=%" G_GSIZE_FORMAT "B, latest=%" GST_TIMEP_FORMAT, bytes_removed, &latest); return bytes_removed; } -gsize -gst_media_source_sample_map_remove_range_from_start (GstMediaSourceSampleMap - * self, GstClockTime latest_dts) -{ - return gst_media_source_sample_map_remove_range (self, 0, latest_dts); -} - -gsize -gst_media_source_sample_map_remove_range_from_end (GstMediaSourceSampleMap - * self, GstClockTime earliest_dts) -{ - return gst_media_source_sample_map_remove_range (self, earliest_dts, - GST_CLOCK_TIME_NONE); -} - GstClockTime gst_media_source_sample_map_get_highest_end_time (GstMediaSourceSampleMap * self) @@ -286,178 +400,40 @@ return self->storage_size; } -static inline gboolean -sample_contains_dts (GstSample * sample, GstClockTime dts) -{ - GstBuffer *buffer = gst_sample_get_buffer (sample); - g_return_val_if_fail (GST_BUFFER_DURATION_IS_VALID (buffer), FALSE); - g_return_val_if_fail (GST_BUFFER_DTS_IS_VALID (buffer), FALSE); - g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (dts), FALSE); - GstClockTime end = GST_BUFFER_DTS (buffer) + GST_BUFFER_DURATION (buffer); - return dts <= end; -} - -static inline gboolean -sample_contains_pts (GstSample * sample, GstClockTime pts) -{ - GstBuffer *buffer = gst_sample_get_buffer (sample); - g_return_val_if_fail (GST_BUFFER_DURATION_IS_VALID (buffer), FALSE); - g_return_val_if_fail (GST_BUFFER_PTS_IS_VALID (buffer), FALSE); - g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (pts), FALSE); - GstClockTime end = GST_BUFFER_PTS (buffer) + GST_BUFFER_DURATION (buffer); - return pts <= end; -} - -static GSequenceIter * -find_sequentially (GSequence * sequence, gpointer item) -{ - GSequenceIter *iter = g_sequence_get_begin_iter (sequence); - for (; !g_sequence_iter_is_end (iter); iter = g_sequence_iter_next (iter)) { - gpointer current = g_sequence_get (iter); - if (current == item) { - return iter; - } - } - return iter; -} - -static GSequenceIter * -find_sample_containing_dts (GstMediaSourceSampleMap * self, GstClockTime dts) -{ - if (dts == 0) { - return g_sequence_get_begin_iter (self->samples_by_dts); - } - if (dts == GST_CLOCK_TIME_NONE) { - return g_sequence_get_end_iter (self->samples_by_dts); - } - GSequenceIter *iter = g_sequence_get_begin_iter (self->samples_by_dts); - while (!g_sequence_iter_is_end (iter)) { - GstSample *sample = g_sequence_get (iter); - if (sample_contains_dts (sample, dts)) { - return iter; - } - iter = g_sequence_iter_next (iter); - } - return iter; -} - -static GSequenceIter * -find_sample_containing_pts (GstMediaSourceSampleMap * self, GstClockTime pts) -{ - if (pts == 0) { - return g_sequence_get_begin_iter (self->samples_by_pts); - } - if (pts == GST_CLOCK_TIME_NONE) { - return g_sequence_get_end_iter (self->samples_by_pts); - } - GSequenceIter *iter = g_sequence_get_begin_iter (self->samples_by_pts); - while (!g_sequence_iter_is_end (iter)) { - GstSample *sample = g_sequence_get (iter); - if (sample_contains_pts (sample, pts)) { - return iter; - } - iter = g_sequence_iter_next (iter); - } - return iter; -} - -static GSequenceIter * -find_previous_non_delta_unit (GstMediaSourceSampleMap * self, - GSequenceIter * iter) -{ - while (!g_sequence_iter_is_begin (iter)) { - if (!iter_is_delta_unit (iter)) { - GST_TRACE_OBJECT (self, "found valid sample"); - return iter; - } - iter = g_sequence_iter_prev (iter); - } - GST_TRACE_OBJECT (self, "rolled back to the first sample"); - return iter; -} - -static GSequenceIter * -gst_media_source_sample_map_iter_starting_dts (GstMediaSourceSampleMap * self, - GstClockTime start_dts) -{ - g_return_val_if_fail (GST_IS_MEDIA_SOURCE_SAMPLE_MAP (self), NULL); - g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (start_dts), NULL); - GSequenceIter *iter = find_sample_containing_dts (self, start_dts); - return find_previous_non_delta_unit (self, iter); -} - -static GSequenceIter * -gst_media_source_sample_map_iter_starting_pts (GstMediaSourceSampleMap - * self, GstClockTime start_pts) -{ - g_return_val_if_fail (GST_IS_MEDIA_SOURCE_SAMPLE_MAP (self), NULL); - g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (start_pts), NULL); - GSequenceIter *iter = find_sample_containing_pts (self, start_pts); - return find_previous_non_delta_unit (self, iter); -} - typedef struct _SampleMapIterator SampleMapIterator; struct _SampleMapIterator { GstIterator iterator; GstMediaSourceSampleMap *map; -/* *INDENT-OFF* */ - GstClockTime (*timestamp_func) (GstSample *); - GSequenceIter *(*resync_locator_func) (SampleMapIterator *); -/* *INDENT-ON* */ + GSequenceIter *(*reset_func) (SampleMapIterator *); - GstClockTime start_time; - GstClockTime current_time; GSequenceIter *current_iter; - GstSample *current_sample; }; static void iter_copy (const SampleMapIterator * it, SampleMapIterator * copy) { copy->map = gst_object_ref (it->map); - copy->timestamp_func = it->timestamp_func; - copy->resync_locator_func = it->resync_locator_func; + copy->reset_func = it->reset_func; - copy->current_time = it->current_time; - copy->start_time = it->start_time; copy->current_iter = it->current_iter; - copy->current_sample = gst_sample_ref (it->current_sample); } static GSequenceIter * -iter_find_resync_point_dts (SampleMapIterator * it) +iter_reset_by_dts (SampleMapIterator * it) { - if (it->current_sample) { - GSequenceIter *iter = - find_sequentially (it->map->samples_by_dts, it->current_sample); - if (!g_sequence_iter_is_end (iter)) { - return g_sequence_iter_next (iter); - } - } - - return gst_media_source_sample_map_iter_starting_dts (it->map, - it->current_time); + return g_sequence_get_begin_iter (it->map->samples_by_dts); } static GSequenceIter * -iter_find_resync_point_pts (SampleMapIterator * it) +iter_reset_by_pts (SampleMapIterator * it) { - if (it->current_sample) { - GSequenceIter *iter = - find_sequentially (it->map->samples_by_pts, it->current_sample); - if (!g_sequence_iter_is_end (iter)) { - return g_sequence_iter_next (iter); - } - } - - return gst_media_source_sample_map_iter_starting_pts (it->map, - it->current_time); + return g_sequence_get_begin_iter (it->map->samples_by_pts); } static GstIteratorResult -iter_next (SampleMapIterator * it, GValue * result) +iter_next_sample (SampleMapIterator * it, GValue * result) { if (g_sequence_iter_is_end (it->current_iter)) { @@ -465,10 +441,7 @@ } GstSample *sample = g_sequence_get (it->current_iter); - gst_clear_sample (&it->current_sample); - it->current_sample = gst_sample_ref (sample); - it->current_time = it->timestamp_func (sample); it->current_iter = g_sequence_iter_next (it->current_iter); gst_value_set_sample (result, sample); @@ -476,55 +449,59 @@ return GST_ITERATOR_OK; } +static GstIteratorResult +iter_next_group (SampleMapIterator * it, GValue * result) +{ + if (g_sequence_iter_is_end (it->current_iter)) { + return GST_ITERATOR_DONE; + } + + it->current_iter = next_coded_frame_group (it->current_iter, result); + + return GST_ITERATOR_OK; +} + static void iter_resync (SampleMapIterator * it) { GST_TRACE_OBJECT (it->map, "resync"); - it->current_time = it->start_time; - it->current_iter = it->resync_locator_func (it); + it->current_iter = it->reset_func (it); } static void iter_free (SampleMapIterator * it) { gst_clear_object (&it->map); - gst_clear_sample (&it->current_sample); } GstIterator * -gst_media_source_sample_map_iter_samples_by_dts (GstMediaSourceSampleMap * map, - GMutex * lock, guint32 * master_cookie, GstClockTime start_dts, - GstSample * start_sample) +gst_media_source_sample_map_iter_samples_by_dts (GstMediaSourceSampleMap * self, + GMutex * lock, guint32 * master_cookie) { /* *INDENT-OFF* */ SampleMapIterator *it = (SampleMapIterator *) gst_iterator_new ( sizeof (SampleMapIterator), - GST_TYPE_SAMPLE, + GST_TYPE_MEDIA_SOURCE_CODED_FRAME_GROUP, lock, master_cookie, (GstIteratorCopyFunction) iter_copy, - (GstIteratorNextFunction) iter_next, + (GstIteratorNextFunction) iter_next_group, (GstIteratorItemFunction) NULL, (GstIteratorResyncFunction) iter_resync, (GstIteratorFreeFunction) iter_free ); /* *INDENT-ON* */ - it->map = gst_object_ref (map); - it->timestamp_func = sample_dts; - it->resync_locator_func = iter_find_resync_point_dts; - it->start_time = start_dts; - it->current_time = start_dts; - it->current_sample = start_sample ? gst_sample_ref (start_sample) : NULL; - it->current_iter = iter_find_resync_point_dts (it); + it->map = gst_object_ref (self); + it->reset_func = iter_reset_by_dts; + it->current_iter = iter_reset_by_dts (it); return GST_ITERATOR (it); } GstIterator * -gst_media_source_sample_map_iter_samples_by_pts (GstMediaSourceSampleMap * map, - GMutex * lock, guint32 * master_cookie, GstClockTime start_pts, - GstSample * start_sample) +gst_media_source_sample_map_iter_samples_by_pts (GstMediaSourceSampleMap * self, + GMutex * lock, guint32 * master_cookie) { /* *INDENT-OFF* */ SampleMapIterator *it = (SampleMapIterator *) gst_iterator_new ( @@ -533,20 +510,43 @@ lock, master_cookie, (GstIteratorCopyFunction) iter_copy, - (GstIteratorNextFunction) iter_next, + (GstIteratorNextFunction) iter_next_sample, (GstIteratorItemFunction) NULL, (GstIteratorResyncFunction) iter_resync, (GstIteratorFreeFunction) iter_free ); /* *INDENT-ON* */ - it->map = gst_object_ref (map); - it->timestamp_func = sample_pts; - it->resync_locator_func = iter_find_resync_point_pts; - it->start_time = start_pts; - it->current_time = start_pts; - it->current_sample = start_sample ? gst_sample_ref (start_sample) : NULL; - it->current_iter = iter_find_resync_point_pts (it); + it->map = gst_object_ref (self); + it->reset_func = iter_reset_by_pts; + it->current_iter = iter_reset_by_pts (it); return GST_ITERATOR (it); } + +static GstMediaSourceCodedFrameGroup * +new_coded_frame_group_from_memory (const GstMediaSourceCodedFrameGroup * src) +{ + GstMediaSourceCodedFrameGroup *box = + g_atomic_rc_box_new0 (GstMediaSourceCodedFrameGroup); + memcpy (box, src, sizeof (GstMediaSourceCodedFrameGroup)); + return box; +} + +GstMediaSourceCodedFrameGroup * +gst_media_source_coded_frame_group_copy (GstMediaSourceCodedFrameGroup * self) +{ + return g_atomic_rc_box_acquire (self); +} + +static void +free_group_inner (GstMediaSourceCodedFrameGroup * self) +{ + g_list_free_full (self->samples, (GDestroyNotify) gst_sample_unref); +} + +void +gst_media_source_coded_frame_group_free (GstMediaSourceCodedFrameGroup * self) +{ + g_atomic_rc_box_release_full (self, (GDestroyNotify) free_group_inner); +}
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/mse/gstmediasourcetrack-private.h -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/mse/gstmediasourcetrack-private.h
Changed
@@ -84,10 +84,6 @@ GstSample * sample); GST_MSE_PRIVATE -gboolean gst_media_source_track_try_push (GstMediaSourceTrack * self, - GstSample * sample); - -GST_MSE_PRIVATE gboolean gst_media_source_track_push_eos (GstMediaSourceTrack * self); GST_MSE_PRIVATE
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/mse/gstmediasourcetrack.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/mse/gstmediasourcetrack.c
Changed
@@ -160,6 +160,7 @@ self->track_type = g_value_get_enum (value); break; case PROP_TRACK_ID: + /* G_PARAM_CONSTRUCT_ONLY */ self->track_id = g_value_dup_string (value); break; case PROP_ACTIVE: @@ -345,7 +346,7 @@ gboolean was_empty = gst_media_source_track_is_empty (self); - GstDataQueueItem *item = wrap_sample (sample); + GstDataQueueItem *item = wrap_sample (gst_sample_ref (sample)); gboolean result = gst_data_queue_push (self->samples, item); @@ -408,19 +409,6 @@ } gboolean -gst_media_source_track_try_push (GstMediaSourceTrack * self, GstSample * sample) -{ - g_return_val_if_fail (GST_IS_MEDIA_SOURCE_TRACK (self), FALSE); - g_return_val_if_fail (GST_IS_SAMPLE (sample), FALSE); - - if (gst_data_queue_is_full (self->samples)) { - return FALSE; - } - - return gst_media_source_track_push (self, sample); -} - -gboolean gst_media_source_track_is_empty (GstMediaSourceTrack * self) { g_return_val_if_fail (GST_IS_MEDIA_SOURCE_TRACK (self), FALSE);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/mse/gstmediasourcetrackbuffer-private.h -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/mse/gstmediasourcetrackbuffer-private.h
Changed
@@ -66,18 +66,11 @@ GstSample * sample); GST_MSE_PRIVATE -void gst_media_source_track_buffer_remove (GstMediaSourceTrackBuffer * self, - GstSample * sample); - -GST_MSE_PRIVATE gsize gst_media_source_track_buffer_remove_range (GstMediaSourceTrackBuffer * self, GstClockTime start, GstClockTime end); GST_MSE_PRIVATE -void gst_media_source_track_buffer_clear (GstMediaSourceTrackBuffer * self); - -GST_MSE_PRIVATE void gst_media_source_track_buffer_eos (GstMediaSourceTrackBuffer * self); GST_MSE_PRIVATE @@ -85,7 +78,7 @@ GstMediaSourceTrackBuffer * self); GST_MSE_PRIVATE -gboolean gst_media_source_track_buffer_await_eos_until ( +void gst_media_source_track_buffer_await_new_data_until ( GstMediaSourceTrackBuffer * self, gint64 deadline); GST_MSE_PRIVATE @@ -94,7 +87,6 @@ GST_MSE_PRIVATE GstIterator * gst_media_source_track_buffer_iter_samples ( - GstMediaSourceTrackBuffer * buffer, GstClockTime start_dts, - GstSample * start_sample); + GstMediaSourceTrackBuffer * self); G_END_DECLS
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/mse/gstmediasourcetrackbuffer.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/mse/gstmediasourcetrackbuffer.c
Changed
@@ -152,22 +152,6 @@ NEW_DATA_UNLOCK (self); } -void -gst_media_source_track_buffer_remove (GstMediaSourceTrackBuffer * self, - GstSample * sample) -{ - g_return_if_fail (GST_IS_MEDIA_SOURCE_TRACK_BUFFER (self)); - g_return_if_fail (GST_IS_SAMPLE (sample)); - - NEW_DATA_LOCK (self); - - gst_media_source_sample_map_remove (self->samples, sample); - invalidate_cookie (self); - - NEW_DATA_SIGNAL (self); - NEW_DATA_UNLOCK (self); -} - gsize gst_media_source_track_buffer_remove_range (GstMediaSourceTrackBuffer * self, GstClockTime earliest, GstClockTime latest) @@ -181,19 +165,6 @@ return size; } -void -gst_media_source_track_buffer_clear (GstMediaSourceTrackBuffer * self) -{ - g_return_if_fail (GST_IS_MEDIA_SOURCE_TRACK_BUFFER (self)); - - NEW_DATA_LOCK (self); - - g_set_object (&self->samples, gst_media_source_sample_map_new ()); - - NEW_DATA_SIGNAL (self); - NEW_DATA_UNLOCK (self); -} - static gboolean is_eos (GstMediaSourceTrackBuffer * self) { @@ -217,16 +188,13 @@ return is_eos (self); } -gboolean -gst_media_source_track_buffer_await_eos_until (GstMediaSourceTrackBuffer * self, - gint64 deadline) +void +gst_media_source_track_buffer_await_new_data_until (GstMediaSourceTrackBuffer * + self, gint64 deadline) { NEW_DATA_LOCK (self); - while (!is_eos (self) && NEW_DATA_WAIT_UNTIL (self, deadline)) { - /* wait */ - } + NEW_DATA_WAIT_UNTIL (self, deadline); NEW_DATA_UNLOCK (self); - return is_eos (self); } gint @@ -249,6 +217,7 @@ { GArray *ranges; GstMediaSourceRange current_range; + GstClockTime max_duration; } GetRangesAccumulator; static gboolean @@ -260,9 +229,23 @@ GstClockTime start = GST_BUFFER_PTS (buffer); GstClockTime end = start + GST_BUFFER_DURATION (buffer); + if (GST_BUFFER_DURATION_IS_VALID (buffer)) { + acc->max_duration = MAX (acc->max_duration, GST_BUFFER_DURATION (buffer)); + } + GstMediaSourceRange *range = &acc->current_range; - if (range->end == 0 || start <= (range->end + (GST_SECOND / 100))) { + if (!GST_CLOCK_TIME_IS_VALID (acc->current_range.start)) { + acc->current_range.start = start; + } + if (!GST_CLOCK_TIME_IS_VALID (acc->current_range.end)) { + acc->current_range.end = end; + } + + GstClockTime gap_tolerance = MAX (GST_SECOND / 10, acc->max_duration * 2); + GstClockTime gap = MAX (0, GST_CLOCK_DIFF (range->end, start)); + + if (range->end == 0 || gap <= gap_tolerance) { range->end = end; return TRUE; } @@ -279,24 +262,34 @@ { GetRangesAccumulator acc = { .ranges = g_array_new_ranges (), - .current_range = {.start = 0,.end = 0}, + .max_duration = 0, + .current_range = {.start = GST_CLOCK_TIME_NONE,.end = GST_CLOCK_TIME_NONE}, }; /* *INDENT-OFF* */ GstIterator *iter = gst_media_source_sample_map_iter_samples_by_pts ( self->samples, &self->new_data_mutex, - &self->master_cookie, - 0, - NULL + &self->master_cookie ); /* *INDENT-ON* */ while (gst_iterator_fold (iter, (GstIteratorFoldFunction) get_ranges_fold, (GValue *) & acc, NULL) == GST_ITERATOR_RESYNC) { gst_iterator_resync (iter); + g_clear_pointer (&acc.ranges, g_array_unref); + acc.ranges = g_array_new_ranges (); + acc.max_duration = 0; + acc.current_range.start = GST_CLOCK_TIME_NONE; + acc.current_range.end = GST_CLOCK_TIME_NONE; } gst_iterator_free (iter); + if (!GST_CLOCK_TIME_IS_VALID (acc.current_range.start)) { + acc.current_range.start = 0; + } + if (!GST_CLOCK_TIME_IS_VALID (acc.current_range.end)) { + acc.current_range.end = 0; + } if (acc.current_range.end > 0) { g_array_append_val (acc.ranges, acc.current_range); } @@ -362,16 +355,8 @@ } GstIterator * -gst_media_source_track_buffer_iter_samples (GstMediaSourceTrackBuffer * self, - GstClockTime start_dts, GstSample * start_sample) +gst_media_source_track_buffer_iter_samples (GstMediaSourceTrackBuffer * self) { - /* *INDENT-OFF* */ - return gst_media_source_sample_map_iter_samples_by_dts ( - self->samples, - &self->new_data_mutex, - &self->master_cookie, - start_dts, - start_sample - ); - /* *INDENT-ON* */ + return gst_media_source_sample_map_iter_samples_by_dts (self->samples, + &self->new_data_mutex, &self->master_cookie); }
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/mse/gstmselogging-private.h -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/mse/gstmselogging-private.h
Changed
@@ -31,3 +31,6 @@ G_GNUC_INTERNAL void gst_mse_init_logging (void); + +G_GNUC_INTERNAL +const gchar * gst_mse_enum_value_nick (GType enum_type, gint mse_enum_value);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/mse/gstmselogging.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/mse/gstmselogging.c
Changed
@@ -33,3 +33,13 @@ { GST_DEBUG_CATEGORY_INIT (gst_mse_debug, "gst-mse", 0, "GstMse"); } + +const gchar * +gst_mse_enum_value_nick (GType enum_type, gint mse_enum_value) +{ + GEnumClass *enum_class = (GEnumClass *) g_type_class_ref (enum_type); + GEnumValue *enum_value = g_enum_get_value (enum_class, mse_enum_value); + const gchar *nick = enum_value->value_nick; + g_type_class_unref (enum_class); + return nick; +}
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/mse/gstmsesrc-private.h -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/mse/gstmsesrc-private.h
Changed
@@ -44,9 +44,6 @@ gsize n_tracks); GST_MSE_PRIVATE -void gst_mse_src_update_ready_state (GstMseSrc * self); - -GST_MSE_PRIVATE void gst_mse_src_attach (GstMseSrc * self, GstMediaSource * media_source); GST_MSE_PRIVATE
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/mse/gstmsesrc.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/mse/gstmsesrc.c
Changed
@@ -63,7 +63,7 @@ #include "gstsourcebuffer.h" #include "gstsourcebuffer-private.h" -#define DEFAULT_POSITION GST_CLOCK_TIME_NONE +#define DEFAULT_POSITION 0 #define DEFAULT_DURATION GST_CLOCK_TIME_NONE #define DEFAULT_READY_STATE GST_MSE_SRC_READY_STATE_HAVE_NOTHING #define DECODE_ERROR "decode error" @@ -96,6 +96,13 @@ GST_STATIC_PAD_TEMPLATE ("src_%s", GST_PAD_SRC, GST_PAD_SOMETIMES, GST_STATIC_CAPS_ANY); +typedef struct +{ + GWeakRef parent; + GstTask *task; + GRecMutex mutex; +} ReadyStateUpdateTask; + /** * GstMseSrcPad: * @@ -110,8 +117,6 @@ GstCaps *most_recent_caps; GstSegment segment; - GstClockTime position; - gboolean sent_stream_collection; gboolean sent_stream_start; gboolean sent_initial_caps; @@ -120,9 +125,11 @@ GCond linked_or_flushing_cond; GMutex linked_or_flushing_lock; gboolean flushing; - gboolean eos; }; +#define MEDIA_SOURCE_LOCK(a) g_mutex_lock (&(a)->media_source_lock) +#define MEDIA_SOURCE_UNLOCK(a) g_mutex_unlock (&(a)->media_source_lock) + #define STREAMS_LOCK(a) (g_mutex_lock (&a->streams_lock)) #define STREAMS_UNLOCK(a) (g_mutex_unlock (&a->streams_lock)) @@ -148,6 +155,19 @@ GstQuery * query); static void pad_task (GstMseSrcPad * pad); +static ReadyStateUpdateTask *ready_state_update_task_new (GstMseSrc * parent); +static void ready_state_update_task_free (ReadyStateUpdateTask * task); +static void ready_state_update_task_func (ReadyStateUpdateTask * task); +static void ready_state_update_task_start (ReadyStateUpdateTask * task); +static void ready_state_update_task_stop (ReadyStateUpdateTask * task); +static void ready_state_update_task_join (ReadyStateUpdateTask * task); + +static const gchar * +mse_src_ready_state_name (GstMseSrcReadyState state) +{ + return gst_mse_enum_value_nick (gst_mse_src_ready_state_get_type (), state); +} + static GstPad * gst_mse_src_pad_new (GstMediaSourceTrack * track, GstStream * stream, guint id, GstClockTime start, gdouble rate) @@ -172,9 +192,7 @@ self->sent_stream_start = FALSE; self->sent_initial_caps = FALSE; self->does_need_segment = TRUE; - self->position = DEFAULT_POSITION; self->flushing = FALSE; - self->eos = FALSE; g_mutex_init (&self->linked_or_flushing_lock); g_cond_init (&self->linked_or_flushing_cond); @@ -223,6 +241,7 @@ GstElement base; GstMediaSource *media_source; + GMutex media_source_lock; guint group_id; GstStreamCollection *collection; @@ -234,12 +253,11 @@ gdouble rate; GstMseSrcReadyState ready_state; + ReadyStateUpdateTask *ready_state_update_task; + GstFlowCombiner *flow_combiner; GMutex flow_combiner_lock; - GCond eos_cond; - GMutex eos_lock; - gchar *uri; }; @@ -249,7 +267,7 @@ GstStateChange transition); static gboolean gst_mse_src_send_event (GstElement * element, GstEvent * event); static void update_ready_state_for_init_segment (GstMseSrc * self); -static void update_ready_state_for_sample (GstMseSrc * self); +static void update_ready_state (GstMseSrc * self); G_DEFINE_TYPE_WITH_CODE (GstMseSrc, gst_mse_src, GST_TYPE_ELEMENT, G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER, gst_mse_src_uri_handler_init)); @@ -267,13 +285,15 @@ gst_mse_src_dispose (GObject * object) { GstMseSrc *self = GST_MSE_SRC (object); + g_clear_pointer (&self->ready_state_update_task, + ready_state_update_task_free); + gst_clear_object (&self->media_source); + g_mutex_clear (&self->media_source_lock); gst_clear_object (&self->collection); g_clear_pointer (&self->streams, g_hash_table_unref); g_mutex_clear (&self->streams_lock); g_clear_pointer (&self->flow_combiner, gst_flow_combiner_free); g_mutex_clear (&self->flow_combiner_lock); - g_cond_clear (&self->eos_cond); - g_mutex_clear (&self->eos_lock); G_OBJECT_CLASS (gst_mse_src_parent_class)->dispose (object); } @@ -464,6 +484,70 @@ return gst_stream_collection_new (G_OBJECT_TYPE_NAME (self)); } +static ReadyStateUpdateTask * +ready_state_update_task_new (GstMseSrc * parent) +{ + ReadyStateUpdateTask *task = g_new0 (ReadyStateUpdateTask, 1); + g_rec_mutex_init (&task->mutex); + g_weak_ref_init (&task->parent, parent); + task->task = + gst_task_new ((GstTaskFunction) ready_state_update_task_func, task, NULL); + gst_task_set_lock (task->task, &task->mutex); + return task; +} + +static void +ready_state_update_task_free (ReadyStateUpdateTask * task) +{ + g_weak_ref_set (&task->parent, NULL); + gst_task_join (task->task); + gst_clear_object (&task->task); + g_weak_ref_clear (&task->parent); + g_rec_mutex_clear (&task->mutex); + g_free (task); +} + +static void +ready_state_update_task_start (ReadyStateUpdateTask * task) +{ + GstMseSrc *parent = g_weak_ref_get (&task->parent); + if (parent) { + gchar *name = g_strdup_printf ("%s:ready-state", GST_OBJECT_NAME (parent)); + g_object_set (task->task, "name", name, NULL); + g_clear_pointer (&name, g_free); + } + gst_clear_object (&parent); + gst_task_start (task->task); +} + +static void +ready_state_update_task_stop (ReadyStateUpdateTask * task) +{ + gst_task_stop (task->task); +} + +static void +ready_state_update_task_join (ReadyStateUpdateTask * task) +{ + gst_task_join (task->task); +} + +static void +ready_state_update_task_func (ReadyStateUpdateTask * task) +{ + GstMseSrc *self = (GstMseSrc *) g_weak_ref_get (&task->parent); + + if (self == NULL) { + GST_ERROR_OBJECT (task->task, "parent object is gone, stopping"); + gst_task_stop (task->task); + return; + } + + update_ready_state (self); + gst_object_unref (self); + g_usleep (G_TIME_SPAN_SECOND); +} + static void gst_mse_src_init (GstMseSrc * self) { @@ -473,11 +557,12 @@ self->uri = NULL; self->start_time = 0; self->rate = 1; + self->media_source = NULL; + g_mutex_init (&self->media_source_lock); g_mutex_init (&self->streams_lock); self->flow_combiner = gst_flow_combiner_new (); g_mutex_init (&self->flow_combiner_lock); - g_cond_init (&self->eos_cond); - g_mutex_init (&self->eos_lock); + self->ready_state_update_task = ready_state_update_task_new (self); } /** @@ -713,11 +798,13 @@ GstSegment *segment = &(pad->segment); segment->base = 0; segment->start = self->start_time; + segment->position = self->start_time; segment->time = self->start_time; segment->rate = self->rate; + } else { + gst_media_source_track_flush (stream->track); } - gst_media_source_track_flush (stream->track); g_atomic_int_set (&pad->does_need_segment, TRUE); gst_pad_push_event (GST_PAD (pad), gst_event_new_flush_stop (is_seek)); @@ -787,11 +874,16 @@ GstMseSrc *self = GST_MSE_SRC (element); switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: + ready_state_update_task_stop (self->ready_state_update_task); tear_down_all_streams (self); break; case GST_STATE_CHANGE_READY_TO_NULL: + ready_state_update_task_join (self->ready_state_update_task); gst_mse_src_detach (self); break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + ready_state_update_task_start (self->ready_state_update_task); + break; default: break; } @@ -802,9 +894,12 @@ static void gst_mse_src_seek (GstMseSrc * self, GstClockTime start_time, gdouble rate) { + GST_OBJECT_LOCK (self); self->start_time = start_time; self->rate = rate; + GST_OBJECT_UNLOCK (self); + MEDIA_SOURCE_LOCK (self); flush_all_streams (self, TRUE); if (self->media_source) { GST_DEBUG_OBJECT (self, "seeking on media source %" GST_PTR_FORMAT, @@ -813,6 +908,7 @@ } else { GST_DEBUG_OBJECT (self, "detached, not seeking on media source"); } + MEDIA_SOURCE_UNLOCK (self); resume_all_streams (self); } @@ -835,7 +931,7 @@ gst_event_unref (event); - if (format != GST_FORMAT_TIME || seek_type != GST_SEEK_TYPE_SET) { + if (format != GST_FORMAT_TIME || seek_type != GST_SEEK_TYPE_SET || rate < 0) { GST_ERROR_OBJECT (self, "Rejecting unsupported seek event: %" GST_PTR_FORMAT, event); return FALSE; @@ -852,55 +948,32 @@ return g_atomic_int_get (&pad->flushing) || GST_PAD_IS_FLUSHING (pad); } -static void +static gboolean await_pad_linked_or_flushing (GstMseSrcPad * pad) { GST_TRACE_OBJECT (pad, "waiting for link"); LINKED_OR_FLUSHING_LOCK (pad); + gboolean flushing = FALSE; while (!gst_pad_is_linked (GST_PAD_CAST (pad)) && !is_flushing (pad)) { LINKED_OR_FLUSHING_WAIT (pad); } + flushing = is_flushing (pad); LINKED_OR_FLUSHING_UNLOCK (pad); GST_TRACE_OBJECT (pad, "linked"); -} - -static gboolean -all_pads_eos_fold (const GValue * item, gboolean * all_eos, gpointer user_data) -{ - GstMseSrcPad *pad = g_value_get_object (item); - if (pad->eos) { - return TRUE; - } else { - *all_eos = FALSE; - return FALSE; - } -} - -static gboolean -all_pads_eos (GstMseSrc * self) -{ - GstIterator *iter = gst_element_iterate_src_pads (GST_ELEMENT_CAST (self)); - gboolean all_eos = TRUE; - while (gst_iterator_fold (iter, - (GstIteratorFoldFunction) all_pads_eos_fold, (GValue *) & all_eos, - NULL) == GST_ITERATOR_RESYNC) { - gst_iterator_resync (iter); - } - gst_iterator_free (iter); - return all_eos; + return flushing; } static void pad_task (GstMseSrcPad * pad) { - await_pad_linked_or_flushing (pad); - - if (is_flushing (pad)) { + GstMseSrc *self = NULL; + gboolean flushing = await_pad_linked_or_flushing (pad); + if (flushing) { GST_TRACE_OBJECT (pad, "pad is flushing"); goto pause; } - GstMseSrc *self = GST_MSE_SRC (gst_pad_get_parent_element (GST_PAD (pad))); + self = GST_MSE_SRC (gst_pad_get_parent_element (GST_PAD (pad))); GstMediaSourceTrack *track = pad->track; @@ -976,7 +1049,11 @@ GstBuffer *buffer = gst_buffer_copy (gst_sample_get_buffer (sample)); if (GST_BUFFER_DTS_IS_VALID (buffer)) { - pad->position = GST_BUFFER_DTS (buffer); + GstClockTime duration = + GST_BUFFER_DURATION_IS_VALID (buffer) ? GST_BUFFER_DURATION (buffer) : + 1; + GstClockTime buffer_end = GST_BUFFER_DTS (buffer) + duration; + pad->segment.position = MAX (pad->segment.position, buffer_end); } GstFlowReturn push_result = gst_pad_push (GST_PAD (pad), buffer); @@ -987,26 +1064,24 @@ GST_PAD_CAST (pad), push_result); FLOW_COMBINER_UNLOCK (self); - if (combined_result != GST_FLOW_OK) { - GST_DEBUG_OBJECT (pad, "push result: %s, combined result: %s", - gst_flow_get_name (push_result), gst_flow_get_name (combined_result)); - goto pause; + switch (combined_result) { + case GST_FLOW_OK: + break; + case GST_FLOW_FLUSHING: + goto pause; + default: + GST_ELEMENT_ERROR (self, CORE, PAD, ("failed to push data downstream"), + ("pad result: %s, combined result %s", + gst_flow_get_name (push_result), + gst_flow_get_name (combined_result))); + goto pause; } } else if (GST_IS_EVENT (object)) { - if (GST_EVENT_TYPE (object) == GST_EVENT_EOS) { - g_mutex_lock (&self->eos_lock); - pad->eos = TRUE; - g_cond_broadcast (&self->eos_cond); - g_mutex_unlock (&self->eos_lock); - g_mutex_lock (&self->eos_lock); - while (!all_pads_eos (self)) { - GST_DEBUG_OBJECT (pad, "waiting for eos on all tracks"); - g_cond_wait (&self->eos_cond, &self->eos_lock); - } - g_mutex_unlock (&self->eos_lock); - GST_DEBUG_OBJECT (pad, "have eos on all tracks"); + GstEvent *event = GST_EVENT (g_steal_pointer (&object)); + if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { + GST_LOG_OBJECT (self, "EOS"); } - if (!gst_pad_push_event (GST_PAD (pad), GST_EVENT (object))) { + if (!gst_pad_push_event (GST_PAD (pad), event)) { GST_ERROR_OBJECT (self, "failed to push enqueued event"); goto pause; } @@ -1016,12 +1091,14 @@ g_assert_not_reached (); } + gst_clear_object (&self); return; pause: if (!g_atomic_int_get (&pad->flushing)) { gst_pad_pause_task (GST_PAD (pad)); } + gst_clear_object (&self); } static gboolean @@ -1073,7 +1150,7 @@ GstMseSrc *self = GST_MSE_SRC (parent); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION:{ - GstClockTime position = pad->position; + GstClockTime position = pad->segment.position; GstFormat fmt; gst_query_parse_position (query, &fmt, NULL); if (fmt == GST_FORMAT_TIME && GST_CLOCK_TIME_IS_VALID (position)) { @@ -1181,13 +1258,6 @@ self->collection)); } -void -gst_mse_src_update_ready_state (GstMseSrc * self) -{ - g_return_if_fail (GST_IS_MSE_SRC (self)); - update_ready_state_for_sample (self); -} - static GstURIType gst_mse_src_uri_get_type (GType type) { @@ -1205,7 +1275,10 @@ gst_mse_src_uri_get_uri (GstURIHandler * handler) { GstMseSrc *self = GST_MSE_SRC (handler); - return g_strdup (self->uri); + GST_OBJECT_LOCK (self); + gchar *uri = g_strdup (self->uri); + GST_OBJECT_UNLOCK (self); + return uri; } static gboolean @@ -1213,8 +1286,10 @@ GError ** error) { GstMseSrc *self = GST_MSE_SRC (handler); + GST_OBJECT_LOCK (self); g_free (self->uri); self->uri = g_strdup (uri); + GST_OBJECT_UNLOCK (self); return TRUE; } @@ -1233,14 +1308,20 @@ { g_return_if_fail (GST_IS_MSE_SRC (self)); g_return_if_fail (GST_IS_MEDIA_SOURCE (media_source)); + + MEDIA_SOURCE_LOCK (self); g_set_object (&self->media_source, media_source); + MEDIA_SOURCE_UNLOCK (self); } void gst_mse_src_detach (GstMseSrc * self) { g_return_if_fail (GST_IS_MSE_SRC (self)); + + MEDIA_SOURCE_LOCK (self); gst_clear_object (&self->media_source); + MEDIA_SOURCE_UNLOCK (self); } static void @@ -1249,7 +1330,9 @@ if (ready_state == self->ready_state) { return; } - GST_DEBUG_OBJECT (self, "ready state %d=>%d", self->ready_state, ready_state); + GST_DEBUG_OBJECT (self, "ready state %s=>%s", + mse_src_ready_state_name (self->ready_state), + mse_src_ready_state_name (ready_state)); self->ready_state = ready_state; g_object_notify_by_pspec (G_OBJECT (self), propertiesPROP_READY_STATE); } @@ -1257,9 +1340,13 @@ static void update_ready_state_for_init_segment (GstMseSrc * self) { - g_return_if_fail (GST_IS_MEDIA_SOURCE (self->media_source)); + MEDIA_SOURCE_LOCK (self); + + if (self->media_source == NULL) { + goto done; + } if (self->ready_state != GST_MSE_SRC_READY_STATE_HAVE_NOTHING) { - return; + goto done; } GstSourceBufferList *buffers = gst_media_source_get_source_buffers (self->media_source); @@ -1275,13 +1362,17 @@ if (!all_received_init_segment) { return; } - set_ready_state (self, GST_MSE_SRC_READY_STATE_HAVE_METADATA); + set_ready_state (self, MAX (self->ready_state, + GST_MSE_SRC_READY_STATE_HAVE_METADATA)); + +done: + MEDIA_SOURCE_UNLOCK (self); } static gboolean -has_current_data (GstMseSrc * self) +has_current_data (GstMseSrc * self, GstClockTime position, + GstClockTime duration) { - GstClockTime position = gst_mse_src_get_position (self); if (!GST_CLOCK_TIME_IS_VALID (position)) { return FALSE; } @@ -1306,10 +1397,8 @@ } static gboolean -has_future_data (GstMseSrc * self) +has_future_data (GstMseSrc * self, GstClockTime position, GstClockTime duration) { - GstClockTime position = gst_mse_src_get_position (self); - GstClockTime duration = self->duration; if (!GST_CLOCK_TIME_IS_VALID (position) || !GST_CLOCK_TIME_IS_VALID (duration)) { return FALSE; @@ -1338,10 +1427,8 @@ } static gboolean -has_enough_data (GstMseSrc * self) +has_enough_data (GstMseSrc * self, GstClockTime position, GstClockTime duration) { - GstClockTime position = gst_mse_src_get_position (self); - GstClockTime duration = self->duration; if (!GST_CLOCK_TIME_IS_VALID (position) || !GST_CLOCK_TIME_IS_VALID (duration)) { return FALSE; @@ -1370,18 +1457,31 @@ } static void -update_ready_state_for_sample (GstMseSrc * self) +update_ready_state (GstMseSrc * self) { - g_return_if_fail (GST_IS_MEDIA_SOURCE (self->media_source)); - g_return_if_fail (self->ready_state >= GST_MSE_SRC_READY_STATE_HAVE_METADATA); + MEDIA_SOURCE_LOCK (self); + + if (self->media_source == NULL) { + goto done; + } + + if (self->ready_state < GST_MSE_SRC_READY_STATE_HAVE_METADATA) { + goto done; + } - if (has_enough_data (self)) { + GstClockTime position = gst_mse_src_get_position (self); + GstClockTime duration = self->duration; + + if (has_enough_data (self, position, duration)) { set_ready_state (self, GST_MSE_SRC_READY_STATE_HAVE_ENOUGH_DATA); - } else if (has_future_data (self)) { + } else if (has_future_data (self, position, duration)) { set_ready_state (self, GST_MSE_SRC_READY_STATE_HAVE_FUTURE_DATA); - } else if (has_current_data (self)) { + } else if (has_current_data (self, position, duration)) { set_ready_state (self, GST_MSE_SRC_READY_STATE_HAVE_CURRENT_DATA); } else { set_ready_state (self, GST_MSE_SRC_READY_STATE_HAVE_METADATA); } + +done: + MEDIA_SOURCE_UNLOCK (self); }
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/mse/gstsourcebuffer.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/mse/gstsourcebuffer.c
Changed
@@ -77,6 +77,7 @@ #include "gstappendpipeline-private.h" #include "gstmediasource.h" #include "gstmediasource-private.h" +#include "gstmediasourcesamplemap-private.h" #include "gstmediasourcetrack-private.h" #include "gstmediasourcetrackbuffer-private.h" #include "gstsourcebufferlist-private.h" @@ -92,13 +93,17 @@ gpointer user_data; } Callbacks; -/** - * GstSourceBuffer: - * Since: 1.24 - */ typedef struct { GstSourceBuffer *parent; + GstTask *task; + GRecMutex lock; + gboolean cancelled; +} AppendToBufferTask; + +typedef struct +{ + GWeakRef parent; GstMediaSourceTrack *track; GstMediaSourceTrackBuffer *buffer; @@ -111,9 +116,9 @@ typedef struct { - gsize n_samples; - GstSample *current_sample; - GstClockTime current_dts; + GstSourceBuffer *parent; + GHashTable *processed_samples; + gboolean push_failed; } TrackFeedAccumulator; typedef struct @@ -130,6 +135,10 @@ gboolean end_buffered; } IsRangeBufferedAccumulator; +/** + * GstSourceBuffer: + * Since: 1.24 + */ struct _GstSourceBuffer { GstObject parent_instance; @@ -145,14 +154,14 @@ gsize size_limit; gsize size; GstBuffer *pending_data; - GstTask *append_to_buffer_task; - GRecMutex append_to_buffer_lock; - GstClockTime seek_time; + GCond pending_data_cond; + AppendToBufferTask *append_to_buffer_task; GstAppendPipeline *append_pipeline; GstMseEventQueue *event_queue; + GMutex tracks_lock; + GstClockTime seek_time; gboolean processed_init_segment; - GHashTable *track_buffers; GHashTable *track_feeds; @@ -203,30 +212,35 @@ static void call_duration_changed (GstSourceBuffer * self); static void call_active_state_changed (GstSourceBuffer * self); -static inline gboolean is_removed (GstSourceBuffer * self); -static void reset_parser_state (GstSourceBuffer * self); -static void append_error (GstSourceBuffer * self); +static GArray *get_buffered_unlocked (GstSourceBuffer * self); +static inline gboolean is_removed_unlocked (GstSourceBuffer * self); +static void reset_parser_state_unlocked (GstSourceBuffer * self); +static void append_error_unlocked (GstSourceBuffer * self); -static void seek_track_buffer (GstMediaSourceTrack * track, +static void seek_track_buffer_unlocked (GstMediaSourceTrack * track, GstMediaSourceTrackBuffer * buffer, GstSourceBuffer * self); static void dispatch_event (SourceBufferEventItem * item, GstSourceBuffer * self); -static void schedule_event (GstSourceBuffer * self, SourceBufferEvent event); -static void append_to_buffer_task (GstSourceBuffer * self); +static void schedule_event_unlocked (GstSourceBuffer * self, + SourceBufferEvent event); +static void append_to_buffer_task_func (AppendToBufferTask * task); +static void append_to_buffer_task_start (AppendToBufferTask * task); +static void append_to_buffer_task_stop (AppendToBufferTask * task); +static AppendToBufferTask *append_to_buffer_task_new (GstSourceBuffer * parent); +static void append_to_buffer_task_free (AppendToBufferTask * task); static void track_feed_task (TrackFeedTask * feed); static void clear_track_feed (TrackFeedTask * feed); static void stop_track_feed (TrackFeedTask * feed); static void start_track_feed (TrackFeedTask * feed); static void reset_track_feed (TrackFeedTask * feed); -static TrackFeedTask *get_track_feed (GstSourceBuffer * self, - GstMediaSourceTrack * track); -static GstMediaSourceTrackBuffer *get_track_buffer (GstSourceBuffer * self, +static TrackFeedTask *get_track_feed_unlocked (GstSourceBuffer * self, GstMediaSourceTrack * track); -static void add_track_feed (GstMediaSourceTrack * track, +static GstMediaSourceTrackBuffer *get_track_buffer_unlocked (GstSourceBuffer * + self, GstMediaSourceTrack * track); +static void add_track_feed_unlocked (GstMediaSourceTrack * track, GstMediaSourceTrackBuffer * track_buffer, GstSourceBuffer * self); -static void add_track_buffer (GstMediaSourceTrack * track, GstSourceBuffer * - self); -static void update_msesrc_ready_state (GstSourceBuffer * self); +static void add_track_buffer_unlocked (GstMediaSourceTrack * track, + GstSourceBuffer * self); static void on_duration_changed (GstAppendPipeline * pipeline, gpointer user_data); @@ -238,38 +252,41 @@ static void on_received_init_segment (GstAppendPipeline * pipeline, gpointer user_data); +#define TRACKS_LOCK(b) g_mutex_lock(&(b)->tracks_lock) +#define TRACKS_UNLOCK(b) g_mutex_unlock(&(b)->tracks_lock) + static inline GstMediaSource * -get_media_source (GstSourceBuffer * self) +get_media_source_unlocked (GstSourceBuffer * self) { - return GST_MEDIA_SOURCE (gst_object_get_parent (GST_OBJECT (self))); + GstObject *parent = GST_OBJECT_PARENT (self); + if (parent == NULL) { + return NULL; + } + return GST_MEDIA_SOURCE (gst_object_ref (parent)); } -static GstMseSrc * -get_msesrc (GstSourceBuffer * self) +static inline GstMediaSource * +get_media_source (GstSourceBuffer * self) { - GstMediaSource *media_source = get_media_source (self); - if (media_source == NULL) { - return NULL; - } - return gst_media_source_get_source_element (media_source); + return GST_MEDIA_SOURCE (gst_object_get_parent (GST_OBJECT (self))); } static void -clear_pending_data (GstSourceBuffer * self) +clear_pending_data_unlocked (GstSourceBuffer * self) { gst_clear_buffer (&self->pending_data); } static GstBuffer * -take_pending_data (GstSourceBuffer * self) +take_pending_data_unlocked (GstSourceBuffer * self) { return g_steal_pointer (&self->pending_data); } static void -set_pending_data (GstSourceBuffer * self, GstBuffer * buffer) +set_pending_data_unlocked (GstSourceBuffer * self, GstBuffer * buffer) { - clear_pending_data (self); + clear_pending_data_unlocked (self); self->pending_data = buffer; } @@ -293,9 +310,9 @@ ? GST_SOURCE_BUFFER_APPEND_MODE_SEQUENCE : GST_SOURCE_BUFFER_APPEND_MODE_SEGMENTS; - GstSourceBuffer *self = g_object_new (GST_TYPE_SOURCE_BUFFER, - "parent", parent, NULL); + GstSourceBuffer *self = g_object_new (GST_TYPE_SOURCE_BUFFER, NULL); + gst_object_set_parent (GST_OBJECT_CAST (self), parent); self->generate_timestamps = generate_timestamps; self->append_mode = append_mode; self->content_type = g_strdup (content_type); @@ -344,20 +361,27 @@ } static void +gst_source_buffer_constructed (GObject * object) +{ + GstSourceBuffer *self = GST_SOURCE_BUFFER (object); + + append_to_buffer_task_start (self->append_to_buffer_task); + + G_OBJECT_CLASS (gst_source_buffer_parent_class)->constructed (object); +} + +static void gst_source_buffer_dispose (GObject * object) { GstSourceBuffer *self = (GstSourceBuffer *) object; - if (self->append_to_buffer_task) { - gst_task_join (self->append_to_buffer_task); - } - gst_clear_object (&self->append_to_buffer_task); + g_clear_pointer (&self->append_to_buffer_task, append_to_buffer_task_free); gst_clear_object (&self->append_pipeline); g_hash_table_remove_all (self->track_feeds); - if (!is_removed (self)) { + if (!is_removed_unlocked (self)) { GstMediaSource *parent = get_media_source (self); gst_media_source_remove_source_buffer (parent, self, NULL); gst_object_unref (parent); @@ -374,10 +398,10 @@ GstSourceBuffer *self = (GstSourceBuffer *) object; g_clear_pointer (&self->content_type, g_free); - g_rec_mutex_clear (&self->append_to_buffer_lock); g_hash_table_unref (self->track_buffers); g_hash_table_unref (self->track_feeds); + g_mutex_clear (&self->tracks_lock); G_OBJECT_CLASS (gst_source_buffer_parent_class)->finalize (object); } @@ -445,6 +469,7 @@ { GObjectClass *oclass = G_OBJECT_CLASS (klass); + oclass->constructed = GST_DEBUG_FUNCPTR (gst_source_buffer_constructed); oclass->dispose = GST_DEBUG_FUNCPTR (gst_source_buffer_dispose); oclass->finalize = GST_DEBUG_FUNCPTR (gst_source_buffer_finalize); oclass->get_property = GST_DEBUG_FUNCPTR (gst_source_buffer_get_property); @@ -644,9 +669,15 @@ on_duration_changed (GstAppendPipeline * pipeline, gpointer user_data) { GstSourceBuffer *self = GST_SOURCE_BUFFER (user_data); - if (is_removed (self)) { + + GST_OBJECT_LOCK (self); + gboolean removed = is_removed_unlocked (self); + GST_OBJECT_UNLOCK (self); + + if (removed) { return; } + call_duration_changed (self); } @@ -655,23 +686,28 @@ gpointer user_data) { GstSourceBuffer *self = GST_SOURCE_BUFFER (user_data); + if (GST_IS_MEDIA_SOURCE_TRACK (track)) { + TRACKS_LOCK (self); GST_DEBUG_OBJECT (self, "got EOS event on %" GST_PTR_FORMAT, track); - GstMediaSourceTrackBuffer *buffer = get_track_buffer (self, track); + GstMediaSourceTrackBuffer *buffer = get_track_buffer_unlocked (self, track); gst_media_source_track_buffer_eos (buffer); + TRACKS_UNLOCK (self); } - update_msesrc_ready_state (self); } static void on_error (GstAppendPipeline * pipeline, gpointer user_data) { GstSourceBuffer *self = GST_SOURCE_BUFFER (user_data); - append_error (self); + + GST_OBJECT_LOCK (self); + append_error_unlocked (self); + GST_OBJECT_UNLOCK (self); } static GstMediaSourceTrackBuffer * -get_track_buffer (GstSourceBuffer * self, GstMediaSourceTrack * track) +get_track_buffer_unlocked (GstSourceBuffer * self, GstMediaSourceTrack * track) { g_return_val_if_fail (g_hash_table_contains (self->track_buffers, track), NULL); @@ -679,14 +715,14 @@ } static inline TrackFeedTask * -get_track_feed (GstSourceBuffer * self, GstMediaSourceTrack * track) +get_track_feed_unlocked (GstSourceBuffer * self, GstMediaSourceTrack * track) { g_return_val_if_fail (g_hash_table_contains (self->track_feeds, track), NULL); return g_hash_table_lookup (self->track_feeds, track); } static void -add_track_buffer (GstMediaSourceTrack * track, GstSourceBuffer * self) +add_track_buffer_unlocked (GstMediaSourceTrack * track, GstSourceBuffer * self) { const gchar *id = gst_media_source_track_get_id (track); if (g_hash_table_contains (self->track_buffers, track)) { @@ -697,21 +733,25 @@ g_hash_table_insert (self->track_buffers, track, buf); GST_DEBUG_OBJECT (self, "added track buffer for track %s", id); - add_track_feed (track, buf, self); + add_track_feed_unlocked (track, buf, self); } static void -add_track_feed (GstMediaSourceTrack * track, +add_track_feed_unlocked (GstMediaSourceTrack * track, GstMediaSourceTrackBuffer * track_buffer, GstSourceBuffer * self) { TrackFeedTask *feed = g_new0 (TrackFeedTask, 1); GstTask *task = gst_task_new ((GstTaskFunction) track_feed_task, feed, NULL); g_rec_mutex_init (&feed->lock); gst_task_set_lock (task, &feed->lock); + const gchar *track_id = gst_media_source_track_get_id (track); + gchar *name = g_strdup_printf ("%s:%s", GST_OBJECT_NAME (self), track_id); + g_object_set (task, "name", name, NULL); + g_clear_pointer (&name, g_free); feed->task = task; feed->buffer = track_buffer; feed->track = gst_object_ref (track); - feed->parent = self; + g_weak_ref_init (&feed->parent, self); feed->cancelled = FALSE; g_hash_table_insert (self->track_feeds, track, feed); } @@ -722,6 +762,7 @@ gst_object_unref (feed->task); g_rec_mutex_clear (&feed->lock); gst_object_unref (feed->track); + g_weak_ref_clear (&feed->parent); g_free (feed); } @@ -751,7 +792,7 @@ } static gboolean -is_within_append_window (GstSourceBuffer * self, GstSample * sample) +is_within_append_window_unlocked (GstSourceBuffer * self, GstSample * sample) { GstBuffer *buffer = gst_sample_get_buffer (sample); GstClockTime start = GST_BUFFER_PTS (buffer); @@ -774,22 +815,25 @@ { GstSourceBuffer *self = GST_SOURCE_BUFFER (user_data); - g_return_if_fail (self->processed_init_segment); + gboolean processed_init_segment = + g_atomic_int_get (&self->processed_init_segment); + g_return_if_fail (processed_init_segment); GST_OBJECT_LOCK (self); + gboolean is_within_window = is_within_append_window_unlocked (self, sample); + GST_OBJECT_UNLOCK (self); - if (is_within_append_window (self, sample)) { - GstMediaSourceTrackBuffer *track_buffer = get_track_buffer (self, track); + TRACKS_LOCK (self); + if (is_within_window) { + GstMediaSourceTrackBuffer *track_buffer = + get_track_buffer_unlocked (self, track); GST_TRACE_OBJECT (self, "new sample on %s with %" GST_PTR_FORMAT, gst_media_source_track_get_id (track), gst_sample_get_buffer (sample)); gst_media_source_track_buffer_add (track_buffer, sample); - TrackFeedTask *feed = get_track_feed (self, track); + TrackFeedTask *feed = get_track_feed_unlocked (self, track); start_track_feed (feed); } - - GST_OBJECT_UNLOCK (self); - - update_msesrc_ready_state (self); + TRACKS_UNLOCK (self); } static void @@ -841,25 +885,24 @@ GST_DEBUG_OBJECT (self, "got init segment, have duration %" GST_TIME_FORMAT, GST_TIME_ARGS (gst_append_pipeline_get_duration (pipeline))); - GST_OBJECT_LOCK (self); + TRACKS_LOCK (self); - if (!self->processed_init_segment) { + if (g_atomic_int_compare_and_exchange (&self->processed_init_segment, FALSE, + TRUE)) { GST_DEBUG_OBJECT (self, "processing first init segment"); GPtrArray *audio_tracks = gst_append_pipeline_get_audio_tracks (pipeline); GPtrArray *text_tracks = gst_append_pipeline_get_text_tracks (pipeline); GPtrArray *video_tracks = gst_append_pipeline_get_video_tracks (pipeline); - g_ptr_array_foreach (audio_tracks, (GFunc) add_track_buffer, self); - g_ptr_array_foreach (text_tracks, (GFunc) add_track_buffer, self); - g_ptr_array_foreach (video_tracks, (GFunc) add_track_buffer, self); + g_ptr_array_foreach (audio_tracks, (GFunc) add_track_buffer_unlocked, self); + g_ptr_array_foreach (text_tracks, (GFunc) add_track_buffer_unlocked, self); + g_ptr_array_foreach (video_tracks, (GFunc) add_track_buffer_unlocked, self); } - self->processed_init_segment = TRUE; - update_track_buffer_modes (self); - GST_OBJECT_UNLOCK (self); + TRACKS_UNLOCK (self); call_received_init_segment (self); call_active_state_changed (self); @@ -892,16 +935,15 @@ self->size_limit = DEFAULT_BUFFER_SIZE; self->size = 0; self->pending_data = NULL; + g_cond_init (&self->pending_data_cond); self->processed_init_segment = FALSE; self->event_queue = gst_mse_event_queue_new ((GstMseEventQueueCallback) dispatch_event, self); - g_rec_mutex_init (&self->append_to_buffer_lock); - self->append_to_buffer_task = gst_task_new ( - (GstTaskFunction) append_to_buffer_task, self, NULL); - gst_task_set_lock (self->append_to_buffer_task, &self->append_to_buffer_lock); + self->append_to_buffer_task = append_to_buffer_task_new (self); self->track_buffers = g_hash_table_new_full ((GHashFunc) track_buffer_hash, (GEqualFunc) track_buffer_equal, NULL, gst_object_unref); + g_mutex_init (&self->tracks_lock); self->track_feeds = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) clear_track_feed); @@ -911,19 +953,17 @@ } static inline gboolean -is_removed (GstSourceBuffer * self) +is_removed_unlocked (GstSourceBuffer * self) { - GstObject *parent = gst_object_get_parent (GST_OBJECT (self)); + GstObject *parent = GST_OBJECT_PARENT (self); if (parent == NULL) { return TRUE; } - gst_object_unref (parent); - GstMediaSource *source = get_media_source (self); + GstMediaSource *source = GST_MEDIA_SOURCE (parent); GstSourceBufferList *buffers = gst_media_source_get_source_buffers (source); gboolean removed = !gst_source_buffer_list_contains (buffers, self); - gst_object_unref (source); gst_object_unref (buffers); return removed; @@ -966,13 +1006,13 @@ } static inline gboolean -is_ended (GstSourceBuffer * self) +is_ended_unlocked (GstSourceBuffer * self) { - if (is_removed (self)) { + if (is_removed_unlocked (self)) { return TRUE; } - GstMediaSource *source = get_media_source (self); + GstMediaSource *source = get_media_source_unlocked (self); gboolean ended = gst_media_source_get_ready_state (source) == GST_MEDIA_SOURCE_READY_STATE_ENDED; @@ -982,10 +1022,10 @@ } static void -open_parent (GstSourceBuffer * self) +open_parent_unlocked (GstSourceBuffer * self) { - g_return_if_fail (!is_removed (self)); - GstMediaSource *source = get_media_source (self); + g_return_if_fail (!is_removed_unlocked (self)); + GstMediaSource *source = get_media_source_unlocked (self); gst_media_source_open (source); gst_object_unref (source); } @@ -1003,7 +1043,11 @@ gst_source_buffer_get_append_mode (GstSourceBuffer * self) { g_return_val_if_fail (GST_IS_SOURCE_BUFFER (self), DEFAULT_APPEND_MODE); - return self->append_mode; + GST_OBJECT_LOCK (self); + GstSourceBufferAppendMode append_mode = self->append_mode; + GST_OBJECT_UNLOCK (self); + + return append_mode; } /** @@ -1029,18 +1073,20 @@ { g_return_val_if_fail (GST_IS_SOURCE_BUFFER (self), FALSE); - if (is_removed (self)) { + GST_OBJECT_LOCK (self); + + if (is_removed_unlocked (self)) { g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_INVALID_STATE, "buffer is removed"); - return FALSE; + goto error; } if (is_updating (self)) { g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_INVALID_STATE, "buffer is still updating"); - return FALSE; + goto error; } if (self->generate_timestamps && mode == @@ -1048,16 +1094,24 @@ g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_TYPE, "cannot change to segments mode while generate timestamps is active"); - return FALSE; + goto error; } - if (is_ended (self)) { - open_parent (self); + if (is_ended_unlocked (self)) { + open_parent_unlocked (self); } self->append_mode = mode; + + GST_OBJECT_UNLOCK (self); + g_object_notify_by_pspec (G_OBJECT (self), propertiesPROP_APPEND_MODE); + return TRUE; + +error: + GST_OBJECT_UNLOCK (self); + return FALSE; } /** @@ -1076,7 +1130,12 @@ gst_source_buffer_get_append_window_start (GstSourceBuffer * self) { g_return_val_if_fail (GST_IS_SOURCE_BUFFER (self), GST_CLOCK_TIME_NONE); - return self->append_window_start; + + GST_OBJECT_LOCK (self); + GstClockTime append_window_start = self->append_window_start; + GST_OBJECT_UNLOCK (self); + + return append_window_start; } /** @@ -1100,32 +1159,42 @@ { g_return_val_if_fail (GST_IS_SOURCE_BUFFER (self), FALSE); - if (is_removed (self)) { + GST_OBJECT_LOCK (self); + + if (is_removed_unlocked (self)) { g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_INVALID_STATE, "append window start cannot be set on source buffer " "with no media source"); - return FALSE; + goto error; } if (is_updating (self)) { g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_INVALID_STATE, "append window start cannot be set on source buffer while updating"); - return FALSE; + goto error; } if (!GST_CLOCK_TIME_IS_VALID (start) || start <= self->append_window_end) { g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_TYPE, "append window start must be between zero and append window end"); - return FALSE; + goto error; } self->append_window_start = start; + + GST_OBJECT_UNLOCK (self); + g_object_notify_by_pspec (G_OBJECT (self), propertiesPROP_APPEND_WINDOW_START); + return TRUE; + +error: + GST_OBJECT_UNLOCK (self); + return FALSE; } /** @@ -1144,7 +1213,12 @@ gst_source_buffer_get_append_window_end (GstSourceBuffer * self) { g_return_val_if_fail (GST_IS_SOURCE_BUFFER (self), GST_CLOCK_TIME_NONE); - return self->append_window_end; + + GST_OBJECT_LOCK (self); + GstClockTime append_window_end = self->append_window_end; + GST_OBJECT_UNLOCK (self); + + return append_window_end; } /** @@ -1168,32 +1242,42 @@ { g_return_val_if_fail (GST_IS_SOURCE_BUFFER (self), FALSE); - if (is_removed (self)) { + GST_OBJECT_LOCK (self); + + if (is_removed_unlocked (self)) { g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_INVALID_STATE, "append window end cannot be set on source buffer " "with no media source"); - return FALSE; + goto error; } if (is_updating (self)) { g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_INVALID_STATE, "append window end cannot be set on source buffer while updating"); - return FALSE; + goto error; } if (end <= self->append_window_start) { g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_TYPE, "append window end must be after append window start"); - return FALSE; + goto error; } self->append_window_end = end; + + GST_OBJECT_UNLOCK (self); + g_object_notify_by_pspec (G_OBJECT (self), propertiesPROP_APPEND_WINDOW_END); + return TRUE; + +error: + GST_OBJECT_UNLOCK (self); + return FALSE; } static gboolean @@ -1270,6 +1354,16 @@ gst_source_buffer_get_buffered (GstSourceBuffer * self, GError ** error) { g_return_val_if_fail (GST_IS_SOURCE_BUFFER (self), NULL); + + TRACKS_LOCK (self); + GArray *buffered = get_buffered_unlocked (self); + TRACKS_UNLOCK (self); + return buffered; +} + +static GArray * +get_buffered_unlocked (GstSourceBuffer * self) +{ GHashTableIter iter; GArray *buffered = NULL; g_hash_table_iter_init (&iter, self->track_buffers); @@ -1292,6 +1386,7 @@ g_array_unref (buffered); buffered = intersection; } + if (buffered == NULL) { return g_array_new_ranges (); } else { @@ -1345,23 +1440,28 @@ return FALSE; } - if (is_removed (self)) { + GST_OBJECT_LOCK (self); + + if (is_removed_unlocked (self)) { g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_INVALID_STATE, "content type cannot be set on source buffer with no media source"); - return FALSE; + goto error; } if (is_updating (self)) { g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_INVALID_STATE, "content type cannot be set on source buffer that is updating"); - return FALSE; + goto error; } g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_NOT_SUPPORTED, "content type cannot be changed"); + +error: + GST_OBJECT_UNLOCK (self); return FALSE; } @@ -1399,7 +1499,13 @@ GstClockTime gst_source_buffer_get_timestamp_offset (GstSourceBuffer * self) { - return self->timestamp_offset; + g_return_val_if_fail (GST_IS_SOURCE_BUFFER (self), FALSE); + + GST_OBJECT_LOCK (self); + GstClockTime timestamp_offset = self->timestamp_offset; + GST_OBJECT_UNLOCK (self); + + return timestamp_offset; } /** @@ -1421,34 +1527,46 @@ offset, GError ** error) { g_return_val_if_fail (GST_IS_SOURCE_BUFFER (self), FALSE); - if (is_removed (self)) { + + GST_OBJECT_LOCK (self); + + if (is_removed_unlocked (self)) { g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_INVALID_STATE, "source buffer is removed"); - return FALSE; + goto error; } if (is_updating (self)) { g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_INVALID_STATE, "source buffer is still updating"); - return FALSE; + goto error; } - if (is_ended (self)) { - GstMediaSource *parent = get_media_source (self); + if (is_ended_unlocked (self)) { + GstMediaSource *parent = get_media_source_unlocked (self); gst_media_source_open (parent); gst_clear_object (&parent); } - GST_OBJECT_LOCK (self); + TRACKS_LOCK (self); GHashTableIter iter; g_hash_table_iter_init (&iter, self->track_buffers); for (gpointer value; g_hash_table_iter_next (&iter, NULL, &value);) { GstMediaSourceTrackBuffer *buffer = value; gst_media_source_track_buffer_set_group_start (buffer, offset); } + TRACKS_UNLOCK (self); + self->timestamp_offset = offset; + GST_OBJECT_UNLOCK (self); + g_object_notify_by_pspec (G_OBJECT (self), propertiesPROP_TIMESTAMP_OFFSET); + return TRUE; + +error: + GST_OBJECT_UNLOCK (self); + return FALSE; } /** @@ -1481,24 +1599,22 @@ } static gboolean -will_overflow (GstSourceBuffer * self, gsize bytes) +will_overflow_unlocked (GstSourceBuffer * self, gsize bytes) { - GST_OBJECT_LOCK (self); gsize total = compute_total_size_unlocked (self); - GST_OBJECT_UNLOCK (self); return total + bytes > self->size_limit; } static void -evict_coded_frames (GstSourceBuffer * self, gsize space_required, +evict_coded_frames_unlocked (GstSourceBuffer * self, gsize space_required, gsize size_limit, GstClockTime position, GstClockTime duration) { - if (!will_overflow (self, space_required)) { + if (!will_overflow_unlocked (self, space_required)) { return; } if (!GST_CLOCK_TIME_IS_VALID (position)) { - GST_ERROR ("invalid position, cannot delete anything"); + GST_ERROR_OBJECT (self, "invalid position, cannot delete anything"); return; } @@ -1509,7 +1625,6 @@ GST_DEBUG_OBJECT (self, "position=%" GST_TIMEP_FORMAT ", attempting removal from 0 to %" GST_TIMEP_FORMAT, &position, &max_dts); - GST_OBJECT_LOCK (self); GHashTableIter iter; g_hash_table_iter_init (&iter, self->track_buffers); for (gpointer value; g_hash_table_iter_next (&iter, NULL, &value);) { @@ -1517,7 +1632,6 @@ gst_media_source_track_buffer_remove_range (buffer, 0, max_dts); } self->size = compute_total_size_unlocked (self); - GST_OBJECT_UNLOCK (self); GST_DEBUG_OBJECT (self, "capacity=%" G_GSIZE_FORMAT "/%" G_GSIZE_FORMAT "(%" G_GSIZE_FORMAT "%%)", self->size, self->size_limit, @@ -1525,9 +1639,9 @@ } static void -reset_parser_state (GstSourceBuffer * self) +reset_parser_state_unlocked (GstSourceBuffer * self) { - clear_pending_data (self); + clear_pending_data_unlocked (self); if (gst_append_pipeline_reset (self->append_pipeline)) { clear_errored (self); } else { @@ -1536,59 +1650,118 @@ } static void -append_error (GstSourceBuffer * self) +append_error_unlocked (GstSourceBuffer * self) { - gst_task_stop (self->append_to_buffer_task); - reset_parser_state (self); + reset_parser_state_unlocked (self); clear_updating (self); - if (is_removed (self)) { + if (is_removed_unlocked (self)) { return; } - schedule_event (self, ON_ERROR); - schedule_event (self, ON_UPDATE_END); + schedule_event_unlocked (self, ON_ERROR); + schedule_event_unlocked (self, ON_UPDATE_END); - GstMediaSource *source = get_media_source (self); + GstMediaSource *source = get_media_source_unlocked (self); gst_media_source_end_of_stream (source, GST_MEDIA_SOURCE_EOS_ERROR_DECODE, NULL); gst_object_unref (source); } static void -append_successful (GstSourceBuffer * self, gboolean ended) +append_successful_unlocked (GstSourceBuffer * self, gboolean ended) { - gst_task_stop (self->append_to_buffer_task); clear_updating (self); - schedule_event (self, ON_UPDATE); - schedule_event (self, ON_UPDATE_END); + schedule_event_unlocked (self, ON_UPDATE); + schedule_event_unlocked (self, ON_UPDATE_END); } static gboolean -encountered_bad_bytes (GstSourceBuffer * self) +encountered_bad_bytes_unlocked (GstSourceBuffer * self) { return gst_append_pipeline_get_failed (self->append_pipeline); } +static GstBuffer * +await_pending_data_unlocked (GstSourceBuffer * self) +{ + if (self->pending_data == NULL) { + guint64 deadline = g_get_monotonic_time () + G_TIME_SPAN_SECOND; + g_cond_wait_until (&self->pending_data_cond, GST_OBJECT_GET_LOCK (self), + deadline); + } + return take_pending_data_unlocked (self); +} + +static AppendToBufferTask * +append_to_buffer_task_new (GstSourceBuffer * parent) +{ + AppendToBufferTask *task = g_new0 (AppendToBufferTask, 1); + g_rec_mutex_init (&task->lock); + task->parent = parent; + task->task = + gst_task_new ((GstTaskFunction) append_to_buffer_task_func, task, NULL); + task->cancelled = FALSE; + gst_task_set_lock (task->task, &task->lock); + return task; +} + +static void +append_to_buffer_task_free (AppendToBufferTask * task) +{ + append_to_buffer_task_stop (task); + gst_task_join (task->task); + gst_clear_object (&task->task); + g_rec_mutex_clear (&task->lock); + task->parent = NULL; + g_free (task); +} + +static void +append_to_buffer_task_start (AppendToBufferTask * task) +{ + gchar *name = g_strdup_printf ("%s:append", GST_OBJECT_NAME (task->parent)); + g_object_set (task->task, "name", name, NULL); + gst_task_start (task->task); + g_free (name); +} + +static void +append_to_buffer_task_stop (AppendToBufferTask * task) +{ + gst_task_stop (task->task); + g_atomic_int_set (&task->cancelled, TRUE); + g_cond_signal (&task->parent->pending_data_cond); +} + static void -append_to_buffer_task (GstSourceBuffer * self) +append_to_buffer_task_func (AppendToBufferTask * task) { - if (is_removed (self)) { - append_successful (self, TRUE); + GstSourceBuffer *self = task->parent; + if (g_atomic_int_get (&task->cancelled)) { + GST_LOG_OBJECT (task->task, "task is done"); + append_to_buffer_task_stop (task); return; } - if (encountered_bad_bytes (self)) { - append_error (self); - return; + GST_OBJECT_LOCK (self); + + GstBuffer *pending_data = await_pending_data_unlocked (self); + + if (is_removed_unlocked (self)) { + append_successful_unlocked (self, TRUE); + goto done; } - GstBuffer *pending_data = take_pending_data (self); + if (encountered_bad_bytes_unlocked (self)) { + append_error_unlocked (self); + goto done; + } if (!GST_IS_BUFFER (pending_data)) { - GST_LOG_OBJECT (self, "no pending data"); - append_successful (self, is_ended (self)); - return; + GST_TRACE_OBJECT (self, "no pending data"); + append_successful_unlocked (self, is_ended_unlocked (self)); + goto done; } GstFlowReturn result = gst_append_pipeline_append (self->append_pipeline, @@ -1596,68 +1769,99 @@ if (result != GST_FLOW_OK) { GST_ERROR_OBJECT (self, "failed to append: %s", gst_flow_get_name (result)); - append_error (self); - return; + append_error_unlocked (self); + goto done; } - append_successful (self, is_ended (self)); + append_successful_unlocked (self, is_ended_unlocked (self)); + +done: + GST_OBJECT_UNLOCK (self); } static gboolean track_feed_fold (const GValue * item, TrackFeedAccumulator * acc, TrackFeedTask * feed) { - GstSample *sample = gst_sample_ref (gst_value_get_sample (item)); - GstClockTime dts = GST_BUFFER_DTS (gst_sample_get_buffer (sample)); - acc->n_samples++; - acc->current_dts = dts; - gst_clear_sample (&acc->current_sample); - acc->current_sample = gst_sample_ref (sample); - if (gst_media_source_track_push (feed->track, sample)) { - return TRUE; - } else { - gst_sample_unref (sample); + if (g_atomic_int_get (&feed->cancelled)) { return FALSE; } + GstSourceBuffer *self = acc->parent; + + GstMediaSourceCodedFrameGroup *group = + gst_value_get_media_source_coded_frame_group (item); + if (group == NULL) { + return FALSE; + } + + for (GList * it = group->samples; it != NULL; it = g_list_next (it)) { + GstSample *sample = GST_SAMPLE (it->data); + if (!g_hash_table_add (acc->processed_samples, gst_sample_ref (sample))) { + continue; + } + if (!gst_media_source_track_push (feed->track, sample)) { + g_hash_table_remove (acc->processed_samples, sample); + GST_LOG_OBJECT (self, "%s: failed to push sample to track", + gst_media_source_track_get_id (feed->track)); + acc->push_failed = TRUE; + return FALSE; + } + } + + return TRUE; +} + +static gint +clip_to_seek_time_dts (const GValue * a, const GValue * b) +{ + GstMediaSourceCodedFrameGroup *group = + gst_value_get_media_source_coded_frame_group (a); + GstClockTime start_dts = g_value_get_uint64 (b); + return group != NULL && start_dts > group->end; } static void track_feed_task (TrackFeedTask * feed) { - GstSourceBuffer *self = feed->parent; + GstSourceBuffer *self = g_weak_ref_get (&feed->parent); + if (self == NULL) { + gst_task_stop (feed->task); + return; + } GstMediaSourceTrack *track = feed->track; GstMediaSourceTrackBuffer *buffer = feed->buffer; - GstClockTime time = feed->parent->seek_time; + GstClockTime time = self->seek_time; const gchar *track_id = gst_media_source_track_get_id (track); GST_DEBUG_OBJECT (self, "%s: feed starting@%" GST_TIMEP_FORMAT, track_id, &time); TrackFeedAccumulator acc = { - .n_samples = 0, - .current_dts = time, - .current_sample = NULL, + .parent = self, + .processed_samples = g_hash_table_new_full (g_direct_hash, g_direct_equal, + (GDestroyNotify) gst_sample_unref, NULL), + .push_failed = FALSE, }; + GValue start_dts_value = G_VALUE_INIT; + g_value_init (&start_dts_value, G_TYPE_UINT64); + g_value_set_uint64 (&start_dts_value, time); while (TRUE) { gboolean eos = gst_media_source_track_buffer_is_eos (buffer); - GstIterator *it = gst_media_source_track_buffer_iter_samples (buffer, - acc.current_dts, acc.current_sample); - while (TRUE) { - GstIteratorResult fold_result = gst_iterator_fold (it, - (GstIteratorFoldFunction) track_feed_fold, (GValue *) & acc, feed); - if (fold_result != GST_ITERATOR_RESYNC) { - break; - } - if (g_atomic_int_get (&feed->cancelled)) { - break; - } - gst_iterator_resync (it); + GstIterator *it = gst_media_source_track_buffer_iter_samples (buffer); + it = gst_iterator_filter (it, (GCompareFunc) clip_to_seek_time_dts, + &start_dts_value); + gst_iterator_fold (it, (GstIteratorFoldFunction) track_feed_fold, + (GValue *) & acc, feed); + g_clear_pointer (&it, gst_iterator_free); + + if (acc.push_failed) { + gst_task_stop (feed->task); + break; } - gst_iterator_free (it); if (eos) { - GST_DEBUG_OBJECT (self, "%s: enqueued all %" G_GSIZE_FORMAT " samples", - track_id, acc.n_samples); + GST_DEBUG_OBJECT (self, "%s: enqueued all %u samples", track_id, + g_hash_table_size (acc.processed_samples)); gst_media_source_track_push_eos (track); GST_DEBUG_OBJECT (self, "%s: marked EOS", track_id); gst_task_stop (feed->task); @@ -1670,13 +1874,14 @@ break; } - GST_DEBUG_OBJECT (self, "%s: resume after %" G_GSIZE_FORMAT " samples", - track_id, acc.n_samples); + GST_TRACE_OBJECT (self, "%s: resume after %u samples", + track_id, g_hash_table_size (acc.processed_samples)); gint64 deadline = g_get_monotonic_time () + G_TIME_SPAN_SECOND; - gst_media_source_track_buffer_await_eos_until (buffer, deadline); + gst_media_source_track_buffer_await_new_data_until (buffer, deadline); } - - gst_clear_sample (&acc.current_sample); + g_clear_pointer (&acc.processed_samples, g_hash_table_unref); + g_value_unset (&start_dts_value); + gst_clear_object (&self); } static void @@ -1686,10 +1891,10 @@ } static void -schedule_event (GstSourceBuffer * self, SourceBufferEvent event) +schedule_event_unlocked (GstSourceBuffer * self, SourceBufferEvent event) { g_return_if_fail (event < N_SIGNALS); - if (is_removed (self)) { + if (is_removed_unlocked (self)) { return; } SourceBufferEventItem item = { @@ -1703,21 +1908,7 @@ static void schedule_append_to_buffer_task (GstSourceBuffer * self) { - GstTask *task = self->append_to_buffer_task; - g_return_if_fail (GST_IS_TASK (task)); - g_return_if_fail (gst_task_get_state (task) != GST_TASK_STARTED); - gst_task_start (task); -} - -static void -update_msesrc_ready_state (GstSourceBuffer * self) -{ - GstMseSrc *element = get_msesrc (self); - if (element == NULL) { - return; - } - gst_mse_src_update_ready_state (element); - gst_object_unref (element); + g_cond_signal (&self->pending_data_cond); } /** @@ -1742,49 +1933,61 @@ g_return_val_if_fail (GST_IS_SOURCE_BUFFER (self), FALSE); g_return_val_if_fail (GST_IS_BUFFER (buf), FALSE); - if (is_removed (self) || is_updating (self)) { + GST_OBJECT_LOCK (self); + TRACKS_LOCK (self); + + if (is_removed_unlocked (self) || is_updating (self)) { g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_INVALID_STATE, "source buffer is removed or still updating"); - return FALSE; + goto error; } if (is_errored (self)) { g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_INVALID_STATE, "source buffer has encountered error"); - return FALSE; + goto error; } - if (is_ended (self)) { - open_parent (self); + if (is_ended_unlocked (self)) { + open_parent_unlocked (self); } - GstMediaSource *source = get_media_source (self); + GstMediaSource *source = get_media_source_unlocked (self); gsize buffer_size = gst_buffer_get_size (buf); GstClockTime position = gst_media_source_get_position (source); GstClockTime duration = gst_media_source_get_duration (source); gst_object_unref (source); - evict_coded_frames (self, buffer_size, self->size_limit, position, duration); + evict_coded_frames_unlocked (self, buffer_size, self->size_limit, position, + duration); - if (will_overflow (self, buffer_size)) { + if (will_overflow_unlocked (self, buffer_size)) { g_set_error (error, GST_MEDIA_SOURCE_ERROR, GST_MEDIA_SOURCE_ERROR_QUOTA_EXCEEDED, "buffer is full"); - return FALSE; + goto error; } g_return_val_if_fail (self->pending_data == NULL, FALSE); - set_pending_data (self, buf); + set_pending_data_unlocked (self, buf); set_updating (self); - schedule_event (self, ON_UPDATE_START); + schedule_event_unlocked (self, ON_UPDATE_START); schedule_append_to_buffer_task (self); + TRACKS_UNLOCK (self); + GST_OBJECT_UNLOCK (self); return TRUE; + +error: + TRACKS_UNLOCK (self); + GST_OBJECT_UNLOCK (self); + gst_clear_buffer (&buf); + return FALSE; } /** @@ -1825,28 +2028,32 @@ is_buffered_fold (const GValue * item, IsBufferedAccumulator * acc, GstSourceBuffer * self) { - GstSample *sample = gst_value_get_sample (item); - GstBuffer *buffer = gst_sample_get_buffer (sample); - GstClockTime buffer_start = GST_BUFFER_DTS (buffer); - GstClockTime buffer_end = buffer_start + GST_BUFFER_DURATION (buffer); - if (acc->time < buffer_start) { - GST_TRACE_OBJECT (self, "position precedes buffer start, done"); + GstMediaSourceCodedFrameGroup *group = + gst_value_get_media_source_coded_frame_group (item); + if (group == NULL) { + acc->buffered = FALSE; + return FALSE; + } + GstClockTime start = group->start; + GstClockTime end = group->end; + if (acc->time < start) { + GST_TRACE_OBJECT (self, "position precedes group start, done"); acc->buffered = FALSE; return FALSE; } - if (acc->time >= buffer_start && acc->time < buffer_end) { - GST_TRACE_OBJECT (self, "position is within buffer, done"); + if (acc->time >= start && acc->time < end) { + GST_TRACE_OBJECT (self, "position is within group, done"); acc->buffered = TRUE; return FALSE; } return TRUE; } -gboolean -gst_source_buffer_is_buffered (GstSourceBuffer * self, GstClockTime time) +static gboolean +is_buffered_unlocked (GstSourceBuffer * self, GstClockTime time) { - GHashTableIter iter; gboolean buffered = TRUE; + GHashTableIter iter; g_hash_table_iter_init (&iter, self->track_buffers); for (gpointer key, value; buffered && g_hash_table_iter_next (&iter, &key, &value);) { @@ -1859,26 +2066,35 @@ .time = time, .buffered = FALSE, }; - GstIterator *iter = - gst_media_source_track_buffer_iter_samples (track_buffer, time, NULL); - while (gst_iterator_fold (iter, (GstIteratorFoldFunction) is_buffered_fold, - (GValue *) & acc, self) == GST_ITERATOR_RESYNC) { - gst_iterator_resync (iter); - } - gst_iterator_free (iter); + GstIterator *it = gst_media_source_track_buffer_iter_samples (track_buffer); + gst_iterator_fold (it, (GstIteratorFoldFunction) is_buffered_fold, + (GValue *) & acc, self); + g_clear_pointer (&it, gst_iterator_free); buffered = acc.buffered; } return buffered; } +gboolean +gst_source_buffer_is_buffered (GstSourceBuffer * self, GstClockTime time) +{ + TRACKS_LOCK (self); + gboolean buffered = is_buffered_unlocked (self, time); + TRACKS_UNLOCK (self); + return buffered; +} + static gboolean is_range_buffered_fold (const GValue * item, IsRangeBufferedAccumulator * acc, GstSourceBuffer * self) { - GstSample *sample = gst_value_get_sample (item); - GstBuffer *buffer = gst_sample_get_buffer (sample); - GstClockTime buffer_start = GST_BUFFER_DTS (buffer); - GstClockTime buffer_end = buffer_start + GST_BUFFER_DURATION (buffer); + GstMediaSourceCodedFrameGroup *group = + gst_value_get_media_source_coded_frame_group (item); + if (group == NULL) { + return FALSE; + } + GstClockTime buffer_start = group->start; + GstClockTime buffer_end = group->end; GstClockTime start = acc->start; GstClockTime end = acc->end; @@ -1914,6 +2130,7 @@ { GHashTableIter iter; gboolean buffered = TRUE; + TRACKS_LOCK (self); g_hash_table_iter_init (&iter, self->track_buffers); for (gpointer key, value; buffered && g_hash_table_iter_next (&iter, &key, &value);) { @@ -1928,16 +2145,13 @@ .start_buffered = FALSE, .end_buffered = FALSE, }; - GstIterator *iter = - gst_media_source_track_buffer_iter_samples (track_buffer, start, NULL); - while (gst_iterator_fold (iter, - (GstIteratorFoldFunction) is_range_buffered_fold, (GValue *) & acc, - self) == GST_ITERATOR_RESYNC) { - gst_iterator_resync (iter); - } + GstIterator *it = gst_media_source_track_buffer_iter_samples (track_buffer); + gst_iterator_fold (it, (GstIteratorFoldFunction) is_range_buffered_fold, + (GValue *) & acc, self); + g_clear_pointer (&it, gst_iterator_free); buffered = acc.end_buffered; - gst_iterator_free (iter); } + TRACKS_UNLOCK (self); return buffered; } @@ -1951,8 +2165,10 @@ void gst_source_buffer_teardown (GstSourceBuffer * self) { - reset_parser_state (self); + GST_OBJECT_LOCK (self); + reset_parser_state_unlocked (self); clear_updating (self); + GST_OBJECT_UNLOCK (self); } GPtrArray * @@ -1983,10 +2199,10 @@ } static void -seek_track_buffer (GstMediaSourceTrack * track, +seek_track_buffer_unlocked (GstMediaSourceTrack * track, GstMediaSourceTrackBuffer * buffer, GstSourceBuffer * self) { - TrackFeedTask *feed = get_track_feed (self, track); + TrackFeedTask *feed = get_track_feed_unlocked (self, track); const gchar *track_id = gst_media_source_track_get_id (track); GST_DEBUG_OBJECT (self, "%s: seeking", track_id); @@ -1999,8 +2215,12 @@ { g_return_if_fail (GST_IS_SOURCE_BUFFER (self)); g_return_if_fail (GST_CLOCK_TIME_IS_VALID (time)); + + TRACKS_LOCK (self); self->seek_time = time; - g_hash_table_foreach (self->track_buffers, (GHFunc) seek_track_buffer, self); + g_hash_table_foreach (self->track_buffers, + (GHFunc) seek_track_buffer_unlocked, self); + TRACKS_UNLOCK (self); } gboolean @@ -2008,12 +2228,14 @@ { gboolean active = FALSE; GHashTableIter iter; - GST_OBJECT_LOCK (self); + + TRACKS_LOCK (self); g_hash_table_iter_init (&iter, self->track_buffers); for (gpointer key; !active && g_hash_table_iter_next (&iter, &key, NULL);) { GstMediaSourceTrack *track = GST_MEDIA_SOURCE_TRACK (key); active |= gst_media_source_track_get_active (track); } - GST_OBJECT_UNLOCK (self); + TRACKS_UNLOCK (self); + return active; }
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/mse/gstsourcebufferlist.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/mse/gstsourcebufferlist.c
Changed
@@ -98,6 +98,12 @@ static GParamSpec *propertiesN_PROPS; static guint signalsN_SIGNALS = { 0 }; +static guint +get_length_unlocked (GstSourceBufferList * self) +{ + return self->buffers->len; +} + static gboolean is_frozen (GstSourceBufferList * self) { @@ -306,9 +312,14 @@ gst_source_buffer_list_index (GstSourceBufferList * self, guint index) { g_return_val_if_fail (GST_IS_SOURCE_BUFFER_LIST (self), NULL); - if (index >= gst_source_buffer_list_get_length (self)) - return NULL; - return gst_object_ref (g_ptr_array_index (self->buffers, index)); + + GST_OBJECT_LOCK (self); + guint length = get_length_unlocked (self); + GstSourceBuffer *buf = index >= length ? NULL : gst_object_ref + (g_ptr_array_index (self->buffers, index)); + GST_OBJECT_UNLOCK (self); + + return buf; } /** @@ -324,7 +335,12 @@ gst_source_buffer_list_get_length (GstSourceBufferList * self) { g_return_val_if_fail (GST_IS_SOURCE_BUFFER_LIST (self), 0); - return self->buffers->len; + + GST_OBJECT_LOCK (self); + guint length = get_length_unlocked (self); + GST_OBJECT_UNLOCK (self); + + return length; } gboolean @@ -333,7 +349,12 @@ { g_return_val_if_fail (GST_IS_SOURCE_BUFFER_LIST (self), FALSE); g_return_val_if_fail (GST_IS_SOURCE_BUFFER (buf), FALSE); - return g_ptr_array_find (self->buffers, buf, NULL); + + GST_OBJECT_LOCK (self); + gboolean found = g_ptr_array_find (self->buffers, buf, NULL); + GST_OBJECT_UNLOCK (self); + + return found; } void @@ -341,7 +362,11 @@ GstSourceBuffer * buf) { g_return_if_fail (GST_IS_SOURCE_BUFFER_LIST (self)); + + GST_OBJECT_LOCK (self); g_ptr_array_add (self->buffers, gst_object_ref (buf)); + GST_OBJECT_UNLOCK (self); + call_source_buffer_added (self); }
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/va/gstvadisplay_drm.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/va/gstvadisplay_drm.c
Changed
@@ -94,6 +94,7 @@ switch (prop_id) { case PROP_PATH: + /* G_PARAM_CONSTRUCT_ONLY */ self->path = g_value_dup_string (value); break; default:
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/vulkan/gstvkformat.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/vulkan/gstvkformat.c
Changed
@@ -614,13 +614,18 @@ #endif gst_vkGetPhysicalDeviceFormatProperties2 (gpu, format, &prop2); - if (supports_KHR_format_feature_flags2 (device)) + if (supports_KHR_format_feature_flags2 (device)) { +#if defined (VK_KHR_format_feature_flags2) return tiling == VK_IMAGE_TILING_LINEAR ? prop3.linearTilingFeatures : prop3.optimalTilingFeatures; - else +#else + g_assert_not_reached (); +#endif + } else { return tiling == VK_IMAGE_TILING_LINEAR ? prop2.formatProperties.linearTilingFeatures : prop2.formatProperties.optimalTilingFeatures; + } } #endif /* defined (VK_KHR_get_physical_device_properties2) */
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/webrtc/ice.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/webrtc/ice.c
Changed
@@ -182,6 +182,7 @@ * gst_webrtc_ice_gather_candidates: * @ice: The #GstWebRTCICE * @stream: The #GstWebRTCICEStream + * * Returns: FALSE on error, TRUE otherwise * * Since: 1.22 @@ -215,6 +216,7 @@ /** * gst_webrtc_ice_get_is_controller: * @ice: The #GstWebRTCICE + * * Returns: TRUE if set as controller, FALSE otherwise * * Since: 1.22 @@ -267,7 +269,8 @@ * gst_webrtc_ice_get_local_candidates: * @ice: The #GstWebRTCICE * @stream: The #GstWebRTCICEStream - * Returns: (transfer full)(array zero-terminated=1): List of local candidates + * + * Returns: (transfer full) (array zero-terminated=1): List of local candidates * * Since: 1.22 */ @@ -286,6 +289,7 @@ * gst_webrtc_ice_get_remote_candidates: * @ice: The #GstWebRTCICE * @stream: The #GstWebRTCICEStream + * * Returns: (transfer full) (array zero-terminated=1): List of remote candidates * * Since: 1.22
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-libs/gst/webrtc/icestream.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-libs/gst/webrtc/icestream.c
Changed
@@ -17,9 +17,9 @@ * Boston, MA 02110-1301, USA. */ /** - * SECTION: icestream - * @short_description: IceStream object - * @title: GstIceStream + * SECTION: GstWebRTCICEStream + * @short_description: GstWebRTCICEStream object + * @title: GstWebRTCICEStream * @symbols: * - GstWebRTCICEStream */
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst-plugins-bad.doap -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst-plugins-bad.doap
Changed
@@ -35,6 +35,16 @@ <release> <Version> + <revision>1.26.1</revision> + <branch>1.26</branch> + <name></name> + <created>2025-04-24</created> + <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gst-plugins-bad/gst-plugins-bad-1.26.1.tar.xz" /> + </Version> + </release> + + <release> + <Version> <revision>1.26.0</revision> <branch>main</branch> <name></name>
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst/codecalpha/gstalphacombine.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst/codecalpha/gstalphacombine.c
Changed
@@ -107,8 +107,18 @@ GMutex buffer_lock; GCond buffer_cond; GstBuffer *alpha_buffer; - /* Ref-counted flushing state */ - guint flushing; + /* flushing state, protected by buffer_lock */ + gboolean flushing; + /* Number of flush-stop events received, used to know when all sink pads are + done flushing. Protected by buffer_lock */ + guint flush_stops; + /* alpha stream EOS, protected by buffer_lock */ + gboolean alpha_eos; + + /* sink pad being blocked while waiting for the other pad to receive + * FLUSH_STOP. Protected by buffer_lock */ + GstPad *blocked_pad; + gulong pad_block_id; GstVideoInfo sink_vinfo; GstVideoInfo alpha_vinfo; @@ -152,33 +162,83 @@ gst_alpha_combine_unlock (GstAlphaCombine * self) { g_mutex_lock (&self->buffer_lock); - self->flushing++; + self->flushing = TRUE; g_cond_broadcast (&self->buffer_cond); g_mutex_unlock (&self->buffer_lock); } +static GstPadProbeReturn +pad_blocked (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + GstAlphaCombine *self = user_data; + + GST_DEBUG_OBJECT (self, "pad %s:%s blocked", GST_DEBUG_PAD_NAME (pad)); + return GST_PAD_PROBE_OK; +} + +/* Has to be called with buffer_lock held */ static void -gst_alpha_combine_unlock_stop (GstAlphaCombine * self) +gst_alpha_combine_clear_sink_pad_probe (GstAlphaCombine * self) { - g_mutex_lock (&self->buffer_lock); - g_assert (self->flushing); - self->flushing--; + if (!self->pad_block_id) + return; + + g_assert (self->blocked_pad); + gst_pad_remove_probe (self->blocked_pad, self->pad_block_id); + self->pad_block_id = 0; + self->blocked_pad = NULL; +} + +/* Has to be called with buffer_lock held */ +static void +gst_alpha_combine_unlock_reset_flushing_state (GstAlphaCombine * self) +{ + self->flushing = FALSE; + self->flush_stops = 0; /* Reset the format cookies to ensure they are equal */ - if (!self->flushing) { - self->sink_format_cookie = 0; - self->alpha_format_cookie = 0; + self->sink_format_cookie = 0; + self->alpha_format_cookie = 0; +} + +static void +gst_alpha_combine_unlock_stop (GstAlphaCombine * self, GstPad * pad) +{ + g_mutex_lock (&self->buffer_lock); + self->flush_stops++; + + /* Keep flushing until we have received a FLUSH_STOP on every sink pad. */ + if (self->flush_stops >= 1 && pad) { + if (self->flush_stops == 2) { + GST_DEBUG_OBJECT (self, + "Both sink pads received FLUSH_STOP, unblocking them"); + gst_alpha_combine_clear_sink_pad_probe (self); + } else { + GST_DEBUG_OBJECT (pad, "FLUSH_STOP received, blocking"); + g_assert (!self->pad_block_id); + self->pad_block_id = + gst_pad_add_probe (pad, + GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM, + pad_blocked, self, NULL); + self->blocked_pad = pad; + g_mutex_unlock (&self->buffer_lock); + return; + } } + gst_alpha_combine_unlock_reset_flushing_state (self); g_mutex_unlock (&self->buffer_lock); } static void gst_alpha_combine_reset (GstAlphaCombine * self) { + g_mutex_lock (&self->buffer_lock); + gst_alpha_combine_clear_sink_pad_probe (self); gst_buffer_replace (&self->alpha_buffer, NULL); gst_buffer_replace (&self->last_alpha_buffer, NULL); self->last_flow_ret = GST_FLOW_OK; + g_mutex_unlock (&self->buffer_lock); } /* @@ -242,6 +302,11 @@ return GST_FLOW_FLUSHING; } + if (self->alpha_eos) { + g_mutex_unlock (&self->buffer_lock); + return GST_FLOW_EOS; + } + /* Now is a good time to validate the formats, as the alpha_vinfo won't be * updated until we signal this alpha_buffer_as being consumed */ if (!gst_alpha_combine_negotiate (self)) { @@ -492,7 +557,7 @@ gst_alpha_combine_unlock (self); break; case GST_EVENT_FLUSH_STOP: - gst_alpha_combine_unlock_stop (self); + gst_alpha_combine_unlock_stop (self, pad); break; case GST_EVENT_CAPS: { @@ -523,7 +588,7 @@ gst_alpha_combine_unlock (self); break; case GST_EVENT_FLUSH_STOP: - gst_alpha_combine_unlock_stop (self); + gst_alpha_combine_unlock_stop (self, pad); gst_alpha_combine_reset (self); break; case GST_EVENT_CAPS: @@ -538,6 +603,22 @@ gst_alpha_combine_handle_gap (self); break; } + case GST_EVENT_EOS: + { + /* alpha is eos so no point keep waiting for a alpha buffer */ + g_mutex_lock (&self->buffer_lock); + self->alpha_eos = TRUE; + g_cond_broadcast (&self->buffer_cond); + g_mutex_unlock (&self->buffer_lock); + break; + } + case GST_EVENT_STREAM_START: + { + g_mutex_lock (&self->buffer_lock); + self->alpha_eos = FALSE; + g_mutex_unlock (&self->buffer_lock); + break; + } default: break; } @@ -587,7 +668,9 @@ switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: - gst_alpha_combine_unlock_stop (self); + g_mutex_lock (&self->buffer_lock); + gst_alpha_combine_unlock_reset_flushing_state (self); + g_mutex_unlock (&self->buffer_lock); break; case GST_STATE_CHANGE_PAUSED_TO_READY: gst_alpha_combine_unlock (self); @@ -623,6 +706,12 @@ g_clear_object (&self->alpha_pad); g_clear_object (&self->src_pad); + if (G_UNLIKELY (self->blocked_pad)) { + g_assert (self->pad_block_id); + gst_pad_remove_probe (self->blocked_pad, self->pad_block_id); + } + g_clear_object (&self->blocked_pad); + G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -669,7 +758,11 @@ self->sink_pad = gst_element_get_static_pad (GST_ELEMENT (self), "sink"); self->alpha_pad = gst_element_get_static_pad (GST_ELEMENT (self), "alpha"); self->src_pad = gst_element_get_static_pad (GST_ELEMENT (self), "src"); - self->flushing = 1; + self->flushing = FALSE; + self->alpha_eos = FALSE; + self->flush_stops = 0; + self->pad_block_id = 0; + self->blocked_pad = NULL; g_mutex_init (&self->buffer_lock); g_cond_init (&self->buffer_cond);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst/codecalpha/gstalphadecodebin.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst/codecalpha/gstalphadecodebin.c
Changed
@@ -97,8 +97,7 @@ GstPad *src_gpad, *sink_gpad; GstPad *src_pad = NULL, *sink_pad = NULL; GstElement *alphademux = NULL; - GstElement *queue = NULL; - GstElement *alpha_queue = NULL; + GstElement *mq = NULL; GstElement *decoder = NULL; GstElement *alpha_decoder = NULL; GstElement *alphacombine = NULL; @@ -119,10 +118,9 @@ goto cleanup; } - queue = gst_element_factory_make ("queue", NULL); - alpha_queue = gst_element_factory_make ("queue", NULL); - if (!queue || !alpha_queue) { - priv->missing_element = "queue"; + mq = gst_element_factory_make ("multiqueue", NULL); + if (!mq) { + priv->missing_element = "multiqueue"; goto cleanup; } @@ -149,29 +147,27 @@ goto cleanup; } - gst_bin_add_many (GST_BIN (self), alphademux, queue, alpha_queue, decoder, - alpha_decoder, alphacombine, NULL); + gst_bin_add_many (GST_BIN (self), alphademux, mq, + decoder, alpha_decoder, alphacombine, NULL); /* link elements */ sink_pad = gst_element_get_static_pad (alphademux, "sink"); gst_ghost_pad_set_target (GST_GHOST_PAD (sink_gpad), sink_pad); gst_clear_object (&sink_pad); - gst_element_link_pads (alphademux, "src", queue, "sink"); - gst_element_link_pads (queue, "src", decoder, "sink"); + gst_element_link_pads (alphademux, "src", mq, "sink_0"); + gst_element_link_pads (mq, "src_0", decoder, "sink"); gst_element_link_pads (decoder, "src", alphacombine, "sink"); - gst_element_link_pads (alphademux, "alpha", alpha_queue, "sink"); - gst_element_link_pads (alpha_queue, "src", alpha_decoder, "sink"); + gst_element_link_pads (alphademux, "alpha", mq, "sink_1"); + gst_element_link_pads (mq, "src_1", alpha_decoder, "sink"); gst_element_link_pads (alpha_decoder, "src", alphacombine, "alpha"); src_pad = gst_element_get_static_pad (alphacombine, "src"); gst_ghost_pad_set_target (GST_GHOST_PAD (src_gpad), src_pad); gst_object_unref (src_pad); - g_object_set (queue, "max-size-bytes", 0, "max-size-time", - G_GUINT64_CONSTANT (0), "max-size-buffers", 1, NULL); - g_object_set (alpha_queue, "max-size-bytes", 0, "max-size-time", + g_object_set (mq, "max-size-bytes", 0, "max-size-time", G_GUINT64_CONSTANT (0), "max-size-buffers", 1, NULL); /* signal success, we will handle this in NULL->READY transition */ @@ -180,8 +176,7 @@ cleanup: gst_clear_object (&alphademux); - gst_clear_object (&queue); - gst_clear_object (&alpha_queue); + gst_clear_object (&mq); gst_clear_object (&decoder); gst_clear_object (&alpha_decoder); gst_clear_object (&alphacombine);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst/faceoverlay/gstfaceoverlay.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst/faceoverlay/gstfaceoverlay.c
Changed
@@ -95,6 +95,7 @@ "SVG Face Overlay"); ); +static void gst_face_overlay_finalize (GObject * object); static void gst_face_overlay_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_face_overlay_get_property (GObject * object, guint prop_id, @@ -289,6 +290,7 @@ gstbin_class = GST_BIN_CLASS (klass); gstelement_class = GST_ELEMENT_CLASS (klass); + gobject_class->finalize = gst_face_overlay_finalize; gobject_class->set_property = gst_face_overlay_set_property; gobject_class->get_property = gst_face_overlay_get_property; @@ -357,6 +359,16 @@ } static void +gst_face_overlay_finalize (GObject * object) +{ + GstFaceOverlay *filter = GST_FACEOVERLAY (object); + + g_free (filter->location); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void gst_face_overlay_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) {
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst/frei0r/gstfrei0r.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst/frei0r/gstfrei0r.c
Changed
@@ -415,6 +415,7 @@ /* Copies the string */ if (instance) ftable->set_param_value (instance, s, prop->prop_idx); + g_free (property_cacheprop->prop_idx.data.s); property_cacheprop->prop_idx.data.s = s; break; }
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst/librfb/gstrfbsrc.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst/librfb/gstrfbsrc.c
Changed
@@ -287,7 +287,8 @@ break; } case PROP_HOST: - src->host = g_value_dup_string (value);; + g_free (src->host); + src->host = g_value_dup_string (value); break; case PROP_PORT: src->port = g_value_get_int (value);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst/librfb/rfbdecoder.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst/librfb/rfbdecoder.c
Changed
@@ -83,6 +83,7 @@ g_clear_object (&decoder->socket_client); g_clear_object (&decoder->cancellable); g_mutex_clear (&decoder->write_lock); + g_free (decoder->password); g_free (decoder); }
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst/tensordecoders/gstssdobjectdetector.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst/tensordecoders/gstssdobjectdetector.c
Changed
@@ -161,7 +161,7 @@ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); gst_element_class_set_static_metadata (element_class, "objectdetector", - "TensorDecoder/Video", + "Tensordecoder/Video", "Apply tensor output from inference to detect objects in video frames", "Aaron Boxer <aaron.boxer@collabora.com>, Marcus Edel <marcus.edel@collabora.com>"); gst_element_class_add_pad_template (element_class,
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/gst/unixfd/gstunixfdsrc.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/gst/unixfd/gstunixfdsrc.c
Changed
@@ -406,7 +406,8 @@ ctx->n_memory = new_buffer->n_memory; for (int i = 0; i < new_buffer->n_memory; i++) { GstMemory *mem = gst_fd_allocator_alloc (allocator, fds_arri, - new_buffer->memoriesi.size, GST_FD_MEMORY_FLAG_NONE); + new_buffer->memoriesi.size + new_buffer->memoriesi.offset, + GST_FD_MEMORY_FLAG_NONE); gst_memory_resize (mem, new_buffer->memoriesi.offset, new_buffer->memoriesi.size); GST_MINI_OBJECT_FLAG_SET (mem, GST_MEMORY_FLAG_READONLY);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/meson.build -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/meson.build
Changed
@@ -1,5 +1,5 @@ project('gst-plugins-bad', 'c', 'cpp', - version : '1.26.0', + version : '1.26.1', meson_version : '>= 1.4', default_options : 'warning_level=1', 'buildtype=debugoptimized' )
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/po/gst-plugins-bad-1.0.pot -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/po/gst-plugins-bad-1.0.pot
Changed
@@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: gst-plugins-bad-1.26.0\n" +"Project-Id-Version: gst-plugins-bad-1.26.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-03-11 20:15+0000\n" +"POT-Creation-Date: 2025-04-24 20:21+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -17,7 +17,7 @@ "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: ext/curl/gstcurlhttpsrc.c:1441 +#: ext/curl/gstcurlhttpsrc.c:1442 msgid "No URL set." msgstr ""
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/po/gst-plugins-bad.pot -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/po/gst-plugins-bad.pot
Changed
@@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: gst-plugins-bad-1.26.0\n" +"Project-Id-Version: gst-plugins-bad-1.26.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-03-11 20:15+0000\n" +"POT-Creation-Date: 2025-04-24 20:21+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -17,7 +17,7 @@ "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: ext/curl/gstcurlhttpsrc.c:1441 +#: ext/curl/gstcurlhttpsrc.c:1442 msgid "No URL set." msgstr ""
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/aja/gstajasink.cpp -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/aja/gstajasink.cpp
Changed
@@ -453,6 +453,7 @@ g_assert(self->device == NULL); g_assert(gst_vec_deque_get_length(self->queue) == 0); g_clear_pointer(&self->queue, gst_vec_deque_free); + g_free(self->device_identifier); g_mutex_clear(&self->queue_lock); g_cond_clear(&self->queue_cond);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/aja/gstajasrc.cpp -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/aja/gstajasrc.cpp
Changed
@@ -582,6 +582,7 @@ g_assert(self->device == NULL); g_assert(gst_vec_deque_get_length(self->queue) == 0); g_clear_pointer(&self->queue, gst_vec_deque_free); + g_free(self->device_identifier); gst_clear_object(&self->clock);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/aja/plugin.cpp -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/aja/plugin.cpp
Changed
@@ -22,9 +22,8 @@ * * Plugin for AJA(https://www.aja.com) capture and output cards. * - * This plugin requires the AJA NTV2 SDK version 16 or newer and works with - * both the Open Source(https://github.com/aja-video/ntv2.git) and - * proprietary(https://www.aja.com/family/developer) version. + * This plugin requires the AJA NTV2 SDK version 17 or newer and works with + * The AJA SDK can be found here(https://github.com/aja-video/libajantv2). * * Since: 1.24 *
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/applemedia/avfvideosrc.m -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/applemedia/avfvideosrc.m
Changed
@@ -53,6 +53,9 @@ static CMVideoDimensions get_oriented_dimensions(GstAVFVideoSourceOrientation orientation, CMVideoDimensions dimensions); +static CMTime +find_range_bound_close_enough_to_fps (AVFrameRateRange *range, int fps_n, int fps_d); + static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, @@ -662,8 +665,11 @@ device.activeFormat = fmt; for (AVFrameRateRange *range in fmt.videoSupportedFrameRateRanges) { CMTime dur = CMTimeMake (info->fps_d, info->fps_n); - if (CMTIME_COMPARE_INLINE (range.minFrameDuration, <=, dur) && - CMTIME_COMPARE_INLINE (range.maxFrameDuration, >=, dur)) { + // Either the value is directly supported, or we rounded it to the nearest 'sane' value in get_caps(), + // in which case AVF might refuse to accept it, so we try to use one of the range bounds if it's close enough. + if ((CMTIME_COMPARE_INLINE (range.minFrameDuration, <=, dur) && + CMTIME_COMPARE_INLINE (range.maxFrameDuration, >=, dur)) || + CMTIME_IS_VALID (dur = find_range_bound_close_enough_to_fps (range, info->fps_n, info->fps_d))) { device.activeVideoMinFrameDuration = dur; device.activeVideoMaxFrameDuration = dur; found_framerate = TRUE; @@ -1581,16 +1587,20 @@ for (AVFrameRateRange *range in format.videoSupportedFrameRateRanges) { int min_fps_n, min_fps_d, max_fps_n, max_fps_d; + GstClockTime min_dur, max_dur; + + // For some third-party devices macOS sometimes reports silly framerates, like 750003/6250 instead of 120/1. + // Let's round all values here just in case, and then reverse that in setDeviceCaps when passing values to AVF. + // Note: In the past, min/maxFrameRate were used instead, but that also came with its own set of rounding issues. + min_dur = gst_util_uint64_scale (GST_SECOND, range.minFrameDuration.value, range.minFrameDuration.timescale); + max_dur = gst_util_uint64_scale (GST_SECOND, range.maxFrameDuration.value, range.maxFrameDuration.timescale); - /* CMTime duration is the inverse of fps*/ - min_fps_n = range.maxFrameDuration.timescale; - min_fps_d = range.maxFrameDuration.value; - max_fps_n = range.minFrameDuration.timescale; - max_fps_d = range.minFrameDuration.value; + gst_video_guess_framerate (min_dur, &max_fps_n, &max_fps_d); + gst_video_guess_framerate (max_dur, &min_fps_n, &min_fps_d); - GST_DEBUG ("dimensions %ix%i fps range is %i/%i, %i/%i", - dimensions.width, dimensions.height, min_fps_n, min_fps_d, max_fps_n, - max_fps_d); + GST_DEBUG ("dimensions %ix%i, duration range %s, assuming fps range %d/%d - %d/%d", + dimensions.width, dimensions.height, range description.UTF8String, + min_fps_n, min_fps_d, max_fps_n, max_fps_d); for (NSNumber *pixel_format in output.availableVideoCVPixelFormatTypes) { GstCaps *caps; @@ -1659,3 +1669,26 @@ } return orientedDimensions; } + +static CMTime +find_range_bound_close_enough_to_fps (AVFrameRateRange *range, int fps_n, int fps_d) +{ + GstClockTime min_dur, max_dur; + gint guessed_n, guessed_d; + + min_dur = gst_util_uint64_scale (GST_SECOND, range.minFrameDuration.value, range.minFrameDuration.timescale); + gst_video_guess_framerate (min_dur, &guessed_n, &guessed_d); + if (guessed_n == fps_n && guessed_d == fps_d) { + GST_DEBUG ("Using min duration from range %s for fps %d/%d", range description.UTF8String, fps_n, fps_d); + return range.minFrameDuration; + } + + max_dur = gst_util_uint64_scale (GST_SECOND, range.maxFrameDuration.value, range.maxFrameDuration.timescale); + gst_video_guess_framerate (max_dur, &guessed_n, &guessed_d); + if (guessed_n == fps_n && guessed_d == fps_d) { + GST_DEBUG ("Using max duration from range %s for fps %d/%d", range description.UTF8String, fps_n, fps_d); + return range.maxFrameDuration; + } + + return kCMTimeInvalid; +}
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/applemedia/vtenc.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/applemedia/vtenc.c
Changed
@@ -242,7 +242,7 @@ static void gst_vtenc_session_configure_max_frame_delay (GstVTEnc * self, VTCompressionSessionRef session, int delay); static void gst_vtenc_session_configure_bitrate (GstVTEnc * self, - VTCompressionSessionRef session, guint bitrate); + VTCompressionSessionRef session); static OSStatus gst_vtenc_session_configure_property_int (GstVTEnc * self, VTCompressionSessionRef session, CFStringRef name, gint value); static OSStatus gst_vtenc_session_configure_property_double (GstVTEnc * self, @@ -626,90 +626,6 @@ } static void -gst_vtenc_set_bitrate (GstVTEnc * self, guint bitrate) -{ - GST_OBJECT_LOCK (self); - - self->bitrate = bitrate; - - if (self->session != NULL) - gst_vtenc_session_configure_bitrate (self, self->session, bitrate); - - GST_OBJECT_UNLOCK (self); -} - -static void -gst_vtenc_set_allow_frame_reordering (GstVTEnc * self, - gboolean allow_frame_reordering) -{ - GST_OBJECT_LOCK (self); - self->allow_frame_reordering = allow_frame_reordering; - if (self->session != NULL) { - gst_vtenc_session_configure_allow_frame_reordering (self, - self->session, allow_frame_reordering); - } - GST_OBJECT_UNLOCK (self); -} - -static void -gst_vtenc_set_realtime (GstVTEnc * self, gboolean realtime) -{ - GST_OBJECT_LOCK (self); - self->realtime = realtime; - if (self->session != NULL) - gst_vtenc_session_configure_realtime (self, self->session, realtime); - GST_OBJECT_UNLOCK (self); -} - -static void -gst_vtenc_set_quality (GstVTEnc * self, gdouble quality) -{ - GST_OBJECT_LOCK (self); - self->quality = quality; - if (self->session != NULL) { - GST_INFO_OBJECT (self, "setting quality %f", quality); - gst_vtenc_session_configure_property_double (self, self->session, - kVTCompressionPropertyKey_Quality, quality); - } - GST_OBJECT_UNLOCK (self); -} - -static void -gst_vtenc_set_max_keyframe_interval (GstVTEnc * self, gint interval) -{ - GST_OBJECT_LOCK (self); - self->max_keyframe_interval = interval; - if (self->session != NULL) { - gst_vtenc_session_configure_max_keyframe_interval (self, self->session, - interval); - } - GST_OBJECT_UNLOCK (self); -} - -static void -gst_vtenc_set_max_keyframe_interval_duration (GstVTEnc * self, - GstClockTime interval) -{ - GST_OBJECT_LOCK (self); - self->max_keyframe_interval_duration = interval; - if (self->session != NULL) { - gst_vtenc_session_configure_max_keyframe_interval_duration (self, - self->session, interval / ((gdouble) GST_SECOND)); - } - GST_OBJECT_UNLOCK (self); -} - -static void -gst_vtenc_set_max_frame_delay (GstVTEnc * self, int delay) -{ - GST_OBJECT_LOCK (self); - self->max_frame_delay = delay; - if (self->session != NULL) - gst_vtenc_session_configure_max_frame_delay (self, self->session, delay); - GST_OBJECT_UNLOCK (self); -} - -static void gst_vtenc_get_property (GObject * obj, guint prop_id, GValue * value, GParamSpec * pspec) { @@ -756,33 +672,48 @@ } static void +gst_vtenc_flag_reconfigure (GstVTEnc * self) +{ + if (self->session != NULL) + g_atomic_int_set (&self->require_reconfigure, TRUE); +} + +static void gst_vtenc_set_property (GObject * obj, guint prop_id, const GValue * value, GParamSpec * pspec) { GstVTEnc *self = GST_VTENC_CAST (obj); + GST_OBJECT_LOCK (self); + switch (prop_id) { case PROP_BITRATE: - gst_vtenc_set_bitrate (self, g_value_get_uint (value) * 1000); + self->bitrate = g_value_get_uint (value) * 1000; + gst_vtenc_flag_reconfigure (self); break; case PROP_ALLOW_FRAME_REORDERING: - gst_vtenc_set_allow_frame_reordering (self, g_value_get_boolean (value)); + self->allow_frame_reordering = g_value_get_boolean (value); + gst_vtenc_flag_reconfigure (self); break; case PROP_REALTIME: - gst_vtenc_set_realtime (self, g_value_get_boolean (value)); + self->realtime = g_value_get_boolean (value); + gst_vtenc_flag_reconfigure (self); break; case PROP_QUALITY: - gst_vtenc_set_quality (self, g_value_get_double (value)); + self->quality = g_value_get_double (value); + gst_vtenc_flag_reconfigure (self); break; case PROP_MAX_KEYFRAME_INTERVAL: - gst_vtenc_set_max_keyframe_interval (self, g_value_get_int (value)); + self->max_keyframe_interval = g_value_get_int (value); + gst_vtenc_flag_reconfigure (self); break; case PROP_MAX_KEYFRAME_INTERVAL_DURATION: - gst_vtenc_set_max_keyframe_interval_duration (self, - g_value_get_uint64 (value)); + self->max_keyframe_interval_duration = g_value_get_uint64 (value); + gst_vtenc_flag_reconfigure (self); break; case PROP_RATE_CONTROL: self->rate_control = g_value_get_enum (value); + gst_vtenc_flag_reconfigure (self); break; case PROP_DATA_RATE_LIMITS: { @@ -790,17 +721,17 @@ float window; const char *s = g_value_get_string (value); if (s && sscanf (s, "%u,%f", &max_bitrate, &window) == 2) { - GST_OBJECT_LOCK (self); self->max_bitrate = max_bitrate * 1000; self->bitrate_window = window; - GST_OBJECT_UNLOCK (self); + gst_vtenc_flag_reconfigure (self); } else { g_warning ("Failed to parse data rate limits: '%s'", s); } } break; case PROP_MAX_FRAME_DELAY: - gst_vtenc_set_max_frame_delay (self, g_value_get_int (value)); + self->max_frame_delay = g_value_get_int (value); + gst_vtenc_flag_reconfigure (self); break; case PROP_PRESERVE_ALPHA: self->preserve_alpha = g_value_get_boolean (value); @@ -809,6 +740,8 @@ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); break; } + + GST_OBJECT_UNLOCK (self); } static gboolean @@ -913,6 +846,7 @@ self->is_flushing = FALSE; self->downstream_ret = GST_FLOW_OK; g_atomic_int_set (&self->require_restart, FALSE); + g_atomic_int_set (&self->require_reconfigure, FALSE); self->output_queue = gst_vec_deque_new (VTENC_OUTPUT_QUEUE_SIZE); /* Set clear_func to unref all remaining frames in gst_vec_deque_free() */ @@ -1166,6 +1100,9 @@ self->session = session; GST_OBJECT_UNLOCK (self); + g_atomic_int_set (&self->require_restart, FALSE); + g_atomic_int_set (&self->require_reconfigure, FALSE); + return session != NULL; } @@ -1612,7 +1549,7 @@ gst_vtenc_session_configure_max_frame_delay (self, session, self->max_frame_delay); - gst_vtenc_session_configure_bitrate (self, session, self->bitrate); + gst_vtenc_session_configure_bitrate (self, session); } /* Force encoder to not preserve alpha with 4444(XQ) ProRes formats if @@ -1803,11 +1740,12 @@ static void gst_vtenc_session_configure_bitrate (GstVTEnc * self, - VTCompressionSessionRef session, guint bitrate) + VTCompressionSessionRef session) { gboolean emulate_cbr = FALSE; double bitrate_window = self->bitrate_window; guint max_bitrate = self->max_bitrate; + guint bitrate = self->bitrate; CFStringRef key = kVTCompressionPropertyKey_AverageBitRate; if (self->rate_control == GST_VTENC_RATE_CONTROL_CBR) { @@ -1986,28 +1924,42 @@ || status == kVTVideoEncoderNotAvailableNowErr; } -static void -gst_vtenc_restart_session (GstVTEnc * self) +static gboolean +gst_vtenc_push_all_pending_frames (GstVTEnc * self) { OSStatus status; - VTCompressionSessionRef session; + gboolean ret = TRUE; - /* We need to push out all frames still inside the encoder, - * otherwise destroy_session() will wait for all callbacks to fire - * and very likely deadlock due to the object lock being taken */ GST_VIDEO_ENCODER_STREAM_UNLOCK (self); + GST_DEBUG_OBJECT (self, "starting VTCompressionSessionCompleteFrames"); status = VTCompressionSessionCompleteFrames (self->session, kCMTimePositiveInfinity); + GST_DEBUG_OBJECT (self, "VTCompressionSessionCompleteFrames ended"); + if (status != noErr) { GST_WARNING_OBJECT (self, - "Error when emptying encoder before restart: %d, will retry on next frame encode", - (int) status); - GST_VIDEO_ENCODER_STREAM_LOCK (self); - return; - } else { - GST_DEBUG_OBJECT (self, "All frames out, restarting encoder session"); + "VTCompressionSessionCompleteFrames returned %d", (int) status); + ret = FALSE; } + GST_VIDEO_ENCODER_STREAM_LOCK (self); + return ret; +} + +static void +gst_vtenc_restart_session (GstVTEnc * self) +{ + VTCompressionSessionRef session; + + /* We need to push out all frames still inside the encoder, + * otherwise destroy_session() will wait for all callbacks to fire + * and very likely deadlock due to the object lock being taken */ + if (!gst_vtenc_push_all_pending_frames (self)) { + GST_DEBUG_OBJECT (self, "Will retry session restart on next frame encode"); + return; + } + + GST_DEBUG_OBJECT (self, "All frames out, restarting encoder session"); GST_OBJECT_LOCK (self); gst_vtenc_destroy_session (self, &self->session); @@ -2019,9 +1971,40 @@ self->session = session; GST_OBJECT_UNLOCK (self); + g_atomic_int_set (&self->require_reconfigure, FALSE); g_atomic_int_set (&self->require_restart, FALSE); } +static void +gst_vtenc_reconfigure_session (GstVTEnc * self) +{ + if (!gst_vtenc_push_all_pending_frames (self)) { + GST_DEBUG_OBJECT (self, + "Will retry session reconfigure on next frame encode"); + return; + } + + GST_DEBUG_OBJECT (self, "All frames out, reconfiguring encoder session"); + + GST_OBJECT_LOCK (self); + gst_vtenc_session_configure_bitrate (self, self->session); + gst_vtenc_session_configure_allow_frame_reordering (self, self->session, + self->allow_frame_reordering); + gst_vtenc_session_configure_realtime (self, self->session, self->realtime); + gst_vtenc_session_configure_property_double (self, self->session, + kVTCompressionPropertyKey_Quality, self->quality); + gst_vtenc_session_configure_max_keyframe_interval (self, self->session, + self->max_keyframe_interval); + gst_vtenc_session_configure_max_keyframe_interval_duration (self, + self->session, + self->max_keyframe_interval_duration / ((gdouble) GST_SECOND)); + gst_vtenc_session_configure_max_frame_delay (self, self->session, + self->max_frame_delay); + GST_OBJECT_UNLOCK (self); + + g_atomic_int_set (&self->require_reconfigure, FALSE); +} + static GstFlowReturn gst_vtenc_encode_frame (GstVTEnc * self, GstVideoCodecFrame * frame) { @@ -2076,6 +2059,8 @@ * and recreates the encoding session. */ if (g_atomic_int_get (&self->require_restart)) gst_vtenc_restart_session (self); + else if (g_atomic_int_get (&self->require_reconfigure)) + gst_vtenc_reconfigure_session (self); if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (frame)) { GST_INFO_OBJECT (self, "received force-keyframe-event, will force intra");
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/applemedia/vtenc.h -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/applemedia/vtenc.h
Changed
@@ -122,6 +122,11 @@ /* If we get an EncoderMalfunctionErr or similar, we restart the session * before the next encode call */ gboolean require_restart; + + /* Certain properties (e.g. bitrate) can be changed on the fly. + * We can't do it straight from the setter as that would often deadlock, + * so we instead reconfigure on next encode call. */ + gboolean require_reconfigure; }; GType gst_vtenc_get_type (void);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/bluez/gsta2dpsink.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/bluez/gsta2dpsink.c
Changed
@@ -121,6 +121,17 @@ } static void +gst_a2dp_sink_finalize (GObject * object) +{ + GstA2dpSink *self = GST_A2DP_SINK (object); + + g_free (self->device); + g_free (self->transport); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void gst_a2dp_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { @@ -281,6 +292,7 @@ parent_class = g_type_class_peek_parent (klass); + object_class->finalize = GST_DEBUG_FUNCPTR (gst_a2dp_sink_finalize); object_class->set_property = GST_DEBUG_FUNCPTR (gst_a2dp_sink_set_property); object_class->get_property = GST_DEBUG_FUNCPTR (gst_a2dp_sink_get_property);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/directshow/dshowdeviceprovider.cpp -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/directshow/dshowdeviceprovider.cpp
Changed
@@ -272,9 +272,11 @@ switch (prop_id) { case PROP_DEVICE: + /* G_PARAM_CONSTRUCT_ONLY */ g_value_set_string (value, device->device); break; case PROP_DEVICE_NAME: + /* G_PARAM_CONSTRUCT_ONLY */ g_value_set_string (value, device->device_name); break; case PROP_DEVICE_INDEX:
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/directsound/gstdirectsounddevice.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/directsound/gstdirectsounddevice.c
Changed
@@ -257,6 +257,7 @@ switch (prop_id) { case PROP_DEVICE_GUID: + /* G_PARAM_CONSTRUCT_ONLY */ device->guid = g_value_dup_string (value); break; default:
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/mediafoundation/gstmfdevice.cpp -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/mediafoundation/gstmfdevice.cpp
Changed
@@ -130,6 +130,7 @@ switch (prop_id) { case PROP_DEVICE_PATH: + /* G_PARAM_CONSTRUCT_ONLY */ g_value_set_string (value, self->device_path); break; default:
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/qsv/gstqsvdecoder.cpp -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/qsv/gstqsvdecoder.cpp
Changed
@@ -169,6 +169,13 @@ "DXGI Adapter LUID (Locally Unique Identifier) of created device", G_MININT64, G_MAXINT64, 0, param_flags)); #else + /** + * GstQsvDecoder:device-path: + * + * DRM device path + * + * Since: 1.22 + */ g_object_class_install_property (object_class, PROP_DEVICE_PATH, g_param_spec_string ("device-path", "Device Path", "DRM device path", nullptr, param_flags));
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/qsv/gstqsvencoder.cpp -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/qsv/gstqsvencoder.cpp
Changed
@@ -219,6 +219,13 @@ "DXGI Adapter LUID (Locally Unique Identifier) of created device", G_MININT64, G_MAXINT64, 0, param_flags)); #else + /** + * GstQsvEncoder:device-path: + * + * DRM device path + * + * Since: 1.22 + */ g_object_class_install_property (object_class, PROP_DEVICE_PATH, g_param_spec_string ("device-path", "Device Path", "DRM device path", nullptr, param_flags));
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/uvcgadget/gstuvcsink.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/uvcgadget/gstuvcsink.c
Changed
@@ -640,6 +640,8 @@ gst_pad_set_query_function (self->sinkpad, gst_uvc_sink_query); gst_pad_set_event_function (self->sinkpad, gst_uvc_sink_event); + self->request_error_code = REQUEST_ERROR_CODE_NO_ERROR; + self->cur_caps = gst_caps_new_empty (); } @@ -985,6 +987,7 @@ case GST_STATE_CHANGE_PAUSED_TO_READY: gst_element_sync_state_with_parent (GST_ELEMENT (self->fakesink)); gst_uvc_sink_remove_idle_probe (self); + self->request_error_code = REQUEST_ERROR_CODE_NO_ERROR; break; case GST_STATE_CHANGE_READY_TO_NULL: if (!gst_uvc_sink_unwatch (self))
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/uvcgadget/gstuvcsink.h -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/uvcgadget/gstuvcsink.h
Changed
@@ -17,6 +17,9 @@ G_BEGIN_DECLS GST_DEBUG_CATEGORY_EXTERN (uvcsink_debug); +#define REQUEST_ERROR_CODE_NO_ERROR 0x0 +#define REQUEST_ERROR_CODE_INVALID_REQUEST 0x6 + #define GST_TYPE_UVCSINK (gst_uvc_sink_get_type()) G_DECLARE_FINAL_TYPE (GstUvcSink, gst_uvc_sink, GST, UVCSINK, GstBin) @@ -54,6 +57,8 @@ int control; + int request_error_code; + /* probes */ int buffer_peer_probe_id; int idle_probe_id;
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/uvcgadget/uvc.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/uvcgadget/uvc.c
Changed
@@ -343,7 +343,7 @@ return 0; } -static void +static int uvc_events_parse_control (GstUvcSink * self, uint8_t req, uint8_t cs, uint8_t entity_id, uint8_t len, struct uvc_request_data *resp) { @@ -357,26 +357,50 @@ case 0: GST_DEBUG_OBJECT (self, "%s", uvc_video_control_interface_control_selector_name (cs)); - break; + /* + * For ERROR_CODE_CONTROL requests we have to return not implemented so + * bail out gracefully here to properly send control is not + * currently implemented. (0x06) (4.2.1.2 Request Error Code Control) + */ + if (cs == UVC_VC_REQUEST_ERROR_CODE_CONTROL) { + resp->data0 = self->request_error_code; + resp->length = 1; + + break; + } + goto error; case 1: GST_DEBUG_OBJECT (self, "%s: %s", uvc_camera_terminal_control_selector_name (cs), uvc_request_name (req)); - break; + goto error; case 2: GST_DEBUG_OBJECT (self, "%s: %s", uvc_processing_unit_control_selector_name (cs), uvc_request_name (req)); - break; + goto error; default: GST_DEBUG_OBJECT (self, "Unknown entity ID (0x%02x), CS: 0x%02x, Request %s (0x%02x)", entity_id, cs, uvc_request_name (req), req); - break; + goto error; } + + self->request_error_code = REQUEST_ERROR_CODE_NO_ERROR; + + return 0; + +error: + + self->request_error_code = REQUEST_ERROR_CODE_INVALID_REQUEST; + /* + * Stall and don't response the control requests that are + * actually not implemented + */ + return -EOPNOTSUPP; } static int @@ -389,9 +413,8 @@ return -EINVAL; if (interface == UVC_STRING_CONTROL_IDX) { - uvc_events_parse_control (self, ctrl->bRequest, ctrl->wValue >> 8, - ctrl->wIndex >> 8, ctrl->wLength, resp); - return -EOPNOTSUPP; + return uvc_events_parse_control (self, ctrl->bRequest, + ctrl->wValue >> 8, ctrl->wIndex >> 8, ctrl->wLength, resp); } else if (interface == UVC_STRING_STREAMING_IDX) { return uvc_events_process_streaming (self, ctrl->bRequest, le16toh (ctrl->wValue) >> 8, resp);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/uvch264/gstuvch264deviceprovider.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/uvch264/gstuvch264deviceprovider.c
Changed
@@ -94,6 +94,7 @@ switch (prop_id) { case PROP_DEVICE_PATH: + /* G_PARAM_CONSTRUCT_ONLY */ self->device_path = g_value_dup_string (value); break; default:
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/v4l2codecs/gstv4l2codecalphadecodebin.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/v4l2codecs/gstv4l2codecalphadecodebin.c
Changed
@@ -119,8 +119,7 @@ GstPad *src_gpad, *sink_gpad; GstPad *src_pad = NULL, *sink_pad = NULL; GstElement *alphademux = NULL; - GstElement *queue = NULL; - GstElement *alpha_queue = NULL; + GstElement *mq = NULL; GstElement *decoder = NULL; GstElement *alpha_decoder = NULL; GstElement *alphacombine = NULL; @@ -141,10 +140,9 @@ goto cleanup; } - queue = gst_element_factory_make ("queue", NULL); - alpha_queue = gst_element_factory_make ("queue", NULL); - if (!queue || !alpha_queue) { - priv->missing_element = "queue"; + mq = gst_element_factory_make ("multiqueue", NULL); + if (!mq) { + priv->missing_element = "multiqueue"; goto cleanup; } @@ -171,7 +169,7 @@ goto cleanup; } - gst_bin_add_many (GST_BIN (self), alphademux, queue, alpha_queue, decoder, + gst_bin_add_many (GST_BIN (self), alphademux, mq, decoder, alpha_decoder, alphacombine, NULL); /* link elements */ @@ -179,21 +177,19 @@ gst_ghost_pad_set_target (GST_GHOST_PAD (sink_gpad), sink_pad); gst_clear_object (&sink_pad); - gst_element_link_pads (alphademux, "src", queue, "sink"); - gst_element_link_pads (queue, "src", decoder, "sink"); + gst_element_link_pads (alphademux, "src", mq, "sink_0"); + gst_element_link_pads (mq, "src_0", decoder, "sink"); gst_element_link_pads (decoder, "src", alphacombine, "sink"); - gst_element_link_pads (alphademux, "alpha", alpha_queue, "sink"); - gst_element_link_pads (alpha_queue, "src", alpha_decoder, "sink"); + gst_element_link_pads (alphademux, "alpha", mq, "sink_1"); + gst_element_link_pads (mq, "src_1", alpha_decoder, "sink"); gst_element_link_pads (alpha_decoder, "src", alphacombine, "alpha"); src_pad = gst_element_get_static_pad (alphacombine, "src"); gst_ghost_pad_set_target (GST_GHOST_PAD (src_gpad), src_pad); gst_object_unref (src_pad); - g_object_set (queue, "max-size-bytes", 0, "max-size-time", - G_GUINT64_CONSTANT (0), "max-size-buffers", 1, NULL); - g_object_set (alpha_queue, "max-size-bytes", 0, "max-size-time", + g_object_set (mq, "max-size-bytes", 0, "max-size-time", G_GUINT64_CONSTANT (0), "max-size-buffers", 1, NULL); /* signal success, we will handle this in NULL->READY transition */ @@ -202,8 +198,7 @@ cleanup: gst_clear_object (&alphademux); - gst_clear_object (&queue); - gst_clear_object (&alpha_queue); + gst_clear_object (&mq); gst_clear_object (&decoder); gst_clear_object (&alpha_decoder); gst_clear_object (&alphacombine);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/v4l2codecs/gstv4l2codecav1dec.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/v4l2codecs/gstv4l2codecav1dec.c
Changed
@@ -1298,6 +1298,7 @@ GstV4l2CodecAV1Dec *self = GST_V4L2_CODEC_AV1_DEC (decoder); GstVideoCodecFrame *frame; GstV4l2Request *request; + GstBuffer *buffer; GstFlowReturn flow_ret; guint count = 1; gsize bytesused; @@ -1358,12 +1359,8 @@ self->bitstream_map = (GstMapInfo) GST_MAP_INFO_INIT; gst_memory_resize (self->bitstream, 0, bytesused); - frame = gst_video_decoder_get_frame (GST_VIDEO_DECODER (self), - GST_CODEC_PICTURE_FRAME_NUMBER (picture)); - g_return_val_if_fail (frame, FALSE); - flow_ret = gst_buffer_pool_acquire_buffer (GST_BUFFER_POOL (self->src_pool), - &frame->output_buffer, NULL); + &buffer, NULL); if (flow_ret != GST_FLOW_OK) { if (flow_ret == GST_FLOW_FLUSHING) GST_DEBUG_OBJECT (self, "Frame decoding aborted, we are flushing."); @@ -1373,12 +1370,17 @@ goto fail; } - request = gst_v4l2_decoder_alloc_request (self->decoder, - GST_CODEC_PICTURE_FRAME_NUMBER (picture), self->bitstream, - frame->output_buffer); + frame = gst_video_decoder_get_frame (GST_VIDEO_DECODER (self), + GST_CODEC_PICTURE_FRAME_NUMBER (picture)); + g_return_val_if_fail (frame, FALSE); + g_warn_if_fail (frame->output_buffer == NULL); + frame->output_buffer = buffer; gst_video_codec_frame_unref (frame); + request = gst_v4l2_decoder_alloc_request (self->decoder, + GST_CODEC_PICTURE_FRAME_NUMBER (picture), self->bitstream, buffer); + if (!request) { GST_ELEMENT_ERROR (self, RESOURCE, NO_SPACE_LEFT, ("Failed to allocate a media request object."), (NULL));
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/v4l2codecs/gstv4l2codech264dec.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/v4l2codecs/gstv4l2codech264dec.c
Changed
@@ -1241,8 +1241,10 @@ system_frame_number); g_return_val_if_fail (frame, FALSE); - if (!gst_v4l2_codec_h264_dec_ensure_output_buffer (self, frame)) + if (!gst_v4l2_codec_h264_dec_ensure_output_buffer (self, frame)) { + gst_video_codec_frame_unref (frame); goto done; + } request = gst_v4l2_decoder_alloc_request (self->decoder, system_frame_number, self->bitstream, frame->output_buffer);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/v4l2codecs/gstv4l2codech265dec.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/v4l2codecs/gstv4l2codech265dec.c
Changed
@@ -1392,8 +1392,10 @@ system_frame_number); g_return_val_if_fail (frame, FALSE); - if (!gst_v4l2_codec_h265_dec_ensure_output_buffer (self, frame)) + if (!gst_v4l2_codec_h265_dec_ensure_output_buffer (self, frame)) { + gst_video_codec_frame_unref (frame); goto done; + } request = gst_v4l2_decoder_alloc_request (self->decoder, system_frame_number, self->bitstream, frame->output_buffer);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/v4l2codecs/gstv4l2codecmpeg2dec.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/v4l2codecs/gstv4l2codecmpeg2dec.c
Changed
@@ -874,8 +874,10 @@ system_frame_number); g_return_val_if_fail (frame, FALSE); - if (!gst_v4l2_codec_mpeg2_dec_ensure_output_buffer (self, frame)) + if (!gst_v4l2_codec_mpeg2_dec_ensure_output_buffer (self, frame)) { + gst_video_codec_frame_unref (frame); goto done; + } request = gst_v4l2_decoder_alloc_request (self->decoder, system_frame_number, self->bitstream, frame->output_buffer);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/v4l2codecs/gstv4l2codecvp9dec.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/v4l2codecs/gstv4l2codecvp9dec.c
Changed
@@ -877,6 +877,7 @@ GstV4l2CodecVp9Dec *self = GST_V4L2_CODEC_VP9_DEC (decoder); GstVideoCodecFrame *frame; GstV4l2Request *request = NULL; + GstBuffer *buffer; GstFlowReturn flow_ret; gsize bytesused; guint num_controls = 1; @@ -907,12 +908,8 @@ self->bitstream_map = (GstMapInfo) GST_MAP_INFO_INIT; gst_memory_resize (self->bitstream, 0, bytesused); - frame = gst_video_decoder_get_frame (GST_VIDEO_DECODER (self), - GST_CODEC_PICTURE_FRAME_NUMBER (picture)); - g_return_val_if_fail (frame, FALSE); - flow_ret = gst_buffer_pool_acquire_buffer (GST_BUFFER_POOL (self->src_pool), - &frame->output_buffer, NULL); + &buffer, NULL); if (flow_ret != GST_FLOW_OK) { if (flow_ret == GST_FLOW_FLUSHING) GST_DEBUG_OBJECT (self, "Frame decoding aborted, we are flushing."); @@ -922,12 +919,16 @@ goto fail; } - request = gst_v4l2_decoder_alloc_request (self->decoder, - GST_CODEC_PICTURE_FRAME_NUMBER (picture), self->bitstream, - frame->output_buffer); - + frame = gst_video_decoder_get_frame (GST_VIDEO_DECODER (self), + GST_CODEC_PICTURE_FRAME_NUMBER (picture)); + g_return_val_if_fail (frame, FALSE); + g_warn_if_fail (frame->output_buffer == NULL); + frame->output_buffer = buffer; gst_video_codec_frame_unref (frame); + request = gst_v4l2_decoder_alloc_request (self->decoder, + GST_CODEC_PICTURE_FRAME_NUMBER (picture), self->bitstream, buffer); + if (!request) { GST_ELEMENT_ERROR (decoder, RESOURCE, NO_SPACE_LEFT, ("Failed to allocate a media request object."), (NULL));
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/va/gstvaav1enc.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/va/gstvaav1enc.c
Changed
@@ -1948,6 +1948,7 @@ } } } + gst_caps_unref (allowed_caps); if (candidates->len == 0) { GST_ERROR_OBJECT (self, "No available profile in caps"); @@ -1993,7 +1994,7 @@ if (ret_profile != VAProfileNone) GST_INFO_OBJECT (self, "Decide the profile: %s", gst_va_profile_name (ret_profile)); - + g_array_unref (candidates); return ret_profile; } @@ -4632,16 +4633,6 @@ } g_object_class_install_properties (object_class, n_props, properties); - - /** - * GstVaFeature: - * @GST_VA_FEATURE_DISABLED: The feature is disabled. - * @GST_VA_FEATURE_ENABLED: The feature is enabled. - * @GST_VA_FEATURE_AUTO: The feature is enabled automatically. - * - * Since: 1.22 - */ - gst_type_mark_as_plugin_api (GST_TYPE_VA_FEATURE, 0); } static GstCaps *
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/va/gstvacaps.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/va/gstvacaps.c
Changed
@@ -351,6 +351,10 @@ if (formats->len == 0) goto bail; + /* if driver reports maximum width or height lower than minimum then skip */ + if (max_width < min_width || max_height < min_height) + goto bail; + if (!fix_raw_formats (display, profile, entrypoint, formats)) goto bail;
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/va/gstvacodecalphadecodebin.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/va/gstvacodecalphadecodebin.c
Changed
@@ -102,8 +102,7 @@ GstPad *src_gpad, *sink_gpad; GstPad *src_pad = NULL, *sink_pad = NULL; GstElement *alphademux = NULL; - GstElement *queue = NULL; - GstElement *alpha_queue = NULL; + GstElement *mq = NULL; GstElement *decoder = NULL; GstElement *alpha_decoder = NULL; GstElement *alphacombine = NULL; @@ -124,10 +123,9 @@ goto cleanup; } - queue = gst_element_factory_make ("queue", NULL); - alpha_queue = gst_element_factory_make ("queue", NULL); - if (!queue || !alpha_queue) { - priv->missing_element = "queue"; + mq = gst_element_factory_make ("multiqueue", NULL); + if (!mq) { + priv->missing_element = "multiqueue"; goto cleanup; } @@ -154,29 +152,27 @@ goto cleanup; } - gst_bin_add_many (GST_BIN (self), alphademux, queue, alpha_queue, decoder, - alpha_decoder, alphacombine, NULL); + gst_bin_add_many (GST_BIN (self), alphademux, mq, + decoder, alpha_decoder, alphacombine, NULL); /* link elements */ sink_pad = gst_element_get_static_pad (alphademux, "sink"); gst_ghost_pad_set_target (GST_GHOST_PAD (sink_gpad), sink_pad); gst_clear_object (&sink_pad); - gst_element_link_pads (alphademux, "src", queue, "sink"); - gst_element_link_pads (queue, "src", decoder, "sink"); + gst_element_link_pads (alphademux, "src", mq, "sink_0"); + gst_element_link_pads (mq, "src_0", decoder, "sink"); gst_element_link_pads (decoder, "src", alphacombine, "sink"); - gst_element_link_pads (alphademux, "alpha", alpha_queue, "sink"); - gst_element_link_pads (alpha_queue, "src", alpha_decoder, "sink"); + gst_element_link_pads (alphademux, "alpha", mq, "sink_1"); + gst_element_link_pads (mq, "src_1", alpha_decoder, "sink"); gst_element_link_pads (alpha_decoder, "src", alphacombine, "alpha"); src_pad = gst_element_get_static_pad (alphacombine, "src"); gst_ghost_pad_set_target (GST_GHOST_PAD (src_gpad), src_pad); gst_object_unref (src_pad); - g_object_set (queue, "max-size-bytes", 0, "max-size-time", - G_GUINT64_CONSTANT (0), "max-size-buffers", 1, NULL); - g_object_set (alpha_queue, "max-size-bytes", 0, "max-size-time", + g_object_set (mq, "max-size-bytes", 0, "max-size-time", G_GUINT64_CONSTANT (0), "max-size-buffers", 1, NULL); /* signal success, we will handle this in NULL->READY transition */ @@ -185,8 +181,7 @@ cleanup: gst_clear_object (&alphademux); - gst_clear_object (&queue); - gst_clear_object (&alpha_queue); + gst_clear_object (&mq); gst_clear_object (&decoder); gst_clear_object (&alpha_decoder); gst_clear_object (&alphacombine);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/va/gstvacodecalphadecodebin.h -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/va/gstvacodecalphadecodebin.h
Changed
@@ -36,6 +36,15 @@ G_BEGIN_DECLS +/** + * GstVaCodecAlphaDecodeBin: + * + * Base class for VA-API based decoder for alpha formats which come + * as a separate stream, typically found in VP8 and VP9. + * + * Since: 1.24 + */ + #define GST_TYPE_VA_CODEC_ALPHA_DECODE_BIN (gst_va_codec_alpha_decode_bin_get_type()) G_DECLARE_DERIVABLE_TYPE (GstVaCodecAlphaDecodeBin, gst_va_codec_alpha_decode_bin, GST, VA_CODEC_ALPHA_DECODE_BIN, GstBin);
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/va/gstvafilter.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/va/gstvafilter.c
Changed
@@ -585,6 +585,11 @@ VAProcColorBalanceAutoBrightness = { "auto-brightness", "Auto-Brightness", "Enable auto brightness", GST_VA_FILTER_PROP_AUTO_BRIGHTNESS }, + /** + * GstVaPostProc:auto-contrast: + * + * Since: 1.20 + */ VAProcColorBalanceAutoContrast = { "auto-contrast", "Auto-Contrast", "Enable auto contrast", GST_VA_FILTER_PROP_AUTO_CONTRAST }, @@ -692,6 +697,13 @@ if (self->pipeline_caps.mirror_flags != VA_MIRROR_NONE || self->pipeline_caps.rotation_flags != VA_ROTATION_NONE) { + /** + * GstVaPostProc:video-direction: + * + * Video direction: rotation and flipping + * + * Since: 1.20 + */ g_object_class_install_property (klass, GST_VA_FILTER_PROP_VIDEO_DIR, g_param_spec_enum ("video-direction", "Video Direction", "Video direction: rotation and flipping",
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/va/gstvah264enc.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/va/gstvah264enc.c
Changed
@@ -39,6 +39,25 @@ * */ +/** + * SECTION:element-vah264lpenc + * @title: vah264lpenc + * @short_description: A VA-API based H264 low power video encoder + * + * vah264lpenc encodes raw video VA surfaces into H.264 bitstreams using + * the installed and chosen VA-API(https://01.org/linuxmedia/vaapi) + * driver. + * + * The raw video frames in main memory can be imported into VA surfaces. + * + * ## Example launch line + * ``` + * gst-launch-1.0 videotestsrc num-buffers=60 ! timeoverlay ! vah264lpenc ! h264parse ! mp4mux ! filesink location=test.mp4 + * ``` + * + * Since: 1.22 + */ + /* @TODO: * 1. Look ahead, which can optimize the slice type and QP. * 2. Field encoding.
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/va/gstvah265enc.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/va/gstvah265enc.c
Changed
@@ -38,6 +38,26 @@ * */ +/** + * SECTION:element-vah265lpenc + * @title: vah265lpenc + * @short_description: A VA-API based H265 low power video encoder + * + * vah265lpenc encodes raw video VA surfaces into H.265 bitstreams using + * the installed and chosen VA-API(https://01.org/linuxmedia/vaapi) + * driver. + * + * The raw video frames in main memory can be imported into VA surfaces. + * + * ## Example launch line + * ``` + * gst-launch-1.0 videotestsrc num-buffers=60 ! timeoverlay ! vah265lpenc ! h265parse ! mp4mux ! filesink location=test.mp4 + * ``` + * + * Since: 1.22 + * + */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -5389,16 +5409,6 @@ } g_object_class_install_properties (object_class, n_props, properties); - - /** - * GstVaFeature: - * @GST_VA_FEATURE_DISABLED: The feature is disabled. - * @GST_VA_FEATURE_ENABLED: The feature is enabled. - * @GST_VA_FEATURE_AUTO: The feature is enabled automatically. - * - * Since: 1.22 - */ - gst_type_mark_as_plugin_api (GST_TYPE_VA_FEATURE, 0); } static GstCaps *
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/va/gstvavp8dec.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/va/gstvavp8dec.c
Changed
@@ -495,6 +495,22 @@ return NULL; } +/** + * SECTION:element-vavp8alphadecodebin + * @title: vavp8alphadecodebin + * @short_description: A VA-API based VP8 video decoder + * + * Wraps two copies vavp8enc to decode a VP8 video with an alpha layer + * typically carried in a WebM file + * + * ## Example launch line + * ``` + * gst-launch-1.0 filesrc location=sample.webm ! parsebin ! vavp8alphadecodebin ! autovideosink + * ``` + * + * Since: 1.26 + */ + static void gst_va_codec_vp8_alpha_decode_bin_class_init (GstVaCodecAlphaDecodeBinClass * klass, gchar * decoder_name)
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/va/gstvavp8enc.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/va/gstvavp8enc.c
Changed
@@ -1408,16 +1408,6 @@ } g_object_class_install_properties (object_class, n_props, properties); - - /** - * GstVaFeature: - * @GST_VA_FEATURE_DISABLED: The feature is disabled. - * @GST_VA_FEATURE_ENABLED: The feature is enabled. - * @GST_VA_FEATURE_AUTO: The feature is enabled automatically. - * - * Since: 1.24 - */ - gst_type_mark_as_plugin_api (GST_TYPE_VA_FEATURE, 0); } static GstCaps *
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/va/gstvavp9dec.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/va/gstvavp9dec.c
Changed
@@ -693,6 +693,22 @@ return NULL; } +/** + * SECTION:element-vavp9alphadecodebin + * @title: vavp9alphadecodebin + * @short_description: A VA-API based VP9 video decoder + * + * Wraps two copies vavp9enc to decode a VP9 video with an alpha layer + * typically carried in a WebM file + * + * ## Example launch line + * ``` + * gst-launch-1.0 filesrc location=sample.webm ! parsebin ! vavp9alphadecodebin ! autovideosink + * ``` + * + * Since: 1.26 + */ + static void gst_va_codec_vp9_alpha_decode_bin_class_init (GstVaCodecAlphaDecodeBinClass * klass, gchar * decoder_name)
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/va/gstvavp9enc.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/va/gstvavp9enc.c
Changed
@@ -1568,6 +1568,7 @@ } } } + gst_caps_unref (allowed_caps); if (candidates->len == 0) { GST_ERROR_OBJECT (self, "No available profile in caps"); @@ -1622,7 +1623,7 @@ if (ret_profile != VAProfileNone) GST_INFO_OBJECT (self, "Decide the profile: %s", gst_va_profile_name (ret_profile)); - + g_array_unref (candidates); return ret_profile; } @@ -3234,16 +3235,6 @@ } g_object_class_install_properties (object_class, n_props, properties); - - /** - * GstVaFeature: - * @GST_VA_FEATURE_DISABLED: The feature is disabled. - * @GST_VA_FEATURE_ENABLED: The feature is enabled. - * @GST_VA_FEATURE_AUTO: The feature is enabled automatically. - * - * Since: 1.24 - */ - gst_type_mark_as_plugin_api (GST_TYPE_VA_FEATURE, 0); } static GstCaps *
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/va/gstvavpp.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/va/gstvavpp.c
Changed
@@ -433,6 +433,10 @@ GstVaVpp *self = GST_VA_VPP (btrans); gst_va_vpp_rebuild_filters (self); + + /* resetting prev_direction ensures the orientation is actually applied to + * the new instance of GstVaFilter we are configuring here */ + self->prev_direction = GST_VIDEO_ORIENTATION_IDENTITY; _update_properties_unlocked (self); } @@ -2302,14 +2306,29 @@ self->prev_direction = self->direction; self->tag_direction = GST_VIDEO_ORIENTATION_AUTO; + /** + * GstVaPostProc:denoise: + * + * Since: 1.20 + */ pspec = g_object_class_find_property (g_class, "denoise"); if (pspec) self->denoise = g_value_get_float (g_param_spec_get_default_value (pspec)); + /** + * GstVaPostProc:sharpen: + * + * Since: 1.20 + */ pspec = g_object_class_find_property (g_class, "sharpen"); if (pspec) self->sharpen = g_value_get_float (g_param_spec_get_default_value (pspec)); + /** + * GstVaPostProc:skin-tone: + * + * Since: 1.20 + */ pspec = g_object_class_find_property (g_class, "skin-tone"); if (pspec) { const GValue *value = g_param_spec_get_default_value (pspec); @@ -2320,22 +2339,44 @@ } /* color balance */ + /** + * GstVaPostProc:brightness: + * + * Since: 1.20 + */ pspec = g_object_class_find_property (g_class, "brightness"); if (pspec) { self->brightness = g_value_get_float (g_param_spec_get_default_value (pspec)); _create_colorbalance_channel (self, "BRIGHTNESS"); } + /** + * GstVaPostProc:contrast: + * + * Since: 1.20 + */ pspec = g_object_class_find_property (g_class, "contrast"); if (pspec) { self->contrast = g_value_get_float (g_param_spec_get_default_value (pspec)); _create_colorbalance_channel (self, "CONTRAST"); } + /** + * GstVaPostProc:hue: + * + * Since: 1.20 + */ pspec = g_object_class_find_property (g_class, "hue"); if (pspec) { self->hue = g_value_get_float (g_param_spec_get_default_value (pspec)); _create_colorbalance_channel (self, "HUE"); } + /** + * GstVaPostProc:saturation: + * + * Color saturation value + * + * Since: 1.20 + */ pspec = g_object_class_find_property (g_class, "saturation"); if (pspec) { self->saturation = @@ -2343,7 +2384,13 @@ _create_colorbalance_channel (self, "SATURATION"); } - /* HDR tone mapping */ + /** + * GstVaPostProc:hdr-tone-mapping: + * + * HDR tone mapping + * + * Since: 1.22 + */ pspec = g_object_class_find_property (g_class, "hdr-tone-mapping"); if (pspec) { self->hdr_mapping =
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/va/meson.build -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/va/meson.build
Changed
@@ -61,6 +61,7 @@ 'gstvavp9enc.h', 'gstvavpp.h', 'vacompat.h', + 'gstvacodecalphadecodebin.h' va_linux_sources =
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/wasapi/gstwasapidevice.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/wasapi/gstwasapidevice.c
Changed
@@ -353,6 +353,7 @@ switch (prop_id) { case PROP_DEVICE_STRID: + /* G_PARAM_CONSTRUCT_ONLY */ device->strid = g_value_dup_string (value); break; default:
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/wasapi2/gstwasapi2device.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/wasapi2/gstwasapi2device.c
Changed
@@ -129,6 +129,7 @@ switch (prop_id) { case PROP_DEVICE: + /* G_PARAM_CONSTRUCT_ONLY */ self->device_id = g_value_dup_string (value); break; default:
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/sys/winks/ksdeviceprovider.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/sys/winks/ksdeviceprovider.c
Changed
@@ -786,6 +786,7 @@ switch (prop_id) { case PROP_PATH: + /* G_PARAM_CONSTRUCT_ONLY */ device->path = g_value_dup_string (value); break; default:
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/tests/check/elements/webrtcbin.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/tests/check/elements/webrtcbin.c
Changed
@@ -6510,7 +6510,8 @@ VAL_SDP_INIT (no_duplicate_payloads, on_sdp_media_no_duplicate_payloads, NULL, NULL); - guint media_format_count = { 3 }; + // two formats for VP8 and H264 and two for VP8-RTX + H264-RTX + guint media_format_count = { 4 }; VAL_SDP_INIT (media_formats, on_sdp_media_count_formats, media_format_count, &no_duplicate_payloads); VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (1),
View file
_service:download_url:gst-plugins-bad-1.26.0.tar.xz/tests/check/libs/mse.c -> _service:download_url:gst-plugins-bad-1.26.1.tar.xz/tests/check/libs/mse.c
Changed
@@ -65,6 +65,13 @@ return media_source; } +static GstClockTime +sample_dts (GstSample * sample) +{ + GstBuffer *buffer = gst_sample_get_buffer (sample); + return GST_BUFFER_DTS (buffer); +} + static GstSample * new_empty_sample_full (GstClockTime dts, GstClockTime pts, GstClockTime duration, GstBufferFlags flags, GstCaps * caps, @@ -81,6 +88,13 @@ } static GstSample * +new_empty_sample_with_timing_and_flags (GstClockTime dts, GstClockTime pts, + GstClockTime duration, GstBufferFlags flags) +{ + return new_empty_sample_full (dts, pts, duration, flags, NULL, NULL, NULL); +} + +static GstSample * new_empty_sample_with_timing (GstClockTime dts, GstClockTime pts, GstClockTime duration) { @@ -595,21 +609,6 @@ GstSample *sample = gst_sample_new (buffer, NULL, NULL, NULL); gboolean result = gst_media_source_track_push (track, sample); fail_unless (result); - gst_buffer_unref (buffer); - gst_object_unref (track); -} - -GST_END_TEST; - -GST_START_TEST (test_track_push_with_inadequate_space) -{ - GstMediaSourceTrack *track = - gst_media_source_track_new_with_size (GST_MEDIA_SOURCE_TRACK_TYPE_OTHER, - "", 0); - GstBuffer *buffer = gst_buffer_new (); - GstSample *sample = gst_sample_new (buffer, NULL, NULL, NULL); - gboolean result = gst_media_source_track_try_push (track, sample); - fail_if (result); gst_sample_unref (sample); gst_buffer_unref (buffer); gst_object_unref (track); @@ -685,7 +684,7 @@ GstClockTime a_start = 0; GstClockTime a_duration = GST_SECOND; - GstClockTime b_start = a_start + a_duration + GST_SECOND; + GstClockTime b_start = a_start + (a_duration * 3) + 1; GstClockTime b_duration = a_duration; GstSample *a = new_empty_sample_with_timing (a_start, a_start, a_duration); GstSample *b = new_empty_sample_with_timing (b_start, b_start, b_duration); @@ -933,6 +932,10 @@ for (guint i = 0; i < G_N_ELEMENTS (samples_to_remove); i++) { GstClockTime time = i; GstSample *sample = new_empty_sample_with_timing (time, time, 1); + if (i > 0) { + GstBuffer *head = gst_sample_get_buffer (sample); + GST_BUFFER_FLAGS (head) = GST_BUFFER_FLAG_DELTA_UNIT; + } gst_media_source_sample_map_add (map, sample); samples_to_removei = sample; } @@ -940,11 +943,15 @@ for (guint i = 0; i < G_N_ELEMENTS (samples_to_preserve); i++) { GstClockTime time = i + G_N_ELEMENTS (samples_to_remove); GstSample *sample = new_empty_sample_with_timing (time, time, 0); + if (i > 0) { + GstBuffer *head = gst_sample_get_buffer (sample); + GST_BUFFER_FLAGS (head) = GST_BUFFER_FLAG_DELTA_UNIT; + } gst_media_source_sample_map_add (map, sample); samples_to_preservei = sample; } - gst_media_source_sample_map_remove_range_from_start (map, 100); + gst_media_source_sample_map_remove_range (map, 0, 100); for (guint i = 0; i < G_N_ELEMENTS (samples_to_remove); i++) { GstSample *sample = samples_to_removei; @@ -975,20 +982,27 @@ GBytes *bytes = g_bytes_new_static (chunk, buffer_size); total_bytes_to_remove += buffer_size; GstSample *sample = new_sample_with_bytes_and_timing (bytes, time, time, 1); + if (i > 0) { + GstBuffer *head = gst_sample_get_buffer (sample); + GST_BUFFER_FLAGS (head) = GST_BUFFER_FLAG_DELTA_UNIT; + } gst_media_source_sample_map_add (map, sample); samples_to_removei = sample; } GstSample *samples_to_preserve100 = { NULL }; - for (guint i = 0; i < G_N_ELEMENTS (samples_to_preserve); i++) { + for (guint i = 0; i < G_N_ELEMENTS (samples_to_remove); i++) { GstClockTime time = i + G_N_ELEMENTS (samples_to_remove); GBytes *bytes = g_bytes_new_static (chunk, 1); GstSample *sample = new_sample_with_bytes_and_timing (bytes, time, time, 0); + if (i > 0) { + GstBuffer *head = gst_sample_get_buffer (sample); + GST_BUFFER_FLAGS (head) = GST_BUFFER_FLAG_DELTA_UNIT; + } gst_media_source_sample_map_add (map, sample); samples_to_preservei = sample; } - gsize bytes_removed = - gst_media_source_sample_map_remove_range_from_start (map, + gsize bytes_removed = gst_media_source_sample_map_remove_range (map, 0, G_N_ELEMENTS (samples_to_remove)); fail_unless_equals_uint64 (bytes_removed, total_bytes_to_remove); @@ -1004,6 +1018,119 @@ GST_END_TEST; +GST_START_TEST (test_sample_map_remove_range_removes_coded_frame_group) +{ + GstMediaSourceSampleMap *map = gst_media_source_sample_map_new (); + + static const GstClockTime duration = 1; + GstSample *keyframe0 = new_empty_sample_with_timing_and_flags (0, 0, + duration, 0); + GstSample *delta0 = new_empty_sample_with_timing_and_flags (1, 1, + duration, GST_BUFFER_FLAG_DELTA_UNIT); + GstSample *keyframe1 = new_empty_sample_with_timing_and_flags (2, 2, + duration, 0); + GstSample *delta1 = new_empty_sample_with_timing_and_flags (3, 3, + duration, GST_BUFFER_FLAG_DELTA_UNIT); + + GstSample *timeline = { keyframe0, delta0, keyframe1, delta1, NULL }; + + gst_media_source_sample_map_add (map, keyframe0); + gst_media_source_sample_map_add (map, delta0); + gst_media_source_sample_map_add (map, keyframe1); + gst_media_source_sample_map_add (map, delta1); + + GstClockTime start = __i__ * 2; + GstClockTime end = start + duration * 2; + + gst_media_source_sample_map_remove_range (map, start, end); + + for (GstSample ** it = timeline; *it != NULL; it++) { + GstSample *sample = *it; + GstClockTime sample_start = sample_dts (sample); + GstClockTime sample_end = sample_start + duration; + if (sample_start >= start && sample_end <= end) { + fail_if (gst_media_source_sample_map_contains (map, sample)); + } else { + fail_unless (gst_media_source_sample_map_contains (map, sample)); + } + } + + gst_object_unref (map); + gst_sample_unref (keyframe0); + gst_sample_unref (delta0); + gst_sample_unref (keyframe1); + gst_sample_unref (delta1); +} + +GST_END_TEST; + +static void +sample_map_iterate_size (const GValue * item, gpointer user_data) +{ + guint *counter = (guint *) user_data; + *counter = *counter + 1; +} + +GST_START_TEST (test_sample_map_empty_iterator_by_dts) +{ + GstMediaSourceSampleMap *map = gst_media_source_sample_map_new (); + + guint counter = 0; + GMutex mutex = { 0 }; + guint32 cookie = 0; + + GstIterator *it = gst_media_source_sample_map_iter_samples_by_dts (map, + &mutex, &cookie); + gst_iterator_foreach (it, sample_map_iterate_size, &counter); + gst_iterator_free (it); + + assert_equals_int (counter, 0); + + gst_object_unref (map); +} + +GST_END_TEST; + +GST_START_TEST (test_sample_map_grouped_iterator_by_dts) +{ + GstMediaSourceSampleMap *map = gst_media_source_sample_map_new (); + + guint counter = 0; + GMutex mutex = { 0 }; + guint32 cookie = 0; + + GstSample *key = new_empty_sample_full (0, + 0, + GST_SECOND, + 0, + NULL, + NULL, + NULL); + GstSample *delta = new_empty_sample_full (GST_SECOND, + GST_SECOND, + GST_SECOND, + GST_BUFFER_FLAG_DELTA_UNIT, + NULL, + NULL, + NULL); + + gst_media_source_sample_map_add (map, key); + gst_media_source_sample_map_add (map, delta); + + GstIterator *it = gst_media_source_sample_map_iter_samples_by_dts (map, + &mutex, &cookie); + gst_iterator_foreach (it, sample_map_iterate_size, &counter); + gst_iterator_free (it); + + assert_equals_int (counter, 1); + + gst_object_unref (map); + gst_clear_sample (&key); + gst_clear_sample (&delta); +} + +GST_END_TEST; + #define DEFAULT_TCASE_TIMEOUT 15 #ifdef HAVE_VALGRIND @@ -1090,7 +1217,6 @@ tcase_add_test (tc_track, test_track_create_and_free); tcase_add_test (tc_track, test_track_create_with_invalid_type); tcase_add_test (tc_track, test_track_push_with_adequate_space); - tcase_add_test (tc_track, test_track_push_with_inadequate_space); tcase_add_test (tc_track_buffer, test_track_buffer_empty); tcase_add_test (tc_track_buffer, test_track_buffer_single_span); @@ -1102,8 +1228,12 @@ tcase_add_test (tc_sample_map, test_sample_map_add_invalid_sample); tcase_add_test (tc_sample_map, test_sample_map_remove_sample); tcase_add_test (tc_sample_map, test_sample_map_remove_range_from_start); + tcase_add_loop_test (tc_sample_map, + test_sample_map_remove_range_removes_coded_frame_group, 0, 2); tcase_add_test (tc_sample_map, test_sample_map_remove_range_from_start_byte_count); + tcase_add_test (tc_sample_map, test_sample_map_empty_iterator_by_dts); + tcase_add_test (tc_sample_map, test_sample_map_grouped_iterator_by_dts); suite_add_tcase (s, tc_media_source); suite_add_tcase (s, tc_source_buffer);
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.