{"object_kind":"push","event_name":"push","before":"cebbb24d63a97590b11a9998f1f8bfe807b83fcf","after":"bf3951eb0daa936248766491079d9eff202ca830","ref":"refs/heads/master","ref_protected":true,"checkout_sha":"bf3951eb0daa936248766491079d9eff202ca830","message":null,"user_id":3060,"user_name":"Wim Taymans","user_username":"wtaymans","user_email":"","user_avatar":"https://secure.gravatar.com/avatar/1ca1bed246cb9b95b7ead6d6be96bb09f0c112953140c8bb38b41aedf4465270?s=80&d=identicon","project_id":4753,"project":{"id":4753,"name":"pipewire","description":"Multimedia processing graphs","web_url":"https://gitlab.freedesktop.org/pipewire/pipewire","avatar_url":"https://gitlab.freedesktop.org/uploads/-/system/project/avatar/4753/pipewire.png","git_ssh_url":"git@ssh.gitlab.freedesktop.org:pipewire/pipewire.git","git_http_url":"https://gitlab.freedesktop.org/pipewire/pipewire.git","namespace":"PipeWire","visibility_level":20,"path_with_namespace":"pipewire/pipewire","default_branch":"master","ci_config_path":"","homepage":"https://gitlab.freedesktop.org/pipewire/pipewire","url":"git@ssh.gitlab.freedesktop.org:pipewire/pipewire.git","ssh_url":"git@ssh.gitlab.freedesktop.org:pipewire/pipewire.git","http_url":"https://gitlab.freedesktop.org/pipewire/pipewire.git"},"commits":[{"id":"bf3951eb0daa936248766491079d9eff202ca830","message":"gstpipewiresrc: copy the last free buffer instead of stalling the stream\n\nA buffer is handed back to the producer as soon as it has been passed on, in the\nsame graph cycle, so when downstream keeps hold of the whole pool the producer\nis left with nothing to fill and the stream stops rather than degrading. With\nthe four buffers a v4l2 source negotiates by default, a consumer holding four\nframes is enough.\n\nHanding over the last free buffer is the moment that decides it, and it is also\nthe last moment that buffer can still be made to come back: copy it there\ninstead of sharing it, and it returns to the producer straight away.\n\nThis follows the design as stated rather than working against it. @wtaymans in\n!1917: \"How about stating to copy the buffers when the gstreamer source is\nlagging for more than X buffers?\", and in #4174: \"The best is to just deal with\nit in the client.\" So the producer keeps its round-robin reuse and the consumer\nstops assuming the memory stays still.\n\nMeasured on three sources -- facetimehd on a MacBookPro14,1, a UVC camera on a\nLenovo, and vivid, which is in the kernel tree and needs no particular hardware\nto reproduce any of this. appsink holding N samples referenced, pool size set\nwith max-buffers, arms alternated run by run, and every frame classified as\nshared or copied by two independent signals that had to agree. \"dead\" is the\nstream stopping after exactly pool frames.\n\n\tpool held before after frames copied\n\t 2 1 55 55 49%\n\t 2 2 dead 41 66%\n\t 3 2 55 55 33%\n\t 3 3 dead 37 49%\n\t 4 3 55 55 24%\n\t 4 4 dead 34 38%\n\t 16 15 37 37 5%\n\t 16 16 dead 22 9%\n\nEvery case that used to stop now survives. The cost is the last column, and it\nis not zero before it is needed: the decision has to be taken before the buffer\nis handed over, from how many are outstanding at that moment, and that number\ncannot tell a consumer that returns the buffer at once from one that keeps it.\nThe smaller the pool the less room there is between the two, which is why a pool\nof two copies about half its frames while nothing is wrong.\n\nWhile it applies, downstream receives system memory where it would otherwise get\nthe DMA-BUF, including on caps carrying memory:DMABuf and format=DMA_DRM. That\nwas checked rather than assumed: with glupload downstream, every frame still\narrives and nothing fails. Other consumers have not been tried.\n\nAn explicit use-bufferpool=false is unaffected, and use-bufferpool=true keeps\nsharing as asked -- the test applies to USE_BUFFERPOOL_AUTO alone. A DMA-BUF\nwithout SPA_DATA_FLAG_MAPPABLE cannot be copied at all, so those keep sharing.\nA pool of one is left out, because there every buffer is the last one, which is\nwhat use-bufferpool=false already provides explicitly.\n\nWhat this does not do is make the sharing itself safe: the producer still hands\na buffer back while downstream may be reading it, so a consumer that holds a\nsingle buffer for a long time can still have it overwritten without ever\nstarving the pool. Closing that would need SPA_META_Busy implemented on the\nproducer side, which no SPA plugin does today.\n\nIt does not treat #4797's \"buffer was not recycled\" directly either -- that\ncheck returns before this decision is reached. What it does is make the state\narise less often: on a pool of four with the consumer holding four, the message\ngoes from 25 occurrences to 10 on one machine and from 81 to 31 on the other,\nin runs of the same length.\n\nRelated: #5363, #4797, #4174, #4863, !1917.\n","title":"gstpipewiresrc: copy the last free buffer instead of stalling the stream","timestamp":"2026-09-07T11:18:13+00:00","url":"https://gitlab.freedesktop.org/pipewire/pipewire/-/commit/bf3951eb0daa936248766491079d9eff202ca830","author":{"name":"Viorel Cernateanu","email":"vrilutza@gmail.com"},"added":[],"modified":["src/gst/gstpipewiresrc.c","src/gst/gstpipewiresrc.h"],"removed":[]}],"total_commits_count":1,"push_options":{},"repository":{"name":"pipewire","url":"git@ssh.gitlab.freedesktop.org:pipewire/pipewire.git","description":"Multimedia processing graphs","homepage":"https://gitlab.freedesktop.org/pipewire/pipewire","git_http_url":"https://gitlab.freedesktop.org/pipewire/pipewire.git","git_ssh_url":"git@ssh.gitlab.freedesktop.org:pipewire/pipewire.git","visibility_level":20}}