~ubuntu-branches/ubuntu/precise/gst-plugins-base0.10/precise-updates

« back to all changes in this revision

Viewing changes to gst/videorate/gstvideorate.c

  • Committer: Package Import Robot
  • Author(s): Sebastian Dröge
  • Date: 2011-12-11 19:27:10 UTC
  • mfrom: (11.7.12) (33.1.11 sid)
  • mto: This revision was merged to the branch mainline in revision 58.
  • Revision ID: package-import@ubuntu.com-20111211192710-f52020gqtas8705f
Tags: 0.10.35.2-1
* New upstream pre-release:
  + debian/rules,
    debian/build-deps.in:
    - Build-depend on GStreamer core >= 0.10.35.2.
    - Build-depend on GLib >= 2.24.
    - Build-depend on GTK+ 3.0.
    - Build-depend on zlib.
  + debian/patches/99_ltmain_as-needed.patch:
    - Refresh to apply cleanly again.
  + debian/libgstreamer-plugins-base.symbols:
    - Update symbols file with new API.
* debian/rules:
  + Remove all dependency_libs from the .la files.
* debian/control.in:
  + Put GI package into section introspection.
* debian/build-deps.in,
  debian/compat,
  debian/control.in,
  debian/gir1.2-gst-plugins-base.install,
  debian/gstreamer-alsa.install,
  debian/gstreamer-gnomevfs.install,
  debian/gstreamer-plugins-base.install,
  debian/gstreamer-x.install,
  debian/libgstreamer-plugins-base-dev.install,
  debian/libgstreamer-plugins-base.install,
  debian/rules:
  + Transition package to multi-arch (Closes: #647485).
    Patch taken from the Ubuntu package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
86
86
#define DEFAULT_SILENT          TRUE
87
87
#define DEFAULT_NEW_PREF        1.0
88
88
#define DEFAULT_SKIP_TO_FIRST   FALSE
 
89
#define DEFAULT_DROP_ONLY       FALSE
 
90
#define DEFAULT_AVERAGE_PERIOD  0
 
91
#define DEFAULT_MAX_RATE        G_MAXINT
 
92
#define DEFAULT_FORCE_FPS_N     -1
 
93
#define DEFAULT_FORCE_FPS_D     1
89
94
 
90
95
enum
91
96
{
92
 
  ARG_0,
93
 
  ARG_IN,
94
 
  ARG_OUT,
95
 
  ARG_DUP,
96
 
  ARG_DROP,
97
 
  ARG_SILENT,
98
 
  ARG_NEW_PREF,
99
 
  ARG_SKIP_TO_FIRST
 
97
  PROP_0,
 
98
  PROP_IN,
 
99
  PROP_OUT,
 
100
  PROP_DUP,
 
101
  PROP_DROP,
 
102
  PROP_SILENT,
 
103
  PROP_NEW_PREF,
 
104
  PROP_SKIP_TO_FIRST,
 
105
  PROP_DROP_ONLY,
 
106
  PROP_AVERAGE_PERIOD,
 
107
  PROP_MAX_RATE,
 
108
  PROP_FORCE_FPS
100
109
      /* FILL ME */
101
110
};
102
111
 
118
127
 
119
128
static void gst_video_rate_swap_prev (GstVideoRate * videorate,
120
129
    GstBuffer * buffer, gint64 time);
121
 
static gboolean gst_video_rate_event (GstPad * pad, GstEvent * event);
122
 
static gboolean gst_video_rate_query (GstPad * pad, GstQuery * query);
123
 
static GstFlowReturn gst_video_rate_chain (GstPad * pad, GstBuffer * buffer);
 
130
static gboolean gst_video_rate_event (GstBaseTransform * trans,
 
131
    GstEvent * event);
 
132
static gboolean gst_video_rate_query (GstBaseTransform * trans,
 
133
    GstPadDirection direction, GstQuery * query);
 
134
 
 
135
static gboolean gst_video_rate_setcaps (GstBaseTransform * trans,
 
136
    GstCaps * in_caps, GstCaps * out_caps);
 
137
 
 
138
static GstCaps *gst_video_rate_transform_caps (GstBaseTransform * trans,
 
139
    GstPadDirection direction, GstCaps * caps);
 
140
 
 
141
static void gst_video_rate_fixate_caps (GstBaseTransform * trans,
 
142
    GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
 
143
 
 
144
static GstFlowReturn gst_video_rate_prepare_output_buffer (GstBaseTransform *
 
145
    trans, GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf);
 
146
static GstFlowReturn gst_video_rate_transform_ip (GstBaseTransform * trans,
 
147
    GstBuffer * buf);
 
148
 
 
149
static gboolean gst_video_rate_start (GstBaseTransform * trans);
 
150
static gboolean gst_video_rate_stop (GstBaseTransform * trans);
 
151
 
124
152
 
125
153
static void gst_video_rate_set_property (GObject * object,
126
154
    guint prop_id, const GValue * value, GParamSpec * pspec);
127
155
static void gst_video_rate_get_property (GObject * object,
128
156
    guint prop_id, GValue * value, GParamSpec * pspec);
129
157
 
130
 
static GstStateChangeReturn gst_video_rate_change_state (GstElement * element,
131
 
    GstStateChange transition);
132
 
 
133
 
/*static guint gst_video_rate_signals[LAST_SIGNAL] = { 0 }; */
134
 
 
135
158
static GParamSpec *pspec_drop = NULL;
136
159
static GParamSpec *pspec_duplicate = NULL;
137
160
 
138
 
GST_BOILERPLATE (GstVideoRate, gst_video_rate, GstElement, GST_TYPE_ELEMENT);
 
161
GST_BOILERPLATE (GstVideoRate, gst_video_rate,
 
162
    GstBaseTransform, GST_TYPE_BASE_TRANSFORM);
139
163
 
140
164
static void
141
165
gst_video_rate_base_init (gpointer g_class)
147
171
      "Drops/duplicates/adjusts timestamps on video frames to make a perfect stream",
148
172
      "Wim Taymans <wim@fluendo.com>");
149
173
 
150
 
  gst_element_class_add_pad_template (element_class,
151
 
      gst_static_pad_template_get (&gst_video_rate_sink_template));
152
 
  gst_element_class_add_pad_template (element_class,
153
 
      gst_static_pad_template_get (&gst_video_rate_src_template));
 
174
  gst_element_class_add_static_pad_template (element_class,
 
175
      &gst_video_rate_sink_template);
 
176
  gst_element_class_add_static_pad_template (element_class,
 
177
      &gst_video_rate_src_template);
154
178
}
155
179
 
156
180
static void
157
181
gst_video_rate_class_init (GstVideoRateClass * klass)
158
182
{
159
183
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
160
 
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
 
184
  GstBaseTransformClass *base_class = GST_BASE_TRANSFORM_CLASS (klass);
161
185
 
162
186
  parent_class = g_type_class_peek_parent (klass);
163
187
 
164
188
  object_class->set_property = gst_video_rate_set_property;
165
189
  object_class->get_property = gst_video_rate_get_property;
166
190
 
167
 
  g_object_class_install_property (object_class, ARG_IN,
 
191
  base_class->set_caps = GST_DEBUG_FUNCPTR (gst_video_rate_setcaps);
 
192
  base_class->transform_caps =
 
193
      GST_DEBUG_FUNCPTR (gst_video_rate_transform_caps);
 
194
  base_class->transform_ip = GST_DEBUG_FUNCPTR (gst_video_rate_transform_ip);
 
195
  base_class->prepare_output_buffer =
 
196
      GST_DEBUG_FUNCPTR (gst_video_rate_prepare_output_buffer);
 
197
  base_class->event = GST_DEBUG_FUNCPTR (gst_video_rate_event);
 
198
  base_class->start = GST_DEBUG_FUNCPTR (gst_video_rate_start);
 
199
  base_class->stop = GST_DEBUG_FUNCPTR (gst_video_rate_stop);
 
200
  base_class->fixate_caps = GST_DEBUG_FUNCPTR (gst_video_rate_fixate_caps);
 
201
  base_class->query = GST_DEBUG_FUNCPTR (gst_video_rate_query);
 
202
 
 
203
  g_object_class_install_property (object_class, PROP_IN,
168
204
      g_param_spec_uint64 ("in", "In",
169
205
          "Number of input frames", 0, G_MAXUINT64, 0,
170
206
          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
171
 
  g_object_class_install_property (object_class, ARG_OUT,
 
207
  g_object_class_install_property (object_class, PROP_OUT,
172
208
      g_param_spec_uint64 ("out", "Out", "Number of output frames", 0,
173
209
          G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
174
210
  pspec_duplicate = g_param_spec_uint64 ("duplicate", "Duplicate",
175
211
      "Number of duplicated frames", 0, G_MAXUINT64, 0,
176
212
      G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
177
 
  g_object_class_install_property (object_class, ARG_DUP, pspec_duplicate);
 
213
  g_object_class_install_property (object_class, PROP_DUP, pspec_duplicate);
178
214
  pspec_drop = g_param_spec_uint64 ("drop", "Drop", "Number of dropped frames",
179
215
      0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
180
 
  g_object_class_install_property (object_class, ARG_DROP, pspec_drop);
181
 
  g_object_class_install_property (object_class, ARG_SILENT,
 
216
  g_object_class_install_property (object_class, PROP_DROP, pspec_drop);
 
217
  g_object_class_install_property (object_class, PROP_SILENT,
182
218
      g_param_spec_boolean ("silent", "silent",
183
219
          "Don't emit notify for dropped and duplicated frames", DEFAULT_SILENT,
184
220
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
185
 
  g_object_class_install_property (object_class, ARG_NEW_PREF,
 
221
  g_object_class_install_property (object_class, PROP_NEW_PREF,
186
222
      g_param_spec_double ("new-pref", "New Pref",
187
223
          "Value indicating how much to prefer new frames (unused)", 0.0, 1.0,
188
224
          DEFAULT_NEW_PREF, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
194
230
   *
195
231
   * Since: 0.10.25
196
232
   */
197
 
  g_object_class_install_property (object_class, ARG_SKIP_TO_FIRST,
 
233
  g_object_class_install_property (object_class, PROP_SKIP_TO_FIRST,
198
234
      g_param_spec_boolean ("skip-to-first", "Skip to first buffer",
199
235
          "Don't produce buffers before the first one we receive",
200
236
          DEFAULT_SKIP_TO_FIRST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
201
237
 
202
 
  element_class->change_state = GST_DEBUG_FUNCPTR (gst_video_rate_change_state);
203
 
}
204
 
 
205
 
/* return the caps that can be used on out_pad given in_caps on in_pad */
 
238
  /**
 
239
   * GstVideoRate:drop-only:
 
240
   *
 
241
   * Only drop frames, no duplicates are produced.
 
242
   *
 
243
   * Since: 0.10.36
 
244
   */
 
245
  g_object_class_install_property (object_class, PROP_DROP_ONLY,
 
246
      g_param_spec_boolean ("drop-only", "Only Drop",
 
247
          "Only drop frames, no duplicates are produced",
 
248
          DEFAULT_DROP_ONLY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
249
 
 
250
  /**
 
251
   * GstVideoRate:average-period:
 
252
   *
 
253
   * Arrange for maximum framerate by dropping frames beyond a certain framerate,
 
254
   * where the framerate is calculated using a moving average over the
 
255
   * configured.
 
256
   *
 
257
   * Since: 0.10.36
 
258
   */
 
259
  g_object_class_install_property (object_class, PROP_AVERAGE_PERIOD,
 
260
      g_param_spec_uint64 ("average-period", "Period over which to average",
 
261
          "Period over which to average the framerate (in ns) (0 = disabled)",
 
262
          0, G_MAXINT64, DEFAULT_AVERAGE_PERIOD,
 
263
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
264
 
 
265
  /**
 
266
   * GstVideoRate:max-rate:
 
267
   *
 
268
   * maximum framerate to pass through
 
269
   *
 
270
   * Since: 0.10.36
 
271
   */
 
272
  g_object_class_install_property (object_class, PROP_MAX_RATE,
 
273
      g_param_spec_int ("max-rate", "maximum framerate",
 
274
          "Maximum framerate allowed to pass through "
 
275
          "(in frames per second, implies drop-only)",
 
276
          1, G_MAXINT, DEFAULT_MAX_RATE,
 
277
          G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
 
278
 
 
279
  /**
 
280
   * GstVideoRate:force-fps:
 
281
   *
 
282
   * Forced output framerate
 
283
   *
 
284
   * Since: 0.10.36
 
285
   */
 
286
  g_object_class_install_property (object_class, PROP_FORCE_FPS,
 
287
      gst_param_spec_fraction ("force-fps", "Force output framerate",
 
288
          "Force output framerate (negative means negotiate via caps)",
 
289
          -1, 1, G_MAXINT, 1, DEFAULT_FORCE_FPS_N, DEFAULT_FORCE_FPS_D,
 
290
          G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
 
291
}
 
292
 
 
293
static void
 
294
gst_value_fraction_get_extremes (const GValue * v,
 
295
    gint * min_num, gint * min_denom, gint * max_num, gint * max_denom)
 
296
{
 
297
  if (GST_VALUE_HOLDS_FRACTION (v)) {
 
298
    *min_num = *max_num = gst_value_get_fraction_numerator (v);
 
299
    *min_denom = *max_denom = gst_value_get_fraction_denominator (v);
 
300
  } else if (GST_VALUE_HOLDS_FRACTION_RANGE (v)) {
 
301
    const GValue *min, *max;
 
302
 
 
303
    min = gst_value_get_fraction_range_min (v);
 
304
    *min_num = gst_value_get_fraction_numerator (min);
 
305
    *min_denom = gst_value_get_fraction_denominator (min);
 
306
 
 
307
    max = gst_value_get_fraction_range_max (v);
 
308
    *max_num = gst_value_get_fraction_numerator (max);
 
309
    *max_denom = gst_value_get_fraction_denominator (max);
 
310
  } else if (GST_VALUE_HOLDS_LIST (v)) {
 
311
    gint min_n = G_MAXINT, min_d = 1, max_n = 0, max_d = 1;
 
312
    int i, n;
 
313
 
 
314
    *min_num = G_MAXINT;
 
315
    *min_denom = 1;
 
316
    *max_num = 0;
 
317
    *max_denom = 1;
 
318
 
 
319
    n = gst_value_list_get_size (v);
 
320
 
 
321
    g_assert (n > 0);
 
322
 
 
323
    for (i = 0; i < n; i++) {
 
324
      const GValue *t = gst_value_list_get_value (v, i);
 
325
 
 
326
      gst_value_fraction_get_extremes (t, &min_n, &min_d, &max_n, &max_d);
 
327
      if (gst_util_fraction_compare (min_n, min_d, *min_num, *min_denom) < 0) {
 
328
        *min_num = min_n;
 
329
        *min_denom = min_d;
 
330
      }
 
331
 
 
332
      if (gst_util_fraction_compare (max_n, max_d, *max_num, *max_denom) > 0) {
 
333
        *max_num = max_n;
 
334
        *max_denom = max_d;
 
335
      }
 
336
    }
 
337
  } else {
 
338
    g_warning ("Unknown type for framerate");
 
339
    *min_num = 0;
 
340
    *min_denom = 1;
 
341
    *max_num = G_MAXINT;
 
342
    *max_denom = 1;
 
343
  }
 
344
}
 
345
 
 
346
/* Clamp the framerate in a caps structure to be a smaller range then
 
347
 * [1...max_rate], otherwise return false */
206
348
static gboolean
207
 
gst_video_rate_transformcaps (GstPad * in_pad, GstCaps * in_caps,
208
 
    GstPad * out_pad, GstCaps ** out_caps)
 
349
gst_video_max_rate_clamp_structure (GstStructure * s, gint maxrate,
 
350
    gint * min_num, gint * min_denom, gint * max_num, gint * max_denom)
209
351
{
210
 
  GstCaps *intersect;
211
 
  const GstCaps *in_templ;
212
 
  gint i;
213
 
  GSList *extra_structures = NULL;
214
 
  GSList *iter;
215
 
 
216
 
  in_templ = gst_pad_get_pad_template_caps (in_pad);
217
 
  intersect = gst_caps_intersect (in_caps, in_templ);
218
 
 
219
 
  /* all possible framerates are allowed */
220
 
  for (i = 0; i < gst_caps_get_size (intersect); i++) {
221
 
    GstStructure *structure;
222
 
 
223
 
    structure = gst_caps_get_structure (intersect, i);
224
 
 
225
 
    if (gst_structure_has_field (structure, "framerate")) {
226
 
      GstStructure *copy_structure;
227
 
 
228
 
      copy_structure = gst_structure_copy (structure);
229
 
      gst_structure_set (copy_structure,
230
 
          "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
231
 
      extra_structures = g_slist_append (extra_structures, copy_structure);
 
352
  gboolean ret = FALSE;
 
353
 
 
354
  if (!gst_structure_has_field (s, "framerate")) {
 
355
    /* No framerate field implies any framerate, clamping would result in
 
356
     * [1..max_rate] so not a real subset */
 
357
    goto out;
 
358
  } else {
 
359
    const GValue *v;
 
360
    GValue intersection = { 0, };
 
361
    GValue clamp = { 0, };
 
362
    gint tmp_num, tmp_denom;
 
363
 
 
364
    g_value_init (&clamp, GST_TYPE_FRACTION_RANGE);
 
365
    gst_value_set_fraction_range_full (&clamp, 0, 1, maxrate, 1);
 
366
 
 
367
    v = gst_structure_get_value (s, "framerate");
 
368
    ret = gst_value_intersect (&intersection, v, &clamp);
 
369
    g_value_unset (&clamp);
 
370
 
 
371
    if (!ret)
 
372
      goto out;
 
373
 
 
374
    gst_value_fraction_get_extremes (&intersection,
 
375
        min_num, min_denom, max_num, max_denom);
 
376
 
 
377
    gst_value_fraction_get_extremes (v,
 
378
        &tmp_num, &tmp_denom, max_num, max_denom);
 
379
 
 
380
    if (gst_util_fraction_compare (*max_num, *max_denom, maxrate, 1) > 0) {
 
381
      *max_num = maxrate;
 
382
      *max_denom = 1;
232
383
    }
233
 
  }
234
 
 
235
 
  /* append the extra structures */
236
 
  for (iter = extra_structures; iter != NULL; iter = g_slist_next (iter)) {
237
 
    gst_caps_append_structure (intersect, (GstStructure *) iter->data);
238
 
  }
239
 
  g_slist_free (extra_structures);
240
 
 
241
 
  *out_caps = intersect;
242
 
 
243
 
  return TRUE;
 
384
 
 
385
    gst_structure_take_value (s, "framerate", &intersection);
 
386
  }
 
387
 
 
388
out:
 
389
  return ret;
244
390
}
245
391
 
246
392
static GstCaps *
247
 
gst_video_rate_getcaps (GstPad * pad)
 
393
gst_video_rate_transform_caps (GstBaseTransform * trans,
 
394
    GstPadDirection direction, GstCaps * caps)
248
395
{
249
 
  GstVideoRate *videorate;
250
 
  GstPad *otherpad;
251
 
  GstCaps *caps;
252
 
 
253
 
  videorate = GST_VIDEO_RATE (GST_PAD_PARENT (pad));
254
 
 
255
 
  otherpad = (pad == videorate->srcpad) ? videorate->sinkpad :
256
 
      videorate->srcpad;
257
 
 
258
 
  /* we can do what the peer can */
259
 
  caps = gst_pad_peer_get_caps (otherpad);
260
 
  if (caps) {
261
 
    GstCaps *transform;
262
 
 
263
 
    gst_video_rate_transformcaps (otherpad, caps, pad, &transform);
264
 
    gst_caps_unref (caps);
265
 
    caps = transform;
 
396
  GstVideoRate *videorate = GST_VIDEO_RATE (trans);
 
397
  GstCaps *ret;
 
398
  GstStructure *s, *s2;
 
399
  GstStructure *s3 = NULL;
 
400
  int maxrate = g_atomic_int_get (&videorate->max_rate);
 
401
 
 
402
  /* Should always be called with simple caps */
 
403
  g_return_val_if_fail (GST_CAPS_IS_SIMPLE (caps), NULL);
 
404
 
 
405
  ret = gst_caps_copy (caps);
 
406
 
 
407
  s = gst_caps_get_structure (ret, 0);
 
408
  s2 = gst_structure_copy (s);
 
409
 
 
410
  if (videorate->force_fps_n >= 0 && videorate->force_fps_d >= 0) {
 
411
    if (direction == GST_PAD_SINK) {
 
412
      gst_caps_remove_structure (ret, 0);
 
413
      gst_structure_set (s2, "framerate", GST_TYPE_FRACTION,
 
414
          videorate->force_fps_n, videorate->force_fps_d, NULL);
 
415
    } else {
 
416
      gst_structure_set (s2, "framerate", GST_TYPE_FRACTION_RANGE, 0, 1,
 
417
          G_MAXINT, 1, NULL);
 
418
    }
 
419
  } else if (videorate->drop_only) {
 
420
    gint min_num = 0, min_denom = 1;
 
421
    gint max_num = G_MAXINT, max_denom = 1;
 
422
 
 
423
    /* Clamp the caps to our maximum rate as the first caps if possible */
 
424
    if (!gst_video_max_rate_clamp_structure (s, maxrate,
 
425
            &min_num, &min_denom, &max_num, &max_denom)) {
 
426
      min_num = 0;
 
427
      min_denom = 1;
 
428
      max_num = maxrate;
 
429
      max_denom = 1;
 
430
 
 
431
      /* clamp wouldn't be a real subset of 1..maxrate, in this case the sink
 
432
       * caps should become [1..maxrate], [1..maxint] and the src caps just
 
433
       * [1..maxrate].  In case there was a caps incompatibility things will
 
434
       * explode later as appropriate :)
 
435
       *
 
436
       * In case [X..maxrate] == [X..maxint], skip as we'll set it later
 
437
       */
 
438
      if (direction == GST_PAD_SRC && maxrate != G_MAXINT)
 
439
        gst_structure_set (s, "framerate", GST_TYPE_FRACTION_RANGE,
 
440
            min_num, min_denom, maxrate, 1, NULL);
 
441
      else
 
442
        gst_caps_remove_structure (ret, 0);
 
443
    }
 
444
 
 
445
    if (direction == GST_PAD_SRC) {
 
446
      /* We can accept anything as long as it's at least the minimal framerate
 
447
       * the the sink needs */
 
448
      gst_structure_set (s2, "framerate", GST_TYPE_FRACTION_RANGE,
 
449
          min_num, min_denom, G_MAXINT, 1, NULL);
 
450
 
 
451
      /* Also allow unknown framerate, if it isn't already */
 
452
      if (min_num != 0 || min_denom != 1) {
 
453
        s3 = gst_structure_copy (s);
 
454
        gst_structure_set (s3, "framerate", GST_TYPE_FRACTION, 0, 1, NULL);
 
455
      }
 
456
    } else if (max_num != 0 || max_denom != 1) {
 
457
      /* We can provide everything upto the maximum framerate at the src */
 
458
      gst_structure_set (s2, "framerate", GST_TYPE_FRACTION_RANGE,
 
459
          0, 1, max_num, max_denom, NULL);
 
460
    }
 
461
  } else if (direction == GST_PAD_SINK) {
 
462
    gint min_num = 0, min_denom = 1;
 
463
    gint max_num = G_MAXINT, max_denom = 1;
 
464
 
 
465
    if (!gst_video_max_rate_clamp_structure (s, maxrate,
 
466
            &min_num, &min_denom, &max_num, &max_denom))
 
467
      gst_caps_remove_structure (ret, 0);
 
468
 
 
469
    gst_structure_set (s2, "framerate", GST_TYPE_FRACTION_RANGE, 0, 1,
 
470
        maxrate, 1, NULL);
266
471
  } else {
267
 
    /* no peer, our padtemplate is enough then */
268
 
    caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
 
472
    /* set the framerate as a range */
 
473
    gst_structure_set (s2, "framerate", GST_TYPE_FRACTION_RANGE, 0, 1,
 
474
        G_MAXINT, 1, NULL);
269
475
  }
270
476
 
271
 
  return caps;
 
477
  gst_caps_merge_structure (ret, s2);
 
478
  if (s3 != NULL)
 
479
    gst_caps_merge_structure (ret, s3);
 
480
 
 
481
  return ret;
 
482
}
 
483
 
 
484
static void
 
485
gst_video_rate_fixate_caps (GstBaseTransform * trans,
 
486
    GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
 
487
{
 
488
  GstStructure *s;
 
489
  gint num, denom;
 
490
 
 
491
  s = gst_caps_get_structure (caps, 0);
 
492
  if (G_UNLIKELY (!gst_structure_get_fraction (s, "framerate", &num, &denom)))
 
493
    return;
 
494
 
 
495
  s = gst_caps_get_structure (othercaps, 0);
 
496
  gst_structure_fixate_field_nearest_fraction (s, "framerate", num, denom);
272
497
}
273
498
 
274
499
static gboolean
275
 
gst_video_rate_setcaps (GstPad * pad, GstCaps * caps)
 
500
gst_video_rate_setcaps (GstBaseTransform * trans, GstCaps * in_caps,
 
501
    GstCaps * out_caps)
276
502
{
277
503
  GstVideoRate *videorate;
278
504
  GstStructure *structure;
279
505
  gboolean ret = TRUE;
280
 
  GstPad *otherpad, *opeer;
281
506
  gint rate_numerator, rate_denominator;
282
507
 
283
 
  videorate = GST_VIDEO_RATE (gst_pad_get_parent (pad));
284
 
 
285
 
  GST_DEBUG_OBJECT (pad, "setcaps called %" GST_PTR_FORMAT, caps);
286
 
 
287
 
  structure = gst_caps_get_structure (caps, 0);
288
 
  if (!gst_structure_get_fraction (structure, "framerate",
289
 
          &rate_numerator, &rate_denominator))
290
 
    goto no_framerate;
291
 
 
292
 
  if (pad == videorate->srcpad) {
293
 
    /* out_frame_count is scaled by the frame rate caps when calculating next_ts.
294
 
     * when the frame rate caps change, we must update base_ts and reset
295
 
     * out_frame_count */
296
 
    if (videorate->to_rate_numerator) {
297
 
      videorate->base_ts +=
298
 
          gst_util_uint64_scale (videorate->out_frame_count,
299
 
          videorate->to_rate_denominator * GST_SECOND,
300
 
          videorate->to_rate_numerator);
301
 
    }
302
 
    videorate->out_frame_count = 0;
303
 
    videorate->to_rate_numerator = rate_numerator;
304
 
    videorate->to_rate_denominator = rate_denominator;
305
 
    otherpad = videorate->sinkpad;
306
 
  } else {
307
 
    videorate->from_rate_numerator = rate_numerator;
308
 
    videorate->from_rate_denominator = rate_denominator;
309
 
    otherpad = videorate->srcpad;
310
 
  }
311
 
 
312
 
  /* now try to find something for the peer */
313
 
  opeer = gst_pad_get_peer (otherpad);
314
 
  if (opeer) {
315
 
    if (gst_pad_accept_caps (opeer, caps)) {
316
 
      /* the peer accepts the caps as they are */
317
 
      gst_pad_set_caps (otherpad, caps);
318
 
 
319
 
      ret = TRUE;
320
 
    } else {
321
 
      GstCaps *peercaps;
322
 
      GstCaps *transform = NULL;
323
 
 
324
 
      ret = FALSE;
325
 
 
326
 
      /* see how we can transform the input caps */
327
 
      if (!gst_video_rate_transformcaps (pad, caps, otherpad, &transform))
328
 
        goto no_transform;
329
 
 
330
 
      /* see what the peer can do */
331
 
      peercaps = gst_pad_get_caps (opeer);
332
 
 
333
 
      GST_DEBUG_OBJECT (opeer, "icaps %" GST_PTR_FORMAT, peercaps);
334
 
      GST_DEBUG_OBJECT (videorate, "transform %" GST_PTR_FORMAT, transform);
335
 
 
336
 
      /* filter against our possibilities */
337
 
      caps = gst_caps_intersect (peercaps, transform);
338
 
      gst_caps_unref (peercaps);
339
 
      gst_caps_unref (transform);
340
 
 
341
 
      GST_DEBUG_OBJECT (videorate, "intersect %" GST_PTR_FORMAT, caps);
342
 
 
343
 
      /* could turn up empty, due to e.g. colorspace etc */
344
 
      if (gst_caps_get_size (caps) == 0) {
345
 
        gst_caps_unref (caps);
346
 
        goto no_transform;
347
 
      }
348
 
 
349
 
      /* take first possibility */
350
 
      gst_caps_truncate (caps);
351
 
      structure = gst_caps_get_structure (caps, 0);
352
 
 
353
 
      /* and fixate */
354
 
      gst_structure_fixate_field_nearest_fraction (structure, "framerate",
355
 
          rate_numerator, rate_denominator);
356
 
 
357
 
      gst_structure_get_fraction (structure, "framerate",
358
 
          &rate_numerator, &rate_denominator);
359
 
 
360
 
      if (otherpad == videorate->srcpad) {
361
 
        videorate->to_rate_numerator = rate_numerator;
362
 
        videorate->to_rate_denominator = rate_denominator;
363
 
      } else {
364
 
        videorate->from_rate_numerator = rate_numerator;
365
 
        videorate->from_rate_denominator = rate_denominator;
366
 
      }
367
 
 
368
 
      if (gst_structure_has_field (structure, "interlaced"))
369
 
        gst_structure_fixate_field_boolean (structure, "interlaced", FALSE);
370
 
      if (gst_structure_has_field (structure, "color-matrix"))
371
 
        gst_structure_fixate_field_string (structure, "color-matrix", "sdtv");
372
 
      if (gst_structure_has_field (structure, "chroma-site"))
373
 
        gst_structure_fixate_field_string (structure, "chroma-site", "mpeg2");
374
 
      if (gst_structure_has_field (structure, "pixel-aspect-ratio"))
375
 
        gst_structure_fixate_field_nearest_fraction (structure,
376
 
            "pixel-aspect-ratio", 1, 1);
377
 
 
378
 
      gst_pad_set_caps (otherpad, caps);
379
 
      gst_caps_unref (caps);
380
 
      ret = TRUE;
381
 
    }
382
 
    gst_object_unref (opeer);
383
 
  }
 
508
  videorate = GST_VIDEO_RATE (trans);
 
509
 
 
510
  GST_DEBUG_OBJECT (trans, "setcaps called in: %" GST_PTR_FORMAT
 
511
      " out: %" GST_PTR_FORMAT, in_caps, out_caps);
 
512
 
 
513
  structure = gst_caps_get_structure (in_caps, 0);
 
514
  if (!gst_structure_get_fraction (structure, "framerate",
 
515
          &rate_numerator, &rate_denominator))
 
516
    goto no_framerate;
 
517
 
 
518
  videorate->from_rate_numerator = rate_numerator;
 
519
  videorate->from_rate_denominator = rate_denominator;
 
520
 
 
521
  structure = gst_caps_get_structure (out_caps, 0);
 
522
  if (!gst_structure_get_fraction (structure, "framerate",
 
523
          &rate_numerator, &rate_denominator))
 
524
    goto no_framerate;
 
525
 
 
526
  /* out_frame_count is scaled by the frame rate caps when calculating next_ts.
 
527
   * when the frame rate caps change, we must update base_ts and reset
 
528
   * out_frame_count */
 
529
  if (videorate->to_rate_numerator) {
 
530
    videorate->base_ts +=
 
531
        gst_util_uint64_scale (videorate->out_frame_count,
 
532
        videorate->to_rate_denominator * GST_SECOND,
 
533
        videorate->to_rate_numerator);
 
534
  }
 
535
  videorate->out_frame_count = 0;
 
536
  videorate->to_rate_numerator = rate_numerator;
 
537
  videorate->to_rate_denominator = rate_denominator;
 
538
 
 
539
  if (rate_numerator)
 
540
    videorate->wanted_diff = gst_util_uint64_scale_int (GST_SECOND,
 
541
        rate_denominator, rate_numerator);
 
542
  else
 
543
    videorate->wanted_diff = 0;
 
544
 
384
545
done:
385
546
  /* After a setcaps, our caps may have changed. In that case, we can't use
386
547
   * the old buffer, if there was one (it might have different dimensions) */
387
548
  GST_DEBUG_OBJECT (videorate, "swapping old buffers");
388
549
  gst_video_rate_swap_prev (videorate, NULL, GST_CLOCK_TIME_NONE);
 
550
  videorate->last_ts = GST_CLOCK_TIME_NONE;
 
551
  videorate->average = 0;
389
552
 
390
 
  gst_object_unref (videorate);
391
553
  return ret;
392
554
 
393
555
no_framerate:
394
556
  {
395
557
    GST_DEBUG_OBJECT (videorate, "no framerate specified");
396
 
    goto done;
397
 
  }
398
 
no_transform:
399
 
  {
400
 
    GST_DEBUG_OBJECT (videorate, "no framerate transform possible");
401
558
    ret = FALSE;
402
559
    goto done;
403
560
  }
417
574
  videorate->next_ts = GST_CLOCK_TIME_NONE;
418
575
  videorate->last_ts = GST_CLOCK_TIME_NONE;
419
576
  videorate->discont = TRUE;
 
577
  videorate->average = 0;
420
578
  gst_video_rate_swap_prev (videorate, NULL, 0);
421
579
 
422
580
  gst_segment_init (&videorate->segment, GST_FORMAT_TIME);
425
583
static void
426
584
gst_video_rate_init (GstVideoRate * videorate, GstVideoRateClass * klass)
427
585
{
428
 
  videorate->sinkpad =
429
 
      gst_pad_new_from_static_template (&gst_video_rate_sink_template, "sink");
430
 
  gst_pad_set_event_function (videorate->sinkpad,
431
 
      GST_DEBUG_FUNCPTR (gst_video_rate_event));
432
 
  gst_pad_set_chain_function (videorate->sinkpad,
433
 
      GST_DEBUG_FUNCPTR (gst_video_rate_chain));
434
 
  gst_pad_set_getcaps_function (videorate->sinkpad,
435
 
      GST_DEBUG_FUNCPTR (gst_video_rate_getcaps));
436
 
  gst_pad_set_setcaps_function (videorate->sinkpad,
437
 
      GST_DEBUG_FUNCPTR (gst_video_rate_setcaps));
438
 
  gst_element_add_pad (GST_ELEMENT (videorate), videorate->sinkpad);
439
 
 
440
 
  videorate->srcpad =
441
 
      gst_pad_new_from_static_template (&gst_video_rate_src_template, "src");
442
 
  gst_pad_set_query_function (videorate->srcpad,
443
 
      GST_DEBUG_FUNCPTR (gst_video_rate_query));
444
 
  gst_pad_set_getcaps_function (videorate->srcpad,
445
 
      GST_DEBUG_FUNCPTR (gst_video_rate_getcaps));
446
 
  gst_pad_set_setcaps_function (videorate->srcpad,
447
 
      GST_DEBUG_FUNCPTR (gst_video_rate_setcaps));
448
 
  gst_element_add_pad (GST_ELEMENT (videorate), videorate->srcpad);
449
 
 
450
586
  gst_video_rate_reset (videorate);
451
587
  videorate->silent = DEFAULT_SILENT;
452
588
  videorate->new_pref = DEFAULT_NEW_PREF;
 
589
  videorate->drop_only = DEFAULT_DROP_ONLY;
 
590
  videorate->average_period = DEFAULT_AVERAGE_PERIOD;
 
591
  videorate->average_period_set = DEFAULT_AVERAGE_PERIOD;
 
592
  videorate->max_rate = DEFAULT_MAX_RATE;
 
593
  videorate->force_fps_n = DEFAULT_FORCE_FPS_N;
 
594
  videorate->force_fps_d = DEFAULT_FORCE_FPS_D;
453
595
 
454
596
  videorate->from_rate_numerator = 0;
455
597
  videorate->from_rate_denominator = 0;
456
598
  videorate->to_rate_numerator = 0;
457
599
  videorate->to_rate_denominator = 0;
 
600
 
 
601
  gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (videorate), TRUE);
458
602
}
459
603
 
460
604
/* flush the oldest buffer */
501
645
    GST_BUFFER_DURATION (outbuf) = videorate->next_ts - push_ts;
502
646
  }
503
647
 
504
 
  /* adapt for looping, bring back to time in current segment. */
505
 
  GST_BUFFER_TIMESTAMP (outbuf) = push_ts - videorate->segment.accum;
506
 
 
507
 
  gst_buffer_set_caps (outbuf, GST_PAD_CAPS (videorate->srcpad));
 
648
  /* We do not need to update time in VFR (variable frame rate) mode */
 
649
  if (!videorate->drop_only) {
 
650
    /* adapt for looping, bring back to time in current segment. */
 
651
    GST_BUFFER_TIMESTAMP (outbuf) = push_ts - videorate->segment.accum;
 
652
  }
508
653
 
509
654
  GST_LOG_OBJECT (videorate,
510
655
      "old is best, dup, pushing buffer outgoing ts %" GST_TIME_FORMAT,
511
656
      GST_TIME_ARGS (push_ts));
512
657
 
513
 
  res = gst_pad_push (videorate->srcpad, outbuf);
 
658
  res = gst_pad_push (GST_BASE_TRANSFORM_SRC_PAD (videorate), outbuf);
514
659
 
515
660
  return res;
516
661
 
529
674
  GST_LOG_OBJECT (videorate, "swap_prev: storing buffer %p in prev", buffer);
530
675
  if (videorate->prevbuf)
531
676
    gst_buffer_unref (videorate->prevbuf);
532
 
  videorate->prevbuf = buffer;
 
677
  videorate->prevbuf = buffer != NULL ? gst_buffer_ref (buffer) : NULL;
533
678
  videorate->prev_ts = time;
534
679
}
535
680
 
555
700
 
556
701
#define MAGIC_LIMIT  25
557
702
static gboolean
558
 
gst_video_rate_event (GstPad * pad, GstEvent * event)
 
703
gst_video_rate_event (GstBaseTransform * trans, GstEvent * event)
559
704
{
560
705
  GstVideoRate *videorate;
561
 
  gboolean ret;
562
706
 
563
 
  videorate = GST_VIDEO_RATE (gst_pad_get_parent (pad));
 
707
  videorate = GST_VIDEO_RATE (trans);
564
708
 
565
709
  switch (GST_EVENT_TYPE (event)) {
566
710
    case GST_EVENT_NEWSEGMENT:
677
821
      break;
678
822
  }
679
823
 
680
 
  ret = gst_pad_push_event (videorate->srcpad, event);
681
 
 
682
 
done:
683
 
  gst_object_unref (videorate);
684
 
 
685
 
  return ret;
 
824
  return TRUE;
686
825
 
687
826
  /* ERRORS */
688
827
format_error:
689
828
  {
690
829
    GST_WARNING_OBJECT (videorate,
691
830
        "Got segment but doesn't have GST_FORMAT_TIME value");
692
 
    gst_event_unref (event);
693
 
    ret = FALSE;
694
 
    goto done;
 
831
    return FALSE;
695
832
  }
696
833
}
697
834
 
698
835
static gboolean
699
 
gst_video_rate_query (GstPad * pad, GstQuery * query)
 
836
gst_video_rate_query (GstBaseTransform * trans, GstPadDirection direction,
 
837
    GstQuery * query)
700
838
{
701
 
  GstVideoRate *videorate;
 
839
  GstVideoRate *videorate = GST_VIDEO_RATE (trans);
702
840
  gboolean res = FALSE;
 
841
  GstPad *otherpad;
703
842
 
704
 
  videorate = GST_VIDEO_RATE (gst_pad_get_parent (pad));
 
843
  otherpad = (direction == GST_PAD_SRC) ?
 
844
      GST_BASE_TRANSFORM_SINK_PAD (trans) : GST_BASE_TRANSFORM_SRC_PAD (trans);
705
845
 
706
846
  switch (GST_QUERY_TYPE (query)) {
707
847
    case GST_QUERY_LATENCY:
709
849
      GstClockTime min, max;
710
850
      gboolean live;
711
851
      guint64 latency;
 
852
      guint64 avg_period;
712
853
      GstPad *peer;
713
854
 
714
 
      if ((peer = gst_pad_get_peer (videorate->sinkpad))) {
 
855
      GST_OBJECT_LOCK (videorate);
 
856
      avg_period = videorate->average_period_set;
 
857
      GST_OBJECT_UNLOCK (videorate);
 
858
 
 
859
      if (avg_period == 0 && (peer = gst_pad_get_peer (otherpad))) {
715
860
        if ((res = gst_pad_query (peer, query))) {
716
861
          gst_query_parse_latency (query, &live, &min, &max);
717
862
 
745
890
          gst_query_set_latency (query, live, min, max);
746
891
        }
747
892
        gst_object_unref (peer);
 
893
        break;
748
894
      }
749
 
      break;
 
895
      /* Simple fallthrough if we don't have a latency or not a peer that we
 
896
       * can't ask about its latency yet.. */
750
897
    }
751
898
    default:
752
 
      res = gst_pad_query_default (pad, query);
 
899
      res = parent_class->query (trans, direction, query);
753
900
      break;
754
901
  }
755
 
  gst_object_unref (videorate);
756
902
 
757
903
  return res;
758
904
}
759
905
 
760
906
static GstFlowReturn
761
 
gst_video_rate_chain (GstPad * pad, GstBuffer * buffer)
 
907
gst_video_rate_trans_ip_max_avg (GstVideoRate * videorate, GstBuffer * buf)
 
908
{
 
909
  GstClockTime ts = GST_BUFFER_TIMESTAMP (buf);
 
910
 
 
911
  videorate->in++;
 
912
 
 
913
  if (!GST_CLOCK_TIME_IS_VALID (ts) || videorate->wanted_diff == 0)
 
914
    goto push;
 
915
 
 
916
  /* drop frames if they exceed our output rate */
 
917
  if (GST_CLOCK_TIME_IS_VALID (videorate->last_ts)) {
 
918
    GstClockTimeDiff diff = ts - videorate->last_ts;
 
919
 
 
920
    /* Drop buffer if its early compared to the desired frame rate and
 
921
     * the current average is higher than the desired average
 
922
     */
 
923
    if (diff < videorate->wanted_diff &&
 
924
        videorate->average < videorate->wanted_diff)
 
925
      goto drop;
 
926
 
 
927
    /* Update average */
 
928
    if (videorate->average) {
 
929
      GstClockTimeDiff wanted_diff;
 
930
 
 
931
      if (G_LIKELY (videorate->average_period > videorate->wanted_diff))
 
932
        wanted_diff = videorate->wanted_diff;
 
933
      else
 
934
        wanted_diff = videorate->average_period * 10;
 
935
 
 
936
      videorate->average =
 
937
          gst_util_uint64_scale_round (videorate->average,
 
938
          videorate->average_period - wanted_diff,
 
939
          videorate->average_period) +
 
940
          gst_util_uint64_scale_round (diff, wanted_diff,
 
941
          videorate->average_period);
 
942
    } else {
 
943
      videorate->average = diff;
 
944
    }
 
945
  }
 
946
 
 
947
  videorate->last_ts = ts;
 
948
 
 
949
push:
 
950
  videorate->out++;
 
951
  return GST_FLOW_OK;
 
952
 
 
953
drop:
 
954
  if (!videorate->silent)
 
955
    gst_video_rate_notify_drop (videorate);
 
956
  return GST_BASE_TRANSFORM_FLOW_DROPPED;
 
957
}
 
958
 
 
959
static GstFlowReturn
 
960
gst_video_rate_prepare_output_buffer (GstBaseTransform * trans,
 
961
    GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf)
 
962
{
 
963
  if (gst_buffer_is_metadata_writable (input)) {
 
964
    gst_buffer_set_caps (input, caps);
 
965
    *buf = gst_buffer_ref (input);
 
966
  } else {
 
967
    *buf = gst_buffer_create_sub (input, 0, GST_BUFFER_SIZE (input));
 
968
    gst_buffer_set_caps (*buf, caps);
 
969
  }
 
970
 
 
971
  return GST_FLOW_OK;
 
972
}
 
973
 
 
974
static GstFlowReturn
 
975
gst_video_rate_transform_ip (GstBaseTransform * trans, GstBuffer * buffer)
762
976
{
763
977
  GstVideoRate *videorate;
764
 
  GstFlowReturn res = GST_FLOW_OK;
 
978
  GstFlowReturn res = GST_BASE_TRANSFORM_FLOW_DROPPED;
765
979
  GstClockTime intime, in_ts, in_dur;
 
980
  GstClockTime avg_period;
 
981
  gboolean skip = FALSE;
766
982
 
767
 
  videorate = GST_VIDEO_RATE (GST_PAD_PARENT (pad));
 
983
  videorate = GST_VIDEO_RATE (trans);
768
984
 
769
985
  /* make sure the denominators are not 0 */
770
986
  if (videorate->from_rate_denominator == 0 ||
771
987
      videorate->to_rate_denominator == 0)
772
988
    goto not_negotiated;
773
989
 
 
990
  GST_OBJECT_LOCK (videorate);
 
991
  avg_period = videorate->average_period_set;
 
992
  GST_OBJECT_UNLOCK (videorate);
 
993
 
 
994
  /* MT-safe switching between modes */
 
995
  if (G_UNLIKELY (avg_period != videorate->average_period)) {
 
996
    gboolean switch_mode = (avg_period == 0 || videorate->average_period == 0);
 
997
    videorate->average_period = avg_period;
 
998
    videorate->last_ts = GST_CLOCK_TIME_NONE;
 
999
 
 
1000
    if (switch_mode) {
 
1001
      if (avg_period) {
 
1002
        /* enabling average mode */
 
1003
        videorate->average = 0;
 
1004
        /* make sure no cached buffers from regular mode are left */
 
1005
        gst_video_rate_swap_prev (videorate, NULL, 0);
 
1006
      } else {
 
1007
        /* enable regular mode */
 
1008
        videorate->next_ts = GST_CLOCK_TIME_NONE;
 
1009
        skip = TRUE;
 
1010
      }
 
1011
 
 
1012
      /* max averaging mode has a no latency, normal mode does */
 
1013
      gst_element_post_message (GST_ELEMENT (videorate),
 
1014
          gst_message_new_latency (GST_OBJECT (videorate)));
 
1015
    }
 
1016
  }
 
1017
 
 
1018
  if (videorate->average_period > 0)
 
1019
    return gst_video_rate_trans_ip_max_avg (videorate, buffer);
 
1020
 
774
1021
  in_ts = GST_BUFFER_TIMESTAMP (buffer);
775
1022
  in_dur = GST_BUFFER_DURATION (buffer);
776
1023
 
800
1047
    if (!GST_CLOCK_TIME_IS_VALID (videorate->next_ts)) {
801
1048
      /* new buffer, we expect to output a buffer that matches the first
802
1049
       * timestamp in the segment */
803
 
      if (videorate->skip_to_first) {
 
1050
      if (videorate->skip_to_first || skip) {
804
1051
        videorate->next_ts = intime;
805
1052
        videorate->base_ts = in_ts - videorate->segment.start;
806
1053
        videorate->out_frame_count = 0;
833
1080
      videorate->drop++;
834
1081
      if (!videorate->silent)
835
1082
        gst_video_rate_notify_drop (videorate);
836
 
      gst_buffer_unref (buffer);
837
1083
      goto done;
838
1084
    }
839
1085
 
857
1103
 
858
1104
      /* output first one when its the best */
859
1105
      if (diff1 <= diff2) {
 
1106
        GstFlowReturn r;
860
1107
        count++;
861
1108
 
862
1109
        /* on error the _flush function posted a warning already */
863
 
        if ((res =
864
 
                gst_video_rate_flush_prev (videorate,
 
1110
        if ((r = gst_video_rate_flush_prev (videorate,
865
1111
                    count > 1)) != GST_FLOW_OK) {
866
 
          gst_buffer_unref (buffer);
 
1112
          res = r;
867
1113
          goto done;
868
1114
        }
869
1115
      }
 
1116
 
 
1117
      /* Do not produce any dups. We can exit loop now */
 
1118
      if (videorate->drop_only)
 
1119
        break;
870
1120
      /* continue while the first one was the best, if they were equal avoid
871
1121
       * going into an infinite loop */
872
1122
    }
907
1157
not_negotiated:
908
1158
  {
909
1159
    GST_WARNING_OBJECT (videorate, "no framerate negotiated");
910
 
    gst_buffer_unref (buffer);
911
1160
    res = GST_FLOW_NOT_NEGOTIATED;
912
1161
    goto done;
913
1162
  }
916
1165
  {
917
1166
    GST_WARNING_OBJECT (videorate,
918
1167
        "Got buffer with GST_CLOCK_TIME_NONE timestamp, discarding it");
919
 
    gst_buffer_unref (buffer);
 
1168
    res = GST_BASE_TRANSFORM_FLOW_DROPPED;
920
1169
    goto done;
921
1170
  }
922
1171
}
923
1172
 
 
1173
static gboolean
 
1174
gst_video_rate_start (GstBaseTransform * trans)
 
1175
{
 
1176
  gst_video_rate_reset (GST_VIDEO_RATE (trans));
 
1177
  return TRUE;
 
1178
}
 
1179
 
 
1180
static gboolean
 
1181
gst_video_rate_stop (GstBaseTransform * trans)
 
1182
{
 
1183
  gst_video_rate_reset (GST_VIDEO_RATE (trans));
 
1184
  return TRUE;
 
1185
}
 
1186
 
924
1187
static void
925
1188
gst_video_rate_set_property (GObject * object,
926
1189
    guint prop_id, const GValue * value, GParamSpec * pspec)
927
1190
{
928
1191
  GstVideoRate *videorate = GST_VIDEO_RATE (object);
929
1192
 
 
1193
  GST_OBJECT_LOCK (videorate);
930
1194
  switch (prop_id) {
931
 
    case ARG_SILENT:
 
1195
    case PROP_SILENT:
932
1196
      videorate->silent = g_value_get_boolean (value);
933
1197
      break;
934
 
    case ARG_NEW_PREF:
 
1198
    case PROP_NEW_PREF:
935
1199
      videorate->new_pref = g_value_get_double (value);
936
1200
      break;
937
 
    case ARG_SKIP_TO_FIRST:
 
1201
    case PROP_SKIP_TO_FIRST:
938
1202
      videorate->skip_to_first = g_value_get_boolean (value);
939
1203
      break;
 
1204
    case PROP_DROP_ONLY:
 
1205
      videorate->drop_only = g_value_get_boolean (value);
 
1206
      goto reconfigure;
 
1207
      break;
 
1208
    case PROP_AVERAGE_PERIOD:
 
1209
      videorate->average_period_set = g_value_get_uint64 (value);
 
1210
      break;
 
1211
    case PROP_MAX_RATE:
 
1212
      g_atomic_int_set (&videorate->max_rate, g_value_get_int (value));
 
1213
      goto reconfigure;
 
1214
      break;
 
1215
    case PROP_FORCE_FPS:
 
1216
      videorate->force_fps_n = gst_value_get_fraction_numerator (value);
 
1217
      videorate->force_fps_d = gst_value_get_fraction_denominator (value);
 
1218
      goto reconfigure;
 
1219
      break;
940
1220
    default:
941
1221
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
942
1222
      break;
943
1223
  }
 
1224
  GST_OBJECT_UNLOCK (videorate);
 
1225
  return;
 
1226
 
 
1227
reconfigure:
 
1228
  GST_OBJECT_UNLOCK (videorate);
 
1229
  gst_base_transform_reconfigure (GST_BASE_TRANSFORM (videorate));
944
1230
}
945
1231
 
946
1232
static void
949
1235
{
950
1236
  GstVideoRate *videorate = GST_VIDEO_RATE (object);
951
1237
 
 
1238
  GST_OBJECT_LOCK (videorate);
952
1239
  switch (prop_id) {
953
 
    case ARG_IN:
 
1240
    case PROP_IN:
954
1241
      g_value_set_uint64 (value, videorate->in);
955
1242
      break;
956
 
    case ARG_OUT:
 
1243
    case PROP_OUT:
957
1244
      g_value_set_uint64 (value, videorate->out);
958
1245
      break;
959
 
    case ARG_DUP:
 
1246
    case PROP_DUP:
960
1247
      g_value_set_uint64 (value, videorate->dup);
961
1248
      break;
962
 
    case ARG_DROP:
 
1249
    case PROP_DROP:
963
1250
      g_value_set_uint64 (value, videorate->drop);
964
1251
      break;
965
 
    case ARG_SILENT:
 
1252
    case PROP_SILENT:
966
1253
      g_value_set_boolean (value, videorate->silent);
967
1254
      break;
968
 
    case ARG_NEW_PREF:
 
1255
    case PROP_NEW_PREF:
969
1256
      g_value_set_double (value, videorate->new_pref);
970
1257
      break;
971
 
    case ARG_SKIP_TO_FIRST:
 
1258
    case PROP_SKIP_TO_FIRST:
972
1259
      g_value_set_boolean (value, videorate->skip_to_first);
973
1260
      break;
 
1261
    case PROP_DROP_ONLY:
 
1262
      g_value_set_boolean (value, videorate->drop_only);
 
1263
      break;
 
1264
    case PROP_AVERAGE_PERIOD:
 
1265
      g_value_set_uint64 (value, videorate->average_period_set);
 
1266
      break;
 
1267
    case PROP_MAX_RATE:
 
1268
      g_value_set_int (value, g_atomic_int_get (&videorate->max_rate));
 
1269
      break;
 
1270
    case PROP_FORCE_FPS:
 
1271
      gst_value_set_fraction (value, videorate->force_fps_n,
 
1272
          videorate->force_fps_d);
 
1273
      break;
974
1274
    default:
975
1275
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
976
1276
      break;
977
1277
  }
978
 
}
979
 
 
980
 
static GstStateChangeReturn
981
 
gst_video_rate_change_state (GstElement * element, GstStateChange transition)
982
 
{
983
 
  GstStateChangeReturn ret;
984
 
  GstVideoRate *videorate;
985
 
 
986
 
  videorate = GST_VIDEO_RATE (element);
987
 
 
988
 
  switch (transition) {
989
 
    case GST_STATE_CHANGE_READY_TO_PAUSED:
990
 
      videorate->discont = TRUE;
991
 
      videorate->last_ts = -1;
992
 
      break;
993
 
    default:
994
 
      break;
995
 
  }
996
 
 
997
 
  ret = parent_class->change_state (element, transition);
998
 
 
999
 
  switch (transition) {
1000
 
    case GST_STATE_CHANGE_PAUSED_TO_READY:
1001
 
      gst_video_rate_reset (videorate);
1002
 
      break;
1003
 
    default:
1004
 
      break;
1005
 
  }
1006
 
 
1007
 
  return ret;
 
1278
  GST_OBJECT_UNLOCK (videorate);
1008
1279
}
1009
1280
 
1010
1281
static gboolean