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