~ubuntu-branches/ubuntu/raring/gst-plugins-good0.10/raring-proposed

« back to all changes in this revision

Viewing changes to farsight/dtmf/gstrtpdtmfsrc.c

  • Committer: Package Import Robot
  • Author(s): Timo Aaltonen
  • Date: 2012-02-09 16:44:53 UTC
  • mfrom: (40.2.38 experimental)
  • Revision ID: package-import@ubuntu.com-20120209164453-6hjokwrvdn42zopb
Tags: 0.10.30.3-1ubuntu1
* Merge from Debian experimental, remaining changes:
  - 04_move_farsight_plugins_to_good.patch
    Import autoconvert, dtmf, liveadder, rptmux from -plugins-bad
  - 05_move_shm_to_good.patch
    Import shm from -plugins-bad.
  - 07_move-camerabin.patch
    Import camerabin, camerabin2, jpegformat and basecamerabinsrc
    from -plugins-bad.
  - control*:
    * Drop dependency from gstreamer0.10-plugins-good on
      gstreamer0.10-gconf. It pulls gconf and gtk3 onto the Kubuntu cd.
    * Use Breaks instead of Conflicts.
    * Add a 'Pre-Depends: ${misc:Pre-Depends}' to the plugin package,
      since we're shipping shared libraries in the package that Debian
      isn't.
* Update the patches by pulling new version of the code from
  -plugins-bad 0.10.22.3.

Show diffs side-by-side

added added

removed removed

Lines of Context:
63
63
 * <row>
64
64
 * <entry>number</entry>
65
65
 * <entry>G_TYPE_INT</entry>
66
 
 * <entry>0-16</entry>
 
66
 * <entry>0-15</entry>
67
67
 * <entry>The event number.</entry>
68
68
 * </row>
69
69
 * <row>
108
108
 * gst_element_send_event (pipeline, event);
109
109
 * </programlisting>
110
110
 *
111
 
 */
 
111
 * When a DTMF tone actually starts or stop, a "dtmf-event-processed"
 
112
 * element #GstMessage with the same fields as the "dtmf-event"
 
113
 * #GstEvent that was used to request the event. Also, if any event
 
114
 * has not been processed when the element goes from the PAUSED to the
 
115
 * READY state, then a "dtmf-event-dropped" message is posted on the
 
116
 * #GstBus in the order that they were received.
 
117
  */
112
118
 
113
119
#ifdef HAVE_CONFIG_H
114
 
#  include "config.h"
 
120
#include "config.h"
115
121
#endif
116
122
 
117
123
#include <stdlib.h>
122
128
#include "gstrtpdtmfsrc.h"
123
129
 
124
130
#define GST_RTP_DTMF_TYPE_EVENT  1
125
 
#define DEFAULT_PACKET_INTERVAL  50     /* ms */
126
 
#define MIN_PACKET_INTERVAL      10     /* ms */
127
 
#define MAX_PACKET_INTERVAL      50     /* ms */
 
131
#define DEFAULT_PTIME            40     /* ms */
128
132
#define DEFAULT_SSRC             -1
129
133
#define DEFAULT_PT               96
130
134
#define DEFAULT_TIMESTAMP_OFFSET -1
131
135
#define DEFAULT_SEQNUM_OFFSET    -1
132
136
#define DEFAULT_CLOCK_RATE       8000
133
 
#define MIN_EVENT                0
134
 
#define MAX_EVENT                16
135
 
#define MIN_EVENT_STRING         "0"
136
 
#define MAX_EVENT_STRING         "16"
137
 
#define MIN_VOLUME               0
138
 
#define MAX_VOLUME               36
139
 
 
140
 
#define MIN_INTER_DIGIT_INTERVAL 50     /* ms */
141
 
#define MIN_PULSE_DURATION       70     /* ms */
142
137
 
143
138
#define DEFAULT_PACKET_REDUNDANCY 1
144
139
#define MIN_PACKET_REDUNDANCY 1
164
159
  PROP_CLOCK_RATE,
165
160
  PROP_TIMESTAMP,
166
161
  PROP_SEQNUM,
167
 
  PROP_INTERVAL,
168
162
  PROP_REDUNDANCY
169
163
};
170
164
 
214
208
  GST_DEBUG_CATEGORY_INIT (gst_rtp_dtmf_src_debug,
215
209
      "rtpdtmfsrc", 0, "rtpdtmfsrc element");
216
210
 
217
 
  gst_element_class_add_pad_template (element_class,
218
 
      gst_static_pad_template_get (&gst_rtp_dtmf_src_template));
 
211
  gst_element_class_add_static_pad_template (element_class,
 
212
      &gst_rtp_dtmf_src_template);
219
213
 
220
214
  gst_element_class_set_details_simple (element_class,
221
215
      "RTP DTMF packet generator", "Source/Network",
273
267
      g_param_spec_uint ("pt", "payload type",
274
268
          "The payload type of the packets",
275
269
          0, 0x80, DEFAULT_PT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
276
 
  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_INTERVAL,
277
 
      g_param_spec_uint ("interval", "Interval between rtp packets",
278
 
          "Interval in ms between two rtp packets", MIN_PACKET_INTERVAL,
279
 
          MAX_PACKET_INTERVAL, DEFAULT_PACKET_INTERVAL,
280
 
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
281
270
  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_REDUNDANCY,
282
271
      g_param_spec_uint ("packet-redundancy", "Packet Redundancy",
283
272
          "Number of packets to send to indicate start and stop dtmf events",
318
307
  object->ts_offset = DEFAULT_TIMESTAMP_OFFSET;
319
308
  object->pt = DEFAULT_PT;
320
309
  object->clock_rate = DEFAULT_CLOCK_RATE;
321
 
  object->interval = DEFAULT_PACKET_INTERVAL;
 
310
  object->ptime = DEFAULT_PTIME;
322
311
  object->packet_redundancy = DEFAULT_PACKET_REDUNDANCY;
323
312
 
324
313
  object->event_queue =
351
340
  gint event_type;
352
341
  gboolean start;
353
342
  gint method;
 
343
  GstClockTime last_stop;
 
344
  gint event_number;
 
345
  gint event_volume;
 
346
  gboolean correct_order;
354
347
 
355
348
  if (!gst_structure_get_int (event_structure, "type", &event_type) ||
356
349
      !gst_structure_get_boolean (event_structure, "start", &start) ||
363
356
    }
364
357
  }
365
358
 
 
359
  if (start)
 
360
    if (!gst_structure_get_int (event_structure, "number", &event_number) ||
 
361
        !gst_structure_get_int (event_structure, "volume", &event_volume))
 
362
      goto failure;
 
363
 
 
364
  GST_OBJECT_LOCK (dtmfsrc);
 
365
  if (gst_structure_get_clock_time (event_structure, "last-stop", &last_stop))
 
366
    dtmfsrc->last_stop = last_stop;
 
367
  else
 
368
    dtmfsrc->last_stop = GST_CLOCK_TIME_NONE;
 
369
  correct_order = (start != dtmfsrc->last_event_was_start);
 
370
  dtmfsrc->last_event_was_start = start;
 
371
  GST_OBJECT_UNLOCK (dtmfsrc);
 
372
 
 
373
  if (!correct_order)
 
374
    goto failure;
 
375
 
366
376
  if (start) {
367
 
    gint event_number;
368
 
    gint event_volume;
369
 
 
370
377
    if (!gst_structure_get_int (event_structure, "number", &event_number) ||
371
378
        !gst_structure_get_int (event_structure, "volume", &event_volume))
372
379
      goto failure;
457
464
      dtmfsrc->pt = g_value_get_uint (value);
458
465
      dtmfsrc->dirty = TRUE;
459
466
      break;
460
 
    case PROP_INTERVAL:
461
 
      dtmfsrc->interval = g_value_get_uint (value);
462
 
      break;
463
467
    case PROP_REDUNDANCY:
464
468
      dtmfsrc->packet_redundancy = g_value_get_uint (value);
465
469
      break;
499
503
    case PROP_SEQNUM:
500
504
      g_value_set_uint (value, dtmfsrc->seqnum);
501
505
      break;
502
 
    case PROP_INTERVAL:
503
 
      g_value_set_uint (value, dtmfsrc->interval);
504
 
      break;
505
506
    case PROP_REDUNDANCY:
506
507
      g_value_set_uint (value, dtmfsrc->packet_redundancy);
507
508
      break;
511
512
  }
512
513
}
513
514
 
514
 
static void
 
515
static gboolean
515
516
gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc * dtmfsrc)
516
517
{
517
 
  GstClock *clock;
518
 
  GstClockTime base_time;
519
 
 
520
 
#ifdef MAEMO_BROKEN
521
 
  base_time = 0;
522
 
#else
523
 
  base_time = gst_element_get_base_time (GST_ELEMENT (dtmfsrc));
524
 
#endif
525
 
 
526
 
  clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc));
527
 
  if (clock != NULL) {
528
 
    dtmfsrc->timestamp = gst_clock_get_time (clock)
529
 
        + (MIN_INTER_DIGIT_INTERVAL * GST_MSECOND) - base_time;
 
518
  GstClockTime last_stop;
 
519
 
 
520
  GST_OBJECT_LOCK (dtmfsrc);
 
521
  last_stop = dtmfsrc->last_stop;
 
522
  GST_OBJECT_UNLOCK (dtmfsrc);
 
523
 
 
524
  if (GST_CLOCK_TIME_IS_VALID (last_stop)) {
 
525
    dtmfsrc->start_timestamp = last_stop;
 
526
  } else {
 
527
    GstClock *clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc));
 
528
 
 
529
    if (clock == NULL)
 
530
      return FALSE;
 
531
 
 
532
    dtmfsrc->start_timestamp = gst_clock_get_time (clock)
 
533
        - gst_element_get_base_time (GST_ELEMENT (dtmfsrc));
 
534
    gst_object_unref (clock);
 
535
  }
 
536
 
 
537
  /* If the last stop was in the past, then lets add the buffers together */
 
538
  if (dtmfsrc->start_timestamp < dtmfsrc->timestamp)
530
539
    dtmfsrc->start_timestamp = dtmfsrc->timestamp;
531
 
    gst_object_unref (clock);
532
 
  } else {
533
 
    gchar *dtmf_name = gst_element_get_name (dtmfsrc);
534
 
    GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", dtmf_name);
535
 
    dtmfsrc->timestamp = GST_CLOCK_TIME_NONE;
536
 
    g_free (dtmf_name);
537
 
  }
 
540
 
 
541
  dtmfsrc->timestamp = dtmfsrc->start_timestamp;
538
542
 
539
543
  dtmfsrc->rtp_timestamp = dtmfsrc->ts_base +
540
544
      gst_util_uint64_scale_int (gst_segment_to_running_time (&GST_BASE_SRC
541
545
          (dtmfsrc)->segment, GST_FORMAT_TIME, dtmfsrc->timestamp),
542
546
      dtmfsrc->clock_rate, GST_SECOND);
 
547
 
 
548
  return TRUE;
543
549
}
544
550
 
545
551
 
554
560
  event->payload = g_slice_new0 (GstRTPDTMFPayload);
555
561
  event->payload->event = CLAMP (event_number, MIN_EVENT, MAX_EVENT);
556
562
  event->payload->volume = CLAMP (event_volume, MIN_VOLUME, MAX_VOLUME);
557
 
  event->payload->duration = dtmfsrc->interval * dtmfsrc->clock_rate / 1000;
 
563
  event->payload->duration = dtmfsrc->ptime * dtmfsrc->clock_rate / 1000;
558
564
 
559
565
  g_async_queue_push (dtmfsrc->event_queue, event);
560
566
}
601
607
  if (dtmfsrc->redundancy_count > 1)
602
608
    GST_BUFFER_DURATION (buf) = 0;
603
609
  else
604
 
    GST_BUFFER_DURATION (buf) = dtmfsrc->interval * GST_MSECOND;
 
610
    GST_BUFFER_DURATION (buf) = dtmfsrc->ptime * GST_MSECOND;
605
611
  GST_BUFFER_TIMESTAMP (buf) = dtmfsrc->timestamp;
606
612
 
607
 
  dtmfsrc->timestamp += GST_BUFFER_DURATION (buf);
608
613
 
609
614
  payload = (GstRTPDTMFPayload *) gst_rtp_buffer_get_payload (buf);
610
615
 
611
616
  /* copy payload and convert to network-byte order */
612
617
  g_memmove (payload, dtmfsrc->payload, sizeof (GstRTPDTMFPayload));
613
 
  /* Force the packet duration to a certain minumum
614
 
   * if its the end of the event
615
 
   */
616
 
  if (payload->e &&
617
 
      payload->duration < MIN_PULSE_DURATION * dtmfsrc->clock_rate / 1000)
618
 
    payload->duration = MIN_PULSE_DURATION * dtmfsrc->clock_rate / 1000;
619
618
 
620
619
  payload->duration = g_htons (payload->duration);
621
620
 
 
621
  if (dtmfsrc->redundancy_count <= 1 && dtmfsrc->last_packet) {
 
622
    GstClockTime inter_digit_interval = MIN_INTER_DIGIT_INTERVAL;
 
623
 
 
624
    if (inter_digit_interval % dtmfsrc->ptime != 0)
 
625
      inter_digit_interval += dtmfsrc->ptime -
 
626
          (MIN_INTER_DIGIT_INTERVAL % dtmfsrc->ptime);
 
627
 
 
628
    GST_BUFFER_DURATION (buf) += inter_digit_interval * GST_MSECOND;
 
629
  }
 
630
 
 
631
  GST_LOG_OBJECT (dtmfsrc, "Creating new buffer with event %u duration "
 
632
      " gst: %" GST_TIME_FORMAT " at %" GST_TIME_FORMAT "(rtp ts:%u dur:%u)",
 
633
      dtmfsrc->payload->event, GST_TIME_ARGS (GST_BUFFER_DURATION (buf)),
 
634
      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), dtmfsrc->rtp_timestamp,
 
635
      dtmfsrc->payload->duration);
622
636
 
623
637
  /* duration of DTMF payloadfor the NEXT packet */
624
638
  /* not updated for redundant packets */
625
 
  if (dtmfsrc->redundancy_count == 0)
626
 
    dtmfsrc->payload->duration +=
627
 
        dtmfsrc->interval * dtmfsrc->clock_rate / 1000;
 
639
  if (dtmfsrc->redundancy_count <= 1)
 
640
    dtmfsrc->payload->duration += dtmfsrc->ptime * dtmfsrc->clock_rate / 1000;
 
641
 
 
642
  if (GST_CLOCK_TIME_IS_VALID (dtmfsrc->timestamp))
 
643
    dtmfsrc->timestamp += GST_BUFFER_DURATION (buf);
628
644
 
629
645
}
630
646
 
644
660
  return buf;
645
661
}
646
662
 
 
663
 
 
664
static void
 
665
gst_dtmf_src_post_message (GstRTPDTMFSrc * dtmfsrc, const gchar * message_name,
 
666
    GstRTPDTMFSrcEvent * event)
 
667
{
 
668
  GstStructure *s = NULL;
 
669
 
 
670
  switch (event->event_type) {
 
671
    case RTP_DTMF_EVENT_TYPE_START:
 
672
      s = gst_structure_new (message_name,
 
673
          "type", G_TYPE_INT, 1,
 
674
          "method", G_TYPE_INT, 1,
 
675
          "start", G_TYPE_BOOLEAN, TRUE,
 
676
          "number", G_TYPE_INT, event->payload->event,
 
677
          "volume", G_TYPE_INT, event->payload->volume, NULL);
 
678
      break;
 
679
    case RTP_DTMF_EVENT_TYPE_STOP:
 
680
      s = gst_structure_new (message_name,
 
681
          "type", G_TYPE_INT, 1, "method", G_TYPE_INT, 1,
 
682
          "start", G_TYPE_BOOLEAN, FALSE, NULL);
 
683
      break;
 
684
    case RTP_DTMF_EVENT_TYPE_PAUSE_TASK:
 
685
      return;
 
686
  }
 
687
 
 
688
  if (s)
 
689
    gst_element_post_message (GST_ELEMENT (dtmfsrc),
 
690
        gst_message_new_element (GST_OBJECT (dtmfsrc), s));
 
691
}
 
692
 
 
693
 
647
694
static GstFlowReturn
648
695
gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset,
649
696
    guint length, GstBuffer ** buffer)
668
715
        case RTP_DTMF_EVENT_TYPE_STOP:
669
716
          GST_WARNING_OBJECT (dtmfsrc,
670
717
              "Received a DTMF stop event when already stopped");
 
718
          gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-dropped", event);
671
719
          break;
672
720
 
673
721
        case RTP_DTMF_EVENT_TYPE_START:
675
723
          dtmfsrc->last_packet = FALSE;
676
724
          /* Set the redundancy on the first packet */
677
725
          dtmfsrc->redundancy_count = dtmfsrc->packet_redundancy;
678
 
          gst_rtp_dtmf_prepare_timestamps (dtmfsrc);
 
726
          if (!gst_rtp_dtmf_prepare_timestamps (dtmfsrc))
 
727
            goto no_clock;
679
728
 
 
729
          gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-processed", event);
680
730
          dtmfsrc->payload = event->payload;
681
731
          event->payload = NULL;
682
732
          break;
710
760
          case RTP_DTMF_EVENT_TYPE_START:
711
761
            GST_WARNING_OBJECT (dtmfsrc,
712
762
                "Received two consecutive DTMF start events");
 
763
            gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-dropped", event);
713
764
            break;
714
765
 
715
766
          case RTP_DTMF_EVENT_TYPE_STOP:
717
768
            dtmfsrc->last_packet = TRUE;
718
769
            /* Set the redundancy on the last packet */
719
770
            dtmfsrc->redundancy_count = dtmfsrc->packet_redundancy;
 
771
            gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-processed", event);
720
772
            break;
721
773
 
722
774
          case RTP_DTMF_EVENT_TYPE_PAUSE_TASK:
742
794
  GST_DEBUG_OBJECT (dtmfsrc, "Processed events, now lets wait on the clock");
743
795
 
744
796
  clock = gst_element_get_clock (GST_ELEMENT (basesrc));
745
 
 
746
 
#ifdef MAEMO_BROKEN
747
 
  clockid = gst_clock_new_single_shot_id (clock, dtmfsrc->timestamp);
748
 
#else
 
797
  if (!clock)
 
798
    goto no_clock;
749
799
  clockid = gst_clock_new_single_shot_id (clock, dtmfsrc->timestamp +
750
800
      gst_element_get_base_time (GST_ELEMENT (dtmfsrc)));
751
 
#endif
752
801
  gst_object_unref (clock);
753
802
 
754
803
  GST_OBJECT_LOCK (dtmfsrc);
813
862
  } else {
814
863
    return GST_FLOW_WRONG_STATE;
815
864
  }
 
865
 
 
866
no_clock:
 
867
  GST_ELEMENT_ERROR (dtmfsrc, STREAM, MUX, ("No available clock"),
 
868
      ("No available clock"));
 
869
  gst_pad_pause_task (GST_BASE_SRC_PAD (dtmfsrc));
 
870
  return GST_FLOW_ERROR;
816
871
}
817
872
 
818
873
 
933
988
      GST_LOG_OBJECT (dtmfsrc, "using internal seqnum-base %u",
934
989
          dtmfsrc->seqnum_base);
935
990
    }
 
991
 
 
992
    if (gst_structure_has_field_typed (s, "ptime", G_TYPE_UINT)) {
 
993
      value = gst_structure_get_value (s, "ptime");
 
994
      dtmfsrc->ptime = g_value_get_uint (value);
 
995
      GST_LOG_OBJECT (dtmfsrc, "using peer ptime %u", dtmfsrc->ptime);
 
996
    } else if (gst_structure_has_field_typed (s, "maxptime", G_TYPE_UINT)) {
 
997
      value = gst_structure_get_value (s, "maxptime");
 
998
      dtmfsrc->ptime = g_value_get_uint (value);
 
999
      GST_LOG_OBJECT (dtmfsrc, "using peer maxptime as ptime %u",
 
1000
          dtmfsrc->ptime);
 
1001
    } else {
 
1002
      /* FIXME, fixate_nearest_uint would be even better */
 
1003
      gst_structure_set (s, "ptime", G_TYPE_UINT, dtmfsrc->ptime, NULL);
 
1004
      GST_LOG_OBJECT (dtmfsrc, "using internal ptime %u", dtmfsrc->ptime);
 
1005
    }
 
1006
 
 
1007
 
936
1008
    GST_DEBUG_OBJECT (dtmfsrc, "with peer caps: %" GST_PTR_FORMAT, srccaps);
937
1009
  }
938
1010
 
965
1037
  else
966
1038
    dtmfsrc->ts_base = dtmfsrc->ts_offset;
967
1039
 
 
1040
  dtmfsrc->timestamp = 0;
968
1041
}
969
1042
 
970
1043
static GstStateChangeReturn
982
1055
      gst_rtp_dtmf_src_ready_to_paused (dtmfsrc);
983
1056
 
984
1057
      /* Flushing the event queue */
985
 
      while ((event = g_async_queue_try_pop (dtmfsrc->event_queue)) != NULL)
 
1058
      while ((event = g_async_queue_try_pop (dtmfsrc->event_queue)) != NULL) {
 
1059
        gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-dropped", event);
986
1060
        gst_rtp_dtmf_src_event_free (event);
 
1061
      }
 
1062
      dtmfsrc->last_event_was_start = FALSE;
987
1063
 
988
1064
      no_preroll = TRUE;
989
1065
      break;
1003
1079
    case GST_STATE_CHANGE_PAUSED_TO_READY:
1004
1080
 
1005
1081
      /* Flushing the event queue */
1006
 
      while ((event = g_async_queue_try_pop (dtmfsrc->event_queue)) != NULL)
 
1082
      while ((event = g_async_queue_try_pop (dtmfsrc->event_queue)) != NULL) {
 
1083
        gst_dtmf_src_post_message (dtmfsrc, "dtmf-event-dropped", event);
1007
1084
        gst_rtp_dtmf_src_event_free (event);
 
1085
      }
 
1086
      dtmfsrc->last_event_was_start = FALSE;
1008
1087
 
1009
1088
      /* Indicate that we don't do PRE_ROLL */
1010
1089
      break;