~ubuntu-branches/ubuntu/quantal/gst-plugins-bad-multiverse0.10/quantal

« back to all changes in this revision

Viewing changes to gst/asfmux/gstrtpasfpay.c

  • Committer: Bazaar Package Importer
  • Author(s): Onkar Shinde
  • Date: 2009-12-07 08:54:28 UTC
  • mfrom: (1.1.15 upstream)
  • Revision ID: james.westby@ubuntu.com-20091207085428-ml6aaukf0p2ph34d
Tags: 0.10.17-0ubuntu1
* New upstream release.
* Add myself to maintainer.
* Fix misc lintian warnings.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ASF RTP Payloader plugin for GStreamer
 
2
 * Copyright (C) 2009 Thiago Santos <thiagoss@embedded.ufcg.edu.br>
 
3
 *
 
4
 * This library is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU Library General Public
 
6
 * License as published by the Free Software Foundation; either
 
7
 * version 2 of the License, or (at your option) any later version.
 
8
 *
 
9
 * This library is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * Library General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU Library General Public
 
15
 * License along with this library; if not, write to the
 
16
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
17
 * Boston, MA 02111-1307, USA.
 
18
 */
 
19
 
 
20
/* FIXME
 
21
 * - this element doesn't follow (max/min) time properties,
 
22
 *   is it possible to do it with a container format?
 
23
 */
 
24
 
 
25
#ifdef HAVE_CONFIG_H
 
26
#  include "config.h"
 
27
#endif
 
28
 
 
29
#include <gst/rtp/gstrtpbuffer.h>
 
30
#include <string.h>
 
31
 
 
32
#include "gstrtpasfpay.h"
 
33
 
 
34
GST_DEBUG_CATEGORY_STATIC (rtpasfpay_debug);
 
35
#define GST_CAT_DEFAULT (rtpasfpay_debug)
 
36
 
 
37
/* elementfactory information */
 
38
static const GstElementDetails gst_rtp_asf_pay_details =
 
39
GST_ELEMENT_DETAILS ("RTP ASF payloader",
 
40
    "Codec/Payloader/Network",
 
41
    "Payload-encodes ASF into RTP packets (MS_RTSP)",
 
42
    "Thiago Santos <thiagoss@embedded.ufcg.edu.br>");
 
43
 
 
44
static GstStaticPadTemplate gst_rtp_asf_pay_sink_template =
 
45
GST_STATIC_PAD_TEMPLATE ("sink",
 
46
    GST_PAD_SINK,
 
47
    GST_PAD_ALWAYS,
 
48
    GST_STATIC_CAPS ("video/x-ms-asf, " "parsed = (boolean) true")
 
49
    );
 
50
 
 
51
static GstStaticPadTemplate gst_rtp_asf_pay_src_template =
 
52
GST_STATIC_PAD_TEMPLATE ("src",
 
53
    GST_PAD_SRC,
 
54
    GST_PAD_ALWAYS,
 
55
    GST_STATIC_CAPS ("application/x-rtp, "
 
56
        "media = (string) {\"audio\", \"video\", \"application\"}, "
 
57
        "clock-rate = (int) 1000, " "encoding-name = (string) \"X-ASF-PF\"")
 
58
    );
 
59
 
 
60
static GstFlowReturn
 
61
gst_rtp_asf_pay_handle_buffer (GstBaseRTPPayload * rtppay, GstBuffer * buffer);
 
62
static gboolean
 
63
gst_rtp_asf_pay_set_caps (GstBaseRTPPayload * rtppay, GstCaps * caps);
 
64
 
 
65
GST_BOILERPLATE (GstRtpAsfPay, gst_rtp_asf_pay, GstBaseRTPPayload,
 
66
    GST_TYPE_BASE_RTP_PAYLOAD);
 
67
 
 
68
static void
 
69
gst_rtp_asf_pay_init (GstRtpAsfPay * rtpasfpay, GstRtpAsfPayClass * klass)
 
70
{
 
71
  rtpasfpay->first_ts = 0;
 
72
  rtpasfpay->config = NULL;
 
73
  rtpasfpay->packets_count = 0;
 
74
  rtpasfpay->state = ASF_NOT_STARTED;
 
75
  rtpasfpay->headers = NULL;
 
76
  rtpasfpay->current = NULL;
 
77
}
 
78
 
 
79
static void
 
80
gst_rtp_asf_pay_finalize (GObject * object)
 
81
{
 
82
  GstRtpAsfPay *rtpasfpay;
 
83
  rtpasfpay = GST_RTP_ASF_PAY (object);
 
84
  g_free (rtpasfpay->config);
 
85
  if (rtpasfpay->headers)
 
86
    gst_buffer_unref (rtpasfpay->headers);
 
87
  G_OBJECT_CLASS (parent_class)->finalize (object);
 
88
}
 
89
 
 
90
static void
 
91
gst_rtp_asf_pay_base_init (gpointer klass)
 
92
{
 
93
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
 
94
 
 
95
  gst_element_class_add_pad_template (element_class,
 
96
      gst_static_pad_template_get (&gst_rtp_asf_pay_sink_template));
 
97
  gst_element_class_add_pad_template (element_class,
 
98
      gst_static_pad_template_get (&gst_rtp_asf_pay_src_template));
 
99
  gst_element_class_set_details (element_class, &gst_rtp_asf_pay_details);
 
100
}
 
101
 
 
102
static void
 
103
gst_rtp_asf_pay_class_init (GstRtpAsfPayClass * klass)
 
104
{
 
105
  GObjectClass *gobject_class;
 
106
  GstBaseRTPPayloadClass *gstbasertppayload_class;
 
107
 
 
108
  gobject_class = (GObjectClass *) klass;
 
109
  gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass;
 
110
 
 
111
  gobject_class->finalize = gst_rtp_asf_pay_finalize;
 
112
 
 
113
  gstbasertppayload_class->handle_buffer = gst_rtp_asf_pay_handle_buffer;
 
114
  gstbasertppayload_class->set_caps = gst_rtp_asf_pay_set_caps;
 
115
 
 
116
  GST_DEBUG_CATEGORY_INIT (rtpasfpay_debug, "rtpasfpay", 0,
 
117
      "ASF RTP Payloader");
 
118
}
 
119
 
 
120
static gboolean
 
121
gst_rtp_asf_pay_set_caps (GstBaseRTPPayload * rtppay, GstCaps * caps)
 
122
{
 
123
  /* FIXME change application for the actual content */
 
124
  gst_basertppayload_set_options (rtppay, "application", TRUE, "X-ASF-PF",
 
125
      1000);
 
126
  return TRUE;
 
127
}
 
128
 
 
129
static GstFlowReturn
 
130
gst_rtp_asf_pay_handle_packet (GstRtpAsfPay * rtpasfpay, GstBuffer * buffer)
 
131
{
 
132
  GstBaseRTPPayload *rtppay;
 
133
  GstAsfPacketInfo *packetinfo;
 
134
  guint8 flags;
 
135
  guint8 *data;
 
136
  guint32 packet_util_size;
 
137
  guint32 packet_offset;
 
138
  guint32 size_left;
 
139
  GstFlowReturn ret = GST_FLOW_OK;
 
140
 
 
141
  rtppay = GST_BASE_RTP_PAYLOAD (rtpasfpay);
 
142
  packetinfo = &rtpasfpay->packetinfo;
 
143
 
 
144
  if (!gst_asf_parse_packet (buffer, packetinfo, TRUE)) {
 
145
    GST_ERROR_OBJECT (rtpasfpay, "Error while parsing asf packet");
 
146
    gst_buffer_unref (buffer);
 
147
    return GST_FLOW_ERROR;
 
148
  }
 
149
 
 
150
  if (packetinfo->packet_size == 0)
 
151
    packetinfo->packet_size = rtpasfpay->asfinfo.packet_size;
 
152
 
 
153
  GST_LOG_OBJECT (rtpasfpay, "Packet size: %" G_GUINT32_FORMAT
 
154
      ", padding: %" G_GUINT32_FORMAT, packetinfo->packet_size,
 
155
      packetinfo->padding);
 
156
 
 
157
  /* update padding field to 0 */
 
158
  if (packetinfo->padding > 0) {
 
159
    GstAsfPacketInfo info;
 
160
    /* find padding field offset */
 
161
    guint offset = packetinfo->err_cor_len + 2 +
 
162
        gst_asf_get_var_size_field_len (packetinfo->packet_field_type) +
 
163
        gst_asf_get_var_size_field_len (packetinfo->seq_field_type);
 
164
    buffer = gst_buffer_make_writable (buffer);
 
165
    switch (packetinfo->padd_field_type) {
 
166
      case ASF_FIELD_TYPE_DWORD:
 
167
        GST_WRITE_UINT32_LE (&(GST_BUFFER_DATA (buffer)[offset]), 0);
 
168
        break;
 
169
      case ASF_FIELD_TYPE_WORD:
 
170
        GST_WRITE_UINT16_LE (&(GST_BUFFER_DATA (buffer)[offset]), 0);
 
171
        break;
 
172
      case ASF_FIELD_TYPE_BYTE:
 
173
        GST_BUFFER_DATA (buffer)[offset] = 0;
 
174
        break;
 
175
      case ASF_FIELD_TYPE_NONE:
 
176
      default:
 
177
        break;
 
178
    }
 
179
    gst_asf_parse_packet (buffer, &info, FALSE);
 
180
  }
 
181
 
 
182
  packet_util_size = packetinfo->packet_size - packetinfo->padding;
 
183
  packet_offset = 0;
 
184
  while (packet_util_size > 0) {
 
185
    /* Even if we don't fill completely an output buffer we
 
186
     * push it when we add an fragment. Because it seems that
 
187
     * it is not possible to determine where a asf packet
 
188
     * fragment ends inside a rtp packet payload.
 
189
     * This flag tells us to push the packet.
 
190
     */
 
191
    gboolean force_push = FALSE;
 
192
 
 
193
    /* we have no output buffer pending, create one */
 
194
    if (rtpasfpay->current == NULL) {
 
195
      GST_LOG_OBJECT (rtpasfpay, "Creating new output buffer");
 
196
      rtpasfpay->current =
 
197
          gst_rtp_buffer_new_allocate_len (GST_BASE_RTP_PAYLOAD_MTU (rtpasfpay),
 
198
          0, 0);
 
199
      rtpasfpay->cur_off = gst_rtp_buffer_get_header_len (rtpasfpay->current);
 
200
      rtpasfpay->has_ts = FALSE;
 
201
      rtpasfpay->marker = FALSE;
 
202
    }
 
203
    data = GST_BUFFER_DATA (rtpasfpay->current) + rtpasfpay->cur_off;
 
204
    size_left = GST_BUFFER_SIZE (rtpasfpay->current) - rtpasfpay->cur_off;
 
205
 
 
206
    GST_DEBUG_OBJECT (rtpasfpay, "Input buffer bytes consumed: %"
 
207
        G_GUINT32_FORMAT "/%" G_GUINT32_FORMAT, packet_offset,
 
208
        GST_BUFFER_SIZE (buffer));
 
209
 
 
210
    GST_DEBUG_OBJECT (rtpasfpay, "Output rtpbuffer status");
 
211
    GST_DEBUG_OBJECT (rtpasfpay, "Current offset: %" G_GUINT32_FORMAT,
 
212
        rtpasfpay->cur_off);
 
213
    GST_DEBUG_OBJECT (rtpasfpay, "Size left: %" G_GUINT32_FORMAT, size_left);
 
214
    GST_DEBUG_OBJECT (rtpasfpay, "Has ts: %s",
 
215
        rtpasfpay->has_ts ? "yes" : "no");
 
216
    if (rtpasfpay->has_ts) {
 
217
      GST_DEBUG_OBJECT (rtpasfpay, "Ts: %" G_GUINT32_FORMAT, rtpasfpay->ts);
 
218
    }
 
219
 
 
220
    flags = 0;
 
221
    if (packetinfo->has_keyframe) {
 
222
      flags = flags | 0x80;
 
223
    }
 
224
    flags = flags | 0x20;       /* Relative timestamp is present */
 
225
 
 
226
    if (!rtpasfpay->has_ts) {
 
227
      /* this is the first asf packet, its send time is the 
 
228
       * rtp packet timestamp */
 
229
      rtpasfpay->has_ts = TRUE;
 
230
      rtpasfpay->ts = packetinfo->send_time;
 
231
    }
 
232
 
 
233
    if (GST_BUFFER_SIZE (rtpasfpay->current) - rtpasfpay->cur_off >=
 
234
        packet_util_size + 8) {
 
235
      /* enough space for the rest of the packet */
 
236
      if (packet_offset == 0) {
 
237
        flags = flags | 0x40;
 
238
        GST_WRITE_UINT24_BE (data + 1, packet_util_size);
 
239
      } else {
 
240
        GST_WRITE_UINT24_BE (data + 1, packet_offset);
 
241
        force_push = TRUE;
 
242
      }
 
243
      data[0] = flags;
 
244
      GST_WRITE_UINT32_BE (data + 4,
 
245
          (gint32) (packetinfo->send_time) - (gint32) rtpasfpay->ts);
 
246
      memcpy (data + 8, GST_BUFFER_DATA (buffer) + packet_offset,
 
247
          packet_util_size);
 
248
 
 
249
      /* updating status variables */
 
250
      rtpasfpay->cur_off += 8 + packet_util_size;
 
251
      size_left -= packet_util_size + 8;
 
252
      packet_offset += packet_util_size;
 
253
      packet_util_size = 0;
 
254
      rtpasfpay->marker = TRUE;
 
255
    } else {
 
256
      /* fragment packet */
 
257
      data[0] = flags;
 
258
      GST_WRITE_UINT24_BE (data + 1, packet_offset);
 
259
      GST_WRITE_UINT32_BE (data + 4,
 
260
          (gint32) (packetinfo->send_time) - (gint32) rtpasfpay->ts);
 
261
      memcpy (data + 8, GST_BUFFER_DATA (buffer) + packet_offset,
 
262
          size_left - 8);
 
263
 
 
264
      /* updating status variables */
 
265
      rtpasfpay->cur_off += size_left;
 
266
      packet_offset += size_left - 8;
 
267
      packet_util_size -= size_left - 8;
 
268
      size_left = 0;
 
269
      force_push = TRUE;
 
270
    }
 
271
 
 
272
    /* there is not enough room for any more buffers */
 
273
    if (force_push || size_left <= 8) {
 
274
 
 
275
      if (size_left != 0) {
 
276
        /* trim remaining bytes not used */
 
277
        GstBuffer *aux = gst_buffer_create_sub (rtpasfpay->current, 0,
 
278
            GST_BUFFER_SIZE (rtpasfpay->current) - size_left);
 
279
        gst_buffer_unref (rtpasfpay->current);
 
280
        rtpasfpay->current = aux;
 
281
      }
 
282
      gst_rtp_buffer_set_ssrc (rtpasfpay->current, rtppay->current_ssrc);
 
283
      gst_rtp_buffer_set_marker (rtpasfpay->current, rtpasfpay->marker);
 
284
      gst_rtp_buffer_set_payload_type (rtpasfpay->current,
 
285
          GST_BASE_RTP_PAYLOAD_PT (rtppay));
 
286
      gst_rtp_buffer_set_seq (rtpasfpay->current, rtppay->seqnum + 1);
 
287
      gst_rtp_buffer_set_timestamp (rtpasfpay->current, packetinfo->send_time);
 
288
 
 
289
      GST_BUFFER_TIMESTAMP (rtpasfpay->current) = GST_BUFFER_TIMESTAMP (buffer);
 
290
 
 
291
      gst_buffer_set_caps (rtpasfpay->current,
 
292
          GST_PAD_CAPS (GST_BASE_RTP_PAYLOAD_SRCPAD (rtppay)));
 
293
 
 
294
      rtppay->seqnum++;
 
295
      rtppay->timestamp = packetinfo->send_time;
 
296
 
 
297
      GST_DEBUG_OBJECT (rtpasfpay, "Pushing rtp buffer");
 
298
      ret =
 
299
          gst_pad_push (GST_BASE_RTP_PAYLOAD_SRCPAD (rtppay),
 
300
          rtpasfpay->current);
 
301
      rtpasfpay->current = NULL;
 
302
      if (ret != GST_FLOW_OK) {
 
303
        gst_buffer_unref (buffer);
 
304
        return ret;
 
305
      }
 
306
    }
 
307
  }
 
308
  gst_buffer_unref (buffer);
 
309
  return ret;
 
310
}
 
311
 
 
312
static GstFlowReturn
 
313
gst_rtp_asf_pay_parse_headers (GstRtpAsfPay * rtpasfpay)
 
314
{
 
315
  GstFlowReturn ret = GST_FLOW_OK;
 
316
  gchar *maxps;
 
317
  g_return_val_if_fail (rtpasfpay->headers, GST_FLOW_ERROR);
 
318
 
 
319
  if (!gst_asf_parse_headers (rtpasfpay->headers, &rtpasfpay->asfinfo))
 
320
    goto error;
 
321
 
 
322
  GST_DEBUG_OBJECT (rtpasfpay, "Packets number: %" G_GUINT64_FORMAT,
 
323
      rtpasfpay->asfinfo.packets_count);
 
324
  GST_DEBUG_OBJECT (rtpasfpay, "Packets size: %" G_GUINT32_FORMAT,
 
325
      rtpasfpay->asfinfo.packet_size);
 
326
  GST_DEBUG_OBJECT (rtpasfpay, "Broadcast mode: %s",
 
327
      rtpasfpay->asfinfo.broadcast ? "true" : "false");
 
328
 
 
329
  /* get the config for caps */
 
330
  g_free (rtpasfpay->config);
 
331
  rtpasfpay->config = g_base64_encode (GST_BUFFER_DATA (rtpasfpay->headers),
 
332
      GST_BUFFER_SIZE (rtpasfpay->headers));
 
333
  GST_DEBUG_OBJECT (rtpasfpay, "Serialized headers to base64 string %s",
 
334
      rtpasfpay->config);
 
335
 
 
336
  g_assert (rtpasfpay->config != NULL);
 
337
  GST_DEBUG_OBJECT (rtpasfpay, "Setting optional caps values: maxps=%"
 
338
      G_GUINT32_FORMAT " and config=%s", rtpasfpay->asfinfo.packet_size,
 
339
      rtpasfpay->config);
 
340
  maxps =
 
341
      g_strdup_printf ("%" G_GUINT32_FORMAT, rtpasfpay->asfinfo.packet_size);
 
342
  gst_basertppayload_set_outcaps (GST_BASE_RTP_PAYLOAD (rtpasfpay), "maxps",
 
343
      G_TYPE_STRING, maxps, "config", G_TYPE_STRING, rtpasfpay->config, NULL);
 
344
  g_free (maxps);
 
345
 
 
346
  return GST_FLOW_OK;
 
347
 
 
348
error:
 
349
  ret = GST_FLOW_ERROR;
 
350
  GST_ERROR_OBJECT (rtpasfpay, "Error while parsing headers");
 
351
  return GST_FLOW_ERROR;
 
352
}
 
353
 
 
354
static GstFlowReturn
 
355
gst_rtp_asf_pay_handle_buffer (GstBaseRTPPayload * rtppay, GstBuffer * buffer)
 
356
{
 
357
  GstRtpAsfPay *rtpasfpay = GST_RTP_ASF_PAY_CAST (rtppay);
 
358
 
 
359
  if (G_UNLIKELY (rtpasfpay->state == ASF_END)) {
 
360
    GST_LOG_OBJECT (rtpasfpay,
 
361
        "Dropping buffer as we already pushed all packets");
 
362
    gst_buffer_unref (buffer);
 
363
    return GST_FLOW_UNEXPECTED; /* we already finished our job */
 
364
  }
 
365
 
 
366
  /* receive headers 
 
367
   * we only accept if they are in a single buffer */
 
368
  if (G_UNLIKELY (rtpasfpay->state == ASF_NOT_STARTED)) {
 
369
    guint64 header_size;
 
370
 
 
371
    if (GST_BUFFER_SIZE (buffer) < 24) {        /* guid+object size size */
 
372
      GST_ERROR_OBJECT (rtpasfpay,
 
373
          "Buffer too small, smaller than a Guid and object size");
 
374
      gst_buffer_unref (buffer);
 
375
      return GST_FLOW_ERROR;
 
376
    }
 
377
 
 
378
    header_size = gst_asf_match_and_peek_obj_size (GST_BUFFER_DATA (buffer),
 
379
        &(guids[ASF_HEADER_OBJECT_INDEX]));
 
380
    if (header_size > 0) {
 
381
      GST_DEBUG_OBJECT (rtpasfpay, "ASF header guid received, size %"
 
382
          G_GUINT64_FORMAT, header_size);
 
383
 
 
384
      if (GST_BUFFER_SIZE (buffer) < header_size) {
 
385
        GST_ERROR_OBJECT (rtpasfpay, "Headers should be contained in a single"
 
386
            " buffer");
 
387
        gst_buffer_unref (buffer);
 
388
        return GST_FLOW_ERROR;
 
389
      } else {
 
390
        rtpasfpay->state = ASF_DATA_OBJECT;
 
391
 
 
392
        /* clear previous headers, if any */
 
393
        if (rtpasfpay->headers) {
 
394
          gst_buffer_unref (rtpasfpay->headers);
 
395
        }
 
396
 
 
397
        GST_DEBUG_OBJECT (rtpasfpay, "Storing headers");
 
398
        if (GST_BUFFER_SIZE (buffer) == header_size) {
 
399
          rtpasfpay->headers = buffer;
 
400
          return GST_FLOW_OK;
 
401
        } else {
 
402
          /* headers are a subbuffer of thie buffer */
 
403
          GstBuffer *aux = gst_buffer_create_sub (buffer, header_size,
 
404
              GST_BUFFER_SIZE (buffer) - header_size);
 
405
          rtpasfpay->headers = gst_buffer_create_sub (buffer, 0, header_size);
 
406
          gst_buffer_replace (&buffer, aux);
 
407
        }
 
408
      }
 
409
    } else {
 
410
      GST_ERROR_OBJECT (rtpasfpay, "Missing ASF header start");
 
411
      gst_buffer_unref (buffer);
 
412
      return GST_FLOW_ERROR;
 
413
    }
 
414
  }
 
415
 
 
416
  if (G_UNLIKELY (rtpasfpay->state == ASF_DATA_OBJECT)) {
 
417
    if (GST_BUFFER_SIZE (buffer) != ASF_DATA_OBJECT_SIZE) {
 
418
      GST_ERROR_OBJECT (rtpasfpay, "Received buffer of different size of "
 
419
          "the data object header");
 
420
      gst_buffer_unref (buffer);
 
421
      return GST_FLOW_ERROR;
 
422
    }
 
423
 
 
424
    if (gst_asf_match_guid (GST_BUFFER_DATA (buffer),
 
425
            &(guids[ASF_DATA_OBJECT_INDEX]))) {
 
426
      GST_DEBUG_OBJECT (rtpasfpay, "Received data object header");
 
427
      rtpasfpay->headers = gst_buffer_join (rtpasfpay->headers, buffer);
 
428
      rtpasfpay->state = ASF_PACKETS;
 
429
 
 
430
      return gst_rtp_asf_pay_parse_headers (rtpasfpay);
 
431
    } else {
 
432
      GST_ERROR_OBJECT (rtpasfpay, "Unexpected object received (was expecting "
 
433
          "data object)");
 
434
      gst_buffer_unref (buffer);
 
435
      return GST_FLOW_ERROR;
 
436
    }
 
437
  }
 
438
 
 
439
  if (G_LIKELY (rtpasfpay->state == ASF_PACKETS)) {
 
440
    /* in broadcast mode we can't trust the packets count information
 
441
     * from the headers
 
442
     * We assume that if this is on broadcast mode it is a live stream
 
443
     * and we are going to keep receiving packets indefinitely
 
444
     */
 
445
    if (rtpasfpay->asfinfo.broadcast ||
 
446
        rtpasfpay->packets_count < rtpasfpay->asfinfo.packets_count) {
 
447
      GST_DEBUG_OBJECT (rtpasfpay, "Received packet %"
 
448
          G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT,
 
449
          rtpasfpay->packets_count, rtpasfpay->asfinfo.packets_count);
 
450
      rtpasfpay->packets_count++;
 
451
      return gst_rtp_asf_pay_handle_packet (rtpasfpay, buffer);
 
452
    } else {
 
453
      GST_INFO_OBJECT (rtpasfpay, "Packets ended");
 
454
      rtpasfpay->state = ASF_END;
 
455
      gst_buffer_unref (buffer);
 
456
      return GST_FLOW_UNEXPECTED;
 
457
    }
 
458
  }
 
459
 
 
460
  gst_buffer_unref (buffer);
 
461
  return GST_FLOW_OK;
 
462
}
 
463
 
 
464
gboolean
 
465
gst_rtp_asf_pay_plugin_init (GstPlugin * plugin)
 
466
{
 
467
  return gst_element_register (plugin, "rtpasfpay",
 
468
      GST_RANK_NONE, GST_TYPE_RTP_ASF_PAY);
 
469
}