1 /*
2 * gstrtponviftimestamp-parse.c
3 *
4 * Copyright (C) 2014 Axis Communications AB
5 * Author: Guillaume Desmottes <guillaume.desmottes@collabora.com>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include <gst/rtp/gstrtpbuffer.h>
30
31 #include "gstrtponvifparse.h"
32
33 static GstFlowReturn gst_rtp_onvif_parse_chain (GstPad * pad,
34 GstObject * parent, GstBuffer * buf);
35
36 static GstStaticPadTemplate sink_template_factory =
37 GST_STATIC_PAD_TEMPLATE ("sink",
38 GST_PAD_SINK,
39 GST_PAD_ALWAYS,
40 GST_STATIC_CAPS ("application/x-rtp")
41 );
42
43 static GstStaticPadTemplate src_template_factory =
44 GST_STATIC_PAD_TEMPLATE ("src",
45 GST_PAD_SRC,
46 GST_PAD_ALWAYS,
47 GST_STATIC_CAPS ("application/x-rtp")
48 );
49
50 G_DEFINE_TYPE (GstRtpOnvifParse, gst_rtp_onvif_parse, GST_TYPE_ELEMENT);
51
52 static void
gst_rtp_onvif_parse_class_init(GstRtpOnvifParseClass * klass)53 gst_rtp_onvif_parse_class_init (GstRtpOnvifParseClass * klass)
54 {
55 GstElementClass *gstelement_class;
56
57 gstelement_class = GST_ELEMENT_CLASS (klass);
58
59 /* register pads */
60 gst_element_class_add_static_pad_template (gstelement_class,
61 &sink_template_factory);
62 gst_element_class_add_static_pad_template (gstelement_class,
63 &src_template_factory);
64
65 gst_element_class_set_static_metadata (gstelement_class,
66 "ONVIF NTP timestamps RTP extension", "Effect/RTP",
67 "Add absolute timestamps and flags of recorded data in a playback "
68 "session", "Guillaume Desmottes <guillaume.desmottes@collabora.com>");
69 }
70
71 static void
gst_rtp_onvif_parse_init(GstRtpOnvifParse * self)72 gst_rtp_onvif_parse_init (GstRtpOnvifParse * self)
73 {
74 self->sinkpad =
75 gst_pad_new_from_static_template (&sink_template_factory, "sink");
76 gst_pad_set_chain_function (self->sinkpad, gst_rtp_onvif_parse_chain);
77 gst_element_add_pad (GST_ELEMENT (self), self->sinkpad);
78 GST_PAD_SET_PROXY_CAPS (self->sinkpad);
79
80 self->srcpad =
81 gst_pad_new_from_static_template (&src_template_factory, "src");
82 gst_element_add_pad (GST_ELEMENT (self), self->srcpad);
83 }
84
85 #define EXTENSION_ID 0xABAC
86 #define EXTENSION_SIZE 3
87
88 static gboolean
handle_buffer(GstRtpOnvifParse * self,GstBuffer * buf)89 handle_buffer (GstRtpOnvifParse * self, GstBuffer * buf)
90 {
91 GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
92 guint8 *data;
93 guint16 bits;
94 guint wordlen;
95 guint8 flags;
96 /*
97 guint64 timestamp;
98 guint8 cseq;
99 */
100
101 if (!gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp)) {
102 GST_ELEMENT_ERROR (self, STREAM, FAILED,
103 ("Failed to map RTP buffer"), (NULL));
104 return FALSE;
105 }
106
107 /* Check if the ONVIF RTP extension is present in the packet */
108 if (!gst_rtp_buffer_get_extension_data (&rtp, &bits, (gpointer) & data,
109 &wordlen))
110 goto out;
111
112 if (bits != EXTENSION_ID || wordlen != EXTENSION_SIZE)
113 goto out;
114
115 /* timestamp = GST_READ_UINT64_BE (data); TODO */
116 flags = GST_READ_UINT8 (data + 8);
117 /* cseq = GST_READ_UINT8 (data + 9); TODO */
118
119 /* C */
120 if (flags & (1 << 7))
121 GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
122 else
123 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
124
125 /* E */
126 /* if (flags & (1 << 6)); TODO */
127
128 /* D */
129 if (flags & (1 << 5))
130 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
131 else
132 GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
133
134 out:
135 gst_rtp_buffer_unmap (&rtp);
136 return TRUE;
137 }
138
139 static GstFlowReturn
gst_rtp_onvif_parse_chain(GstPad * pad,GstObject * parent,GstBuffer * buf)140 gst_rtp_onvif_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
141 {
142 GstRtpOnvifParse *self = GST_RTP_ONVIF_PARSE (parent);
143
144 if (!handle_buffer (self, buf)) {
145 gst_buffer_unref (buf);
146 return GST_FLOW_ERROR;
147 }
148
149 return gst_pad_push (self->srcpad, buf);
150 }
151