1 /* 2 * This file is part of gtkD. 3 * 4 * gtkD is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License 6 * as published by the Free Software Foundation; either version 3 7 * of the License, or (at your option) any later version, with 8 * some exceptions, please read the COPYING file. 9 * 10 * gtkD is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with gtkD; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA 18 */ 19 20 // generated automatically - do not change 21 // find conversion definition on APILookup.txt 22 // implement new conversion functionalities on the wrap.utils pakage 23 24 25 module gst.app.AppSink; 26 27 private import gobject.ObjectG; 28 private import gobject.Signals; 29 private import gst.app.c.functions; 30 public import gst.app.c.types; 31 private import gst.base.BaseSink; 32 private import gstreamer.Caps; 33 private import gstreamer.Sample; 34 private import gstreamer.URIHandlerIF; 35 private import gstreamer.URIHandlerT; 36 private import std.algorithm; 37 38 39 /** 40 * Appsink is a sink plugin that supports many different methods for making 41 * the application get a handle on the GStreamer data in a pipeline. Unlike 42 * most GStreamer elements, Appsink provides external API functions. 43 * 44 * appsink can be used by linking to the gstappsink.h header file to access the 45 * methods or by using the appsink action signals and properties. 46 * 47 * The normal way of retrieving samples from appsink is by using the 48 * gst_app_sink_pull_sample() and gst_app_sink_pull_preroll() methods. 49 * These methods block until a sample becomes available in the sink or when the 50 * sink is shut down or reaches EOS. There are also timed variants of these 51 * methods, gst_app_sink_try_pull_sample() and gst_app_sink_try_pull_preroll(), 52 * which accept a timeout parameter to limit the amount of time to wait. 53 * 54 * Appsink will internally use a queue to collect buffers from the streaming 55 * thread. If the application is not pulling samples fast enough, this queue 56 * will consume a lot of memory over time. The "max-buffers" property can be 57 * used to limit the queue size. The "drop" property controls whether the 58 * streaming thread blocks or if older buffers are dropped when the maximum 59 * queue size is reached. Note that blocking the streaming thread can negatively 60 * affect real-time performance and should be avoided. 61 * 62 * If a blocking behaviour is not desirable, setting the "emit-signals" property 63 * to %TRUE will make appsink emit the "new-sample" and "new-preroll" signals 64 * when a sample can be pulled without blocking. 65 * 66 * The "caps" property on appsink can be used to control the formats that 67 * appsink can receive. This property can contain non-fixed caps, the format of 68 * the pulled samples can be obtained by getting the sample caps. 69 * 70 * If one of the pull-preroll or pull-sample methods return %NULL, the appsink 71 * is stopped or in the EOS state. You can check for the EOS state with the 72 * "eos" property or with the gst_app_sink_is_eos() method. 73 * 74 * The eos signal can also be used to be informed when the EOS state is reached 75 * to avoid polling. 76 */ 77 public class AppSink : BaseSink, URIHandlerIF 78 { 79 /** the main Gtk struct */ 80 protected GstAppSink* gstAppSink; 81 82 /** Get the main Gtk struct */ 83 public GstAppSink* getAppSinkStruct(bool transferOwnership = false) 84 { 85 if (transferOwnership) 86 ownedRef = false; 87 return gstAppSink; 88 } 89 90 /** the main Gtk struct as a void* */ 91 protected override void* getStruct() 92 { 93 return cast(void*)gstAppSink; 94 } 95 96 /** 97 * Sets our main struct and passes it to the parent class. 98 */ 99 public this (GstAppSink* gstAppSink, bool ownedRef = false) 100 { 101 this.gstAppSink = gstAppSink; 102 super(cast(GstBaseSink*)gstAppSink, ownedRef); 103 } 104 105 // add the URIHandler capabilities 106 mixin URIHandlerT!(GstAppSink); 107 108 109 /** */ 110 public static GType getType() 111 { 112 return gst_app_sink_get_type(); 113 } 114 115 /** 116 * Check if @appsink supports buffer lists. 117 * 118 * Returns: %TRUE if @appsink supports buffer lists. 119 * 120 * Since: 1.12 121 */ 122 public bool getBufferListSupport() 123 { 124 return gst_app_sink_get_buffer_list_support(gstAppSink) != 0; 125 } 126 127 /** 128 * Get the configured caps on @appsink. 129 * 130 * Returns: the #GstCaps accepted by the sink. gst_caps_unref() after usage. 131 */ 132 public Caps getCaps() 133 { 134 auto p = gst_app_sink_get_caps(gstAppSink); 135 136 if(p is null) 137 { 138 return null; 139 } 140 141 return ObjectG.getDObject!(Caps)(cast(GstCaps*) p, true); 142 } 143 144 /** 145 * Check if @appsink will drop old buffers when the maximum amount of queued 146 * buffers is reached. 147 * 148 * Returns: %TRUE if @appsink is dropping old buffers when the queue is 149 * filled. 150 */ 151 public bool getDrop() 152 { 153 return gst_app_sink_get_drop(gstAppSink) != 0; 154 } 155 156 /** 157 * Check if appsink will emit the "new-preroll" and "new-sample" signals. 158 * 159 * Returns: %TRUE if @appsink is emiting the "new-preroll" and "new-sample" 160 * signals. 161 */ 162 public bool getEmitSignals() 163 { 164 return gst_app_sink_get_emit_signals(gstAppSink) != 0; 165 } 166 167 /** 168 * Get the maximum amount of buffers that can be queued in @appsink. 169 * 170 * Returns: The maximum amount of buffers that can be queued. 171 */ 172 public uint getMaxBuffers() 173 { 174 return gst_app_sink_get_max_buffers(gstAppSink); 175 } 176 177 /** 178 * Check if @appsink will wait for all buffers to be consumed when an EOS is 179 * received. 180 * 181 * Returns: %TRUE if @appsink will wait for all buffers to be consumed when an 182 * EOS is received. 183 */ 184 public bool getWaitOnEos() 185 { 186 return gst_app_sink_get_wait_on_eos(gstAppSink) != 0; 187 } 188 189 /** 190 * Check if @appsink is EOS, which is when no more samples can be pulled because 191 * an EOS event was received. 192 * 193 * This function also returns %TRUE when the appsink is not in the PAUSED or 194 * PLAYING state. 195 * 196 * Returns: %TRUE if no more samples can be pulled and the appsink is EOS. 197 */ 198 public bool isEos() 199 { 200 return gst_app_sink_is_eos(gstAppSink) != 0; 201 } 202 203 /** 204 * Get the last preroll sample in @appsink. This was the sample that caused the 205 * appsink to preroll in the PAUSED state. This sample can be pulled many times 206 * and remains available to the application even after EOS. 207 * 208 * This function is typically used when dealing with a pipeline in the PAUSED 209 * state. Calling this function after doing a seek will give the sample right 210 * after the seek position. 211 * 212 * Note that the preroll sample will also be returned as the first sample 213 * when calling gst_app_sink_pull_sample(). 214 * 215 * If an EOS event was received before any buffers, this function returns 216 * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition. 217 * 218 * This function blocks until a preroll sample or EOS is received or the appsink 219 * element is set to the READY/NULL state. 220 * 221 * Returns: a #GstSample or NULL when the appsink is stopped or EOS. 222 * Call gst_sample_unref() after usage. 223 */ 224 public Sample pullPreroll() 225 { 226 auto p = gst_app_sink_pull_preroll(gstAppSink); 227 228 if(p is null) 229 { 230 return null; 231 } 232 233 return ObjectG.getDObject!(Sample)(cast(GstSample*) p, true); 234 } 235 236 /** 237 * This function blocks until a sample or EOS becomes available or the appsink 238 * element is set to the READY/NULL state. 239 * 240 * This function will only return samples when the appsink is in the PLAYING 241 * state. All rendered buffers will be put in a queue so that the application 242 * can pull samples at its own rate. Note that when the application does not 243 * pull samples fast enough, the queued buffers could consume a lot of memory, 244 * especially when dealing with raw video frames. 245 * 246 * If an EOS event was received before any buffers, this function returns 247 * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition. 248 * 249 * Returns: a #GstSample or NULL when the appsink is stopped or EOS. 250 * Call gst_sample_unref() after usage. 251 */ 252 public Sample pullSample() 253 { 254 auto p = gst_app_sink_pull_sample(gstAppSink); 255 256 if(p is null) 257 { 258 return null; 259 } 260 261 return ObjectG.getDObject!(Sample)(cast(GstSample*) p, true); 262 } 263 264 /** 265 * Instruct @appsink to enable or disable buffer list support. 266 * 267 * For backwards-compatibility reasons applications need to opt in 268 * to indicate that they will be able to handle buffer lists. 269 * 270 * Params: 271 * enableLists = enable or disable buffer list support 272 * 273 * Since: 1.12 274 */ 275 public void setBufferListSupport(bool enableLists) 276 { 277 gst_app_sink_set_buffer_list_support(gstAppSink, enableLists); 278 } 279 280 /** 281 * Set callbacks which will be executed for each new preroll, new sample and eos. 282 * This is an alternative to using the signals, it has lower overhead and is thus 283 * less expensive, but also less flexible. 284 * 285 * If callbacks are installed, no signals will be emitted for performance 286 * reasons. 287 * 288 * Params: 289 * callbacks = the callbacks 290 * userData = a user_data argument for the callbacks 291 * notify = a destroy notify function 292 */ 293 public void setCallbacks(GstAppSinkCallbacks* callbacks, void* userData, GDestroyNotify notify) 294 { 295 gst_app_sink_set_callbacks(gstAppSink, callbacks, userData, notify); 296 } 297 298 /** 299 * Set the capabilities on the appsink element. This function takes 300 * a copy of the caps structure. After calling this method, the sink will only 301 * accept caps that match @caps. If @caps is non-fixed, or incomplete, 302 * you must check the caps on the samples to get the actual used caps. 303 * 304 * Params: 305 * caps = caps to set 306 */ 307 public void setCaps(Caps caps) 308 { 309 gst_app_sink_set_caps(gstAppSink, (caps is null) ? null : caps.getCapsStruct()); 310 } 311 312 /** 313 * Instruct @appsink to drop old buffers when the maximum amount of queued 314 * buffers is reached. 315 * 316 * Params: 317 * drop = the new state 318 */ 319 public void setDrop(bool drop) 320 { 321 gst_app_sink_set_drop(gstAppSink, drop); 322 } 323 324 /** 325 * Make appsink emit the "new-preroll" and "new-sample" signals. This option is 326 * by default disabled because signal emission is expensive and unneeded when 327 * the application prefers to operate in pull mode. 328 * 329 * Params: 330 * emit = the new state 331 */ 332 public void setEmitSignals(bool emit) 333 { 334 gst_app_sink_set_emit_signals(gstAppSink, emit); 335 } 336 337 /** 338 * Set the maximum amount of buffers that can be queued in @appsink. After this 339 * amount of buffers are queued in appsink, any more buffers will block upstream 340 * elements until a sample is pulled from @appsink. 341 * 342 * Params: 343 * max = the maximum number of buffers to queue 344 */ 345 public void setMaxBuffers(uint max) 346 { 347 gst_app_sink_set_max_buffers(gstAppSink, max); 348 } 349 350 /** 351 * Instruct @appsink to wait for all buffers to be consumed when an EOS is received. 352 * 353 * Params: 354 * wait = the new state 355 */ 356 public void setWaitOnEos(bool wait) 357 { 358 gst_app_sink_set_wait_on_eos(gstAppSink, wait); 359 } 360 361 /** 362 * Get the last preroll sample in @appsink. This was the sample that caused the 363 * appsink to preroll in the PAUSED state. This sample can be pulled many times 364 * and remains available to the application even after EOS. 365 * 366 * This function is typically used when dealing with a pipeline in the PAUSED 367 * state. Calling this function after doing a seek will give the sample right 368 * after the seek position. 369 * 370 * Note that the preroll sample will also be returned as the first sample 371 * when calling gst_app_sink_pull_sample(). 372 * 373 * If an EOS event was received before any buffers or the timeout expires, 374 * this function returns %NULL. Use gst_app_sink_is_eos () to check for the EOS 375 * condition. 376 * 377 * This function blocks until a preroll sample or EOS is received, the appsink 378 * element is set to the READY/NULL state, or the timeout expires. 379 * 380 * Params: 381 * timeout = the maximum amount of time to wait for the preroll sample 382 * 383 * Returns: a #GstSample or NULL when the appsink is stopped or EOS or the timeout expires. 384 * Call gst_sample_unref() after usage. 385 * 386 * Since: 1.10 387 */ 388 public Sample tryPullPreroll(GstClockTime timeout) 389 { 390 auto p = gst_app_sink_try_pull_preroll(gstAppSink, timeout); 391 392 if(p is null) 393 { 394 return null; 395 } 396 397 return ObjectG.getDObject!(Sample)(cast(GstSample*) p, true); 398 } 399 400 /** 401 * This function blocks until a sample or EOS becomes available or the appsink 402 * element is set to the READY/NULL state or the timeout expires. 403 * 404 * This function will only return samples when the appsink is in the PLAYING 405 * state. All rendered buffers will be put in a queue so that the application 406 * can pull samples at its own rate. Note that when the application does not 407 * pull samples fast enough, the queued buffers could consume a lot of memory, 408 * especially when dealing with raw video frames. 409 * 410 * If an EOS event was received before any buffers or the timeout expires, 411 * this function returns %NULL. Use gst_app_sink_is_eos () to check for the EOS 412 * condition. 413 * 414 * Params: 415 * timeout = the maximum amount of time to wait for a sample 416 * 417 * Returns: a #GstSample or NULL when the appsink is stopped or EOS or the timeout expires. 418 * Call gst_sample_unref() after usage. 419 * 420 * Since: 1.10 421 */ 422 public Sample tryPullSample(GstClockTime timeout) 423 { 424 auto p = gst_app_sink_try_pull_sample(gstAppSink, timeout); 425 426 if(p is null) 427 { 428 return null; 429 } 430 431 return ObjectG.getDObject!(Sample)(cast(GstSample*) p, true); 432 } 433 434 protected class OnEosDelegateWrapper 435 { 436 void delegate(AppSink) dlg; 437 gulong handlerId; 438 439 this(void delegate(AppSink) dlg) 440 { 441 this.dlg = dlg; 442 onEosListeners ~= this; 443 } 444 445 void remove(OnEosDelegateWrapper source) 446 { 447 foreach(index, wrapper; onEosListeners) 448 { 449 if (wrapper.handlerId == source.handlerId) 450 { 451 onEosListeners[index] = null; 452 onEosListeners = std.algorithm.remove(onEosListeners, index); 453 break; 454 } 455 } 456 } 457 } 458 OnEosDelegateWrapper[] onEosListeners; 459 460 /** 461 * Signal that the end-of-stream has been reached. This signal is emitted from 462 * the streaming thread. 463 */ 464 gulong addOnEos(void delegate(AppSink) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 465 { 466 auto wrapper = new OnEosDelegateWrapper(dlg); 467 wrapper.handlerId = Signals.connectData( 468 this, 469 "eos", 470 cast(GCallback)&callBackEos, 471 cast(void*)wrapper, 472 cast(GClosureNotify)&callBackEosDestroy, 473 connectFlags); 474 return wrapper.handlerId; 475 } 476 477 extern(C) static void callBackEos(GstAppSink* appsinkStruct, OnEosDelegateWrapper wrapper) 478 { 479 wrapper.dlg(wrapper.outer); 480 } 481 482 extern(C) static void callBackEosDestroy(OnEosDelegateWrapper wrapper, GClosure* closure) 483 { 484 wrapper.remove(wrapper); 485 } 486 487 protected class OnNewPrerollDelegateWrapper 488 { 489 GstFlowReturn delegate(AppSink) dlg; 490 gulong handlerId; 491 492 this(GstFlowReturn delegate(AppSink) dlg) 493 { 494 this.dlg = dlg; 495 onNewPrerollListeners ~= this; 496 } 497 498 void remove(OnNewPrerollDelegateWrapper source) 499 { 500 foreach(index, wrapper; onNewPrerollListeners) 501 { 502 if (wrapper.handlerId == source.handlerId) 503 { 504 onNewPrerollListeners[index] = null; 505 onNewPrerollListeners = std.algorithm.remove(onNewPrerollListeners, index); 506 break; 507 } 508 } 509 } 510 } 511 OnNewPrerollDelegateWrapper[] onNewPrerollListeners; 512 513 /** 514 * Signal that a new preroll sample is available. 515 * 516 * This signal is emitted from the streaming thread and only when the 517 * "emit-signals" property is %TRUE. 518 * 519 * The new preroll sample can be retrieved with the "pull-preroll" action 520 * signal or gst_app_sink_pull_preroll() either from this signal callback 521 * or from any other thread. 522 * 523 * Note that this signal is only emitted when the "emit-signals" property is 524 * set to %TRUE, which it is not by default for performance reasons. 525 */ 526 gulong addOnNewPreroll(GstFlowReturn delegate(AppSink) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 527 { 528 auto wrapper = new OnNewPrerollDelegateWrapper(dlg); 529 wrapper.handlerId = Signals.connectData( 530 this, 531 "new-preroll", 532 cast(GCallback)&callBackNewPreroll, 533 cast(void*)wrapper, 534 cast(GClosureNotify)&callBackNewPrerollDestroy, 535 connectFlags); 536 return wrapper.handlerId; 537 } 538 539 extern(C) static GstFlowReturn callBackNewPreroll(GstAppSink* appsinkStruct, OnNewPrerollDelegateWrapper wrapper) 540 { 541 return wrapper.dlg(wrapper.outer); 542 } 543 544 extern(C) static void callBackNewPrerollDestroy(OnNewPrerollDelegateWrapper wrapper, GClosure* closure) 545 { 546 wrapper.remove(wrapper); 547 } 548 549 protected class OnNewSampleDelegateWrapper 550 { 551 GstFlowReturn delegate(AppSink) dlg; 552 gulong handlerId; 553 554 this(GstFlowReturn delegate(AppSink) dlg) 555 { 556 this.dlg = dlg; 557 onNewSampleListeners ~= this; 558 } 559 560 void remove(OnNewSampleDelegateWrapper source) 561 { 562 foreach(index, wrapper; onNewSampleListeners) 563 { 564 if (wrapper.handlerId == source.handlerId) 565 { 566 onNewSampleListeners[index] = null; 567 onNewSampleListeners = std.algorithm.remove(onNewSampleListeners, index); 568 break; 569 } 570 } 571 } 572 } 573 OnNewSampleDelegateWrapper[] onNewSampleListeners; 574 575 /** 576 * Signal that a new sample is available. 577 * 578 * This signal is emitted from the streaming thread and only when the 579 * "emit-signals" property is %TRUE. 580 * 581 * The new sample can be retrieved with the "pull-sample" action 582 * signal or gst_app_sink_pull_sample() either from this signal callback 583 * or from any other thread. 584 * 585 * Note that this signal is only emitted when the "emit-signals" property is 586 * set to %TRUE, which it is not by default for performance reasons. 587 */ 588 gulong addOnNewSample(GstFlowReturn delegate(AppSink) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 589 { 590 auto wrapper = new OnNewSampleDelegateWrapper(dlg); 591 wrapper.handlerId = Signals.connectData( 592 this, 593 "new-sample", 594 cast(GCallback)&callBackNewSample, 595 cast(void*)wrapper, 596 cast(GClosureNotify)&callBackNewSampleDestroy, 597 connectFlags); 598 return wrapper.handlerId; 599 } 600 601 extern(C) static GstFlowReturn callBackNewSample(GstAppSink* appsinkStruct, OnNewSampleDelegateWrapper wrapper) 602 { 603 return wrapper.dlg(wrapper.outer); 604 } 605 606 extern(C) static void callBackNewSampleDestroy(OnNewSampleDelegateWrapper wrapper, GClosure* closure) 607 { 608 wrapper.remove(wrapper); 609 } 610 611 protected class OnPullPrerollDelegateWrapper 612 { 613 Sample delegate(AppSink) dlg; 614 gulong handlerId; 615 616 this(Sample delegate(AppSink) dlg) 617 { 618 this.dlg = dlg; 619 onPullPrerollListeners ~= this; 620 } 621 622 void remove(OnPullPrerollDelegateWrapper source) 623 { 624 foreach(index, wrapper; onPullPrerollListeners) 625 { 626 if (wrapper.handlerId == source.handlerId) 627 { 628 onPullPrerollListeners[index] = null; 629 onPullPrerollListeners = std.algorithm.remove(onPullPrerollListeners, index); 630 break; 631 } 632 } 633 } 634 } 635 OnPullPrerollDelegateWrapper[] onPullPrerollListeners; 636 637 /** 638 * Get the last preroll sample in @appsink. This was the sample that caused the 639 * appsink to preroll in the PAUSED state. This sample can be pulled many times 640 * and remains available to the application even after EOS. 641 * 642 * This function is typically used when dealing with a pipeline in the PAUSED 643 * state. Calling this function after doing a seek will give the sample right 644 * after the seek position. 645 * 646 * Note that the preroll sample will also be returned as the first sample 647 * when calling gst_app_sink_pull_sample() or the "pull-sample" action signal. 648 * 649 * If an EOS event was received before any buffers, this function returns 650 * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition. 651 * 652 * This function blocks until a preroll sample or EOS is received or the appsink 653 * element is set to the READY/NULL state. 654 * 655 * Returns: a #GstSample or NULL when the appsink is stopped or EOS. 656 */ 657 gulong addOnPullPreroll(Sample delegate(AppSink) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 658 { 659 auto wrapper = new OnPullPrerollDelegateWrapper(dlg); 660 wrapper.handlerId = Signals.connectData( 661 this, 662 "pull-preroll", 663 cast(GCallback)&callBackPullPreroll, 664 cast(void*)wrapper, 665 cast(GClosureNotify)&callBackPullPrerollDestroy, 666 connectFlags); 667 return wrapper.handlerId; 668 } 669 670 extern(C) static GstSample* callBackPullPreroll(GstAppSink* appsinkStruct, OnPullPrerollDelegateWrapper wrapper) 671 { 672 auto r = wrapper.dlg(wrapper.outer); 673 return r.getSampleStruct(); 674 } 675 676 extern(C) static void callBackPullPrerollDestroy(OnPullPrerollDelegateWrapper wrapper, GClosure* closure) 677 { 678 wrapper.remove(wrapper); 679 } 680 681 protected class OnPullSampleDelegateWrapper 682 { 683 Sample delegate(AppSink) dlg; 684 gulong handlerId; 685 686 this(Sample delegate(AppSink) dlg) 687 { 688 this.dlg = dlg; 689 onPullSampleListeners ~= this; 690 } 691 692 void remove(OnPullSampleDelegateWrapper source) 693 { 694 foreach(index, wrapper; onPullSampleListeners) 695 { 696 if (wrapper.handlerId == source.handlerId) 697 { 698 onPullSampleListeners[index] = null; 699 onPullSampleListeners = std.algorithm.remove(onPullSampleListeners, index); 700 break; 701 } 702 } 703 } 704 } 705 OnPullSampleDelegateWrapper[] onPullSampleListeners; 706 707 /** 708 * This function blocks until a sample or EOS becomes available or the appsink 709 * element is set to the READY/NULL state. 710 * 711 * This function will only return samples when the appsink is in the PLAYING 712 * state. All rendered samples will be put in a queue so that the application 713 * can pull samples at its own rate. 714 * 715 * Note that when the application does not pull samples fast enough, the 716 * queued samples could consume a lot of memory, especially when dealing with 717 * raw video frames. It's possible to control the behaviour of the queue with 718 * the "drop" and "max-buffers" properties. 719 * 720 * If an EOS event was received before any buffers, this function returns 721 * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition. 722 * 723 * Returns: a #GstSample or NULL when the appsink is stopped or EOS. 724 */ 725 gulong addOnPullSample(Sample delegate(AppSink) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 726 { 727 auto wrapper = new OnPullSampleDelegateWrapper(dlg); 728 wrapper.handlerId = Signals.connectData( 729 this, 730 "pull-sample", 731 cast(GCallback)&callBackPullSample, 732 cast(void*)wrapper, 733 cast(GClosureNotify)&callBackPullSampleDestroy, 734 connectFlags); 735 return wrapper.handlerId; 736 } 737 738 extern(C) static GstSample* callBackPullSample(GstAppSink* appsinkStruct, OnPullSampleDelegateWrapper wrapper) 739 { 740 auto r = wrapper.dlg(wrapper.outer); 741 return r.getSampleStruct(); 742 } 743 744 extern(C) static void callBackPullSampleDestroy(OnPullSampleDelegateWrapper wrapper, GClosure* closure) 745 { 746 wrapper.remove(wrapper); 747 } 748 749 protected class OnTryPullPrerollDelegateWrapper 750 { 751 Sample delegate(ulong, AppSink) dlg; 752 gulong handlerId; 753 754 this(Sample delegate(ulong, AppSink) dlg) 755 { 756 this.dlg = dlg; 757 onTryPullPrerollListeners ~= this; 758 } 759 760 void remove(OnTryPullPrerollDelegateWrapper source) 761 { 762 foreach(index, wrapper; onTryPullPrerollListeners) 763 { 764 if (wrapper.handlerId == source.handlerId) 765 { 766 onTryPullPrerollListeners[index] = null; 767 onTryPullPrerollListeners = std.algorithm.remove(onTryPullPrerollListeners, index); 768 break; 769 } 770 } 771 } 772 } 773 OnTryPullPrerollDelegateWrapper[] onTryPullPrerollListeners; 774 775 /** 776 * Get the last preroll sample in @appsink. This was the sample that caused the 777 * appsink to preroll in the PAUSED state. This sample can be pulled many times 778 * and remains available to the application even after EOS. 779 * 780 * This function is typically used when dealing with a pipeline in the PAUSED 781 * state. Calling this function after doing a seek will give the sample right 782 * after the seek position. 783 * 784 * Note that the preroll sample will also be returned as the first sample 785 * when calling gst_app_sink_pull_sample() or the "pull-sample" action signal. 786 * 787 * If an EOS event was received before any buffers or the timeout expires, 788 * this function returns %NULL. Use gst_app_sink_is_eos () to check for the EOS 789 * condition. 790 * 791 * This function blocks until a preroll sample or EOS is received, the appsink 792 * element is set to the READY/NULL state, or the timeout expires. 793 * 794 * Params: 795 * timeout = the maximum amount of time to wait for the preroll sample 796 * 797 * Returns: a #GstSample or NULL when the appsink is stopped or EOS or the timeout expires. 798 * 799 * Since: 1.10 800 */ 801 gulong addOnTryPullPreroll(Sample delegate(ulong, AppSink) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 802 { 803 auto wrapper = new OnTryPullPrerollDelegateWrapper(dlg); 804 wrapper.handlerId = Signals.connectData( 805 this, 806 "try-pull-preroll", 807 cast(GCallback)&callBackTryPullPreroll, 808 cast(void*)wrapper, 809 cast(GClosureNotify)&callBackTryPullPrerollDestroy, 810 connectFlags); 811 return wrapper.handlerId; 812 } 813 814 extern(C) static GstSample* callBackTryPullPreroll(GstAppSink* appsinkStruct, ulong timeout, OnTryPullPrerollDelegateWrapper wrapper) 815 { 816 auto r = wrapper.dlg(timeout, wrapper.outer); 817 return r.getSampleStruct(); 818 } 819 820 extern(C) static void callBackTryPullPrerollDestroy(OnTryPullPrerollDelegateWrapper wrapper, GClosure* closure) 821 { 822 wrapper.remove(wrapper); 823 } 824 825 protected class OnTryPullSampleDelegateWrapper 826 { 827 Sample delegate(ulong, AppSink) dlg; 828 gulong handlerId; 829 830 this(Sample delegate(ulong, AppSink) dlg) 831 { 832 this.dlg = dlg; 833 onTryPullSampleListeners ~= this; 834 } 835 836 void remove(OnTryPullSampleDelegateWrapper source) 837 { 838 foreach(index, wrapper; onTryPullSampleListeners) 839 { 840 if (wrapper.handlerId == source.handlerId) 841 { 842 onTryPullSampleListeners[index] = null; 843 onTryPullSampleListeners = std.algorithm.remove(onTryPullSampleListeners, index); 844 break; 845 } 846 } 847 } 848 } 849 OnTryPullSampleDelegateWrapper[] onTryPullSampleListeners; 850 851 /** 852 * This function blocks until a sample or EOS becomes available or the appsink 853 * element is set to the READY/NULL state or the timeout expires. 854 * 855 * This function will only return samples when the appsink is in the PLAYING 856 * state. All rendered samples will be put in a queue so that the application 857 * can pull samples at its own rate. 858 * 859 * Note that when the application does not pull samples fast enough, the 860 * queued samples could consume a lot of memory, especially when dealing with 861 * raw video frames. It's possible to control the behaviour of the queue with 862 * the "drop" and "max-buffers" properties. 863 * 864 * If an EOS event was received before any buffers or the timeout expires, 865 * this function returns %NULL. Use gst_app_sink_is_eos () to check 866 * for the EOS condition. 867 * 868 * Params: 869 * timeout = the maximum amount of time to wait for a sample 870 * 871 * Returns: a #GstSample or NULL when the appsink is stopped or EOS or the timeout expires. 872 * 873 * Since: 1.10 874 */ 875 gulong addOnTryPullSample(Sample delegate(ulong, AppSink) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 876 { 877 auto wrapper = new OnTryPullSampleDelegateWrapper(dlg); 878 wrapper.handlerId = Signals.connectData( 879 this, 880 "try-pull-sample", 881 cast(GCallback)&callBackTryPullSample, 882 cast(void*)wrapper, 883 cast(GClosureNotify)&callBackTryPullSampleDestroy, 884 connectFlags); 885 return wrapper.handlerId; 886 } 887 888 extern(C) static GstSample* callBackTryPullSample(GstAppSink* appsinkStruct, ulong timeout, OnTryPullSampleDelegateWrapper wrapper) 889 { 890 auto r = wrapper.dlg(timeout, wrapper.outer); 891 return r.getSampleStruct(); 892 } 893 894 extern(C) static void callBackTryPullSampleDestroy(OnTryPullSampleDelegateWrapper wrapper, GClosure* closure) 895 { 896 wrapper.remove(wrapper); 897 } 898 }