add rtponvifextract element

https://bugzilla.gnome.org/show_bug.cgi?id=731769
This commit is contained in:
Guillaume Desmottes 2014-06-05 15:06:33 +02:00 committed by Olivier Crête
parent b424b72df1
commit 189005184c
5 changed files with 314 additions and 2 deletions

View file

@ -2,7 +2,8 @@ plugin_LTLIBRARIES = libgstrtponvif.la
libgstrtponvif_la_SOURCES = \ libgstrtponvif_la_SOURCES = \
gstrtponvif.c \ gstrtponvif.c \
gstrtponviftimestamp.c gstrtponviftimestamp.h gstrtponviftimestamp.c gstrtponviftimestamp.h \
gstrtponvifparse.c gstonvifparse.h
libgstrtponvif_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ libgstrtponvif_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \
$(GST_BASE_CFLAGS) $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS)
libgstrtponvif_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \ libgstrtponvif_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \

View file

@ -25,6 +25,7 @@
#include <gst/gst.h> #include <gst/gst.h>
#include "gstrtponviftimestamp.h" #include "gstrtponviftimestamp.h"
#include "gstrtponvifparse.h"
static gboolean static gboolean
plugin_init (GstPlugin * plugin) plugin_init (GstPlugin * plugin)
@ -32,6 +33,9 @@ plugin_init (GstPlugin * plugin)
if (!gst_element_register (plugin, "rtponviftimestamp", GST_RANK_NONE, if (!gst_element_register (plugin, "rtponviftimestamp", GST_RANK_NONE,
GST_TYPE_RTP_ONVIF_TIMESTAMP)) GST_TYPE_RTP_ONVIF_TIMESTAMP))
return FALSE; return FALSE;
if (!gst_element_register (plugin, "rtponvifparse", GST_RANK_NONE,
GST_TYPE_RTP_ONVIF_PARSE))
return FALSE;
return TRUE; return TRUE;
} }

View file

@ -0,0 +1,150 @@
/*
* gstrtponviftimestamp-parse.c
*
* Copyright (C) 2014 Axis Communications AB
* Author: Guillaume Desmottes <guillaume.desmottes@collabora.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gst/rtp/gstrtpbuffer.h>
#include "gstrtponvifparse.h"
static GstFlowReturn gst_rtp_onvif_parse_chain (GstPad * pad,
GstObject * parent, GstBuffer * buf);
static GstStaticPadTemplate sink_template_factory =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("application/x-rtp")
);
static GstStaticPadTemplate src_template_factory =
GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("application/x-rtp")
);
G_DEFINE_TYPE (GstRtpOnvifParse, gst_rtp_onvif_parse, GST_TYPE_ELEMENT);
static void
gst_rtp_onvif_parse_class_init (GstRtpOnvifParseClass * klass)
{
GstElementClass *gstelement_class;
gstelement_class = GST_ELEMENT_CLASS (klass);
/* register pads */
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&sink_template_factory));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&src_template_factory));
gst_element_class_set_static_metadata (gstelement_class,
"ONVIF NTP timestamps RTP extension", "Effect/RTP",
"Add absolute timestamps and flags of recorded data in a playback "
"session", "Guillaume Desmottes <guillaume.desmottes@collabora.com>");
}
static void
gst_rtp_onvif_parse_init (GstRtpOnvifParse * self)
{
self->sinkpad =
gst_pad_new_from_static_template (&sink_template_factory, "sink");
gst_pad_set_chain_function (self->sinkpad, gst_rtp_onvif_parse_chain);
gst_element_add_pad (GST_ELEMENT (self), self->sinkpad);
GST_PAD_SET_PROXY_CAPS (self->sinkpad);
self->srcpad =
gst_pad_new_from_static_template (&src_template_factory, "src");
gst_element_add_pad (GST_ELEMENT (self), self->srcpad);
}
#define EXTENSION_ID 0xABAC
#define EXTENSION_SIZE 3
static gboolean
handle_buffer (GstRtpOnvifParse * self, GstBuffer * buf)
{
GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
guint8 *data;
guint16 bits;
guint wordlen;
guint8 flags;
/*
guint64 timestamp;
guint8 cseq;
*/
if (!gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp)) {
GST_ELEMENT_ERROR (self, STREAM, FAILED,
("Failed to map RTP buffer"), (NULL));
return FALSE;
}
/* Check if the ONVIF RTP extension is present in the packet */
if (!gst_rtp_buffer_get_extension_data (&rtp, &bits, (gpointer) & data,
&wordlen))
goto out;
if (bits != EXTENSION_ID || wordlen != EXTENSION_SIZE)
goto out;
/* timestamp = GST_READ_UINT64_BE (data); TODO */
flags = GST_READ_UINT8 (data + 8);
/* cseq = GST_READ_UINT8 (data + 9); TODO */
/* C */
if (flags & (1 << 7))
GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
else
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
/* E */
/* if (flags & (1 << 6)); TODO */
/* D */
if (flags & (1 << 5))
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
else
GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
out:
gst_rtp_buffer_unmap (&rtp);
return TRUE;
}
static GstFlowReturn
gst_rtp_onvif_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{
GstRtpOnvifParse *self = GST_RTP_ONVIF_PARSE (parent);
if (!handle_buffer (self, buf)) {
gst_buffer_unref (buf);
return GST_FLOW_ERROR;
}
return gst_pad_push (self->srcpad, buf);
}

View file

@ -0,0 +1,62 @@
/*
* gstrtponviftimestamp-parse.h
*
* Copyright (C) 2014 Axis Communications AB
* Author: Guillaume Desmottes <guillaume.desmottes@collabora.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GST_RTP_ONVIF_PARSE_H__
#define __GST_RTP_ONVIF_PARSE_H__
#include <gst/gst.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GST_TYPE_RTP_ONVIF_PARSE \
(gst_rtp_onvif_parse_get_type())
#define GST_RTP_ONVIF_PARSE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_ONVIF_PARSE,GstRtpOnvifParse))
#define GST_RTP_ONVIF_PARSE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_ONVIF_PARSE,GstRtpOnvifParseClass))
#define GST_IS_RTP_ONVIF_PARSE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_ONVIF_PARSE))
#define GST_IS_RTP_ONVIF_PARSE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_ONVIF_PARSE))
typedef struct _GstRtpOnvifParse GstRtpOnvifParse;
typedef struct _GstRtpOnvifParseClass GstRtpOnvifParseClass;
struct _GstRtpOnvifParse {
GstElement element;
/* pads */
GstPad *sinkpad,*srcpad;
};
struct _GstRtpOnvifParseClass {
GstElementClass parent_class;
};
GType gst_rtp_onvif_parse_get_type(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GST_RTP_ONVIF_PARSE_H__ */

View file

@ -326,12 +326,101 @@ GST_START_TEST (test_apply_e_bit)
GST_END_TEST; GST_END_TEST;
static GstElement *
setup_rtponvifparse (gboolean set_e_bit)
{
GstElement *parse;
GST_DEBUG ("setup_rtponvifparse");
parse = gst_check_setup_element ("rtponvifparse");
setup_element (parse);
return parse;
}
static void
cleanup_rtponvifparse (GstElement * parse)
{
GST_DEBUG ("cleanup_rtponvifparse");
cleanup_element (parse);
}
static void
test_parse (gboolean clean_point, gboolean discont)
{
GstElement *parse;
GstBuffer *rtp, *buf;
GstSegment segment;
parse = setup_rtponvifparse (FALSE);
rtp = gst_rtp_buffer_new_allocate (4, 0, 0);
buf = create_extension_buffer (rtp, clean_point, FALSE, discont);
gst_buffer_unref (rtp);
/* stream start */
fail_unless (gst_pad_push_event (mysrcpad,
gst_event_new_stream_start ("test")));
/* Push a segment */
gst_segment_init (&segment, GST_FORMAT_TIME);
fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)));
/* Push buffer */
fail_unless (gst_pad_push (mysrcpad, buf) == GST_FLOW_OK,
"failed pushing buffer");
g_assert_cmpuint (g_list_length (buffers), ==, 1);
buf = buffers->data;
if (clean_point)
g_assert (!GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT));
else
g_assert (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT));
if (discont)
g_assert (GST_BUFFER_IS_DISCONT (buf));
else
g_assert (!GST_BUFFER_IS_DISCONT (buf));
g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL);
g_list_free (buffers);
buffers = NULL;
ASSERT_OBJECT_REFCOUNT (parse, "rtponvifparse", 1);
cleanup_rtponvifparse (parse);
}
GST_START_TEST (test_parse_no_flag)
{
test_parse (FALSE, FALSE);
}
GST_END_TEST;
GST_START_TEST (test_parse_clean_point)
{
test_parse (TRUE, FALSE);
}
GST_END_TEST;
GST_START_TEST (test_parse_discont)
{
test_parse (FALSE, TRUE);
}
GST_END_TEST;
static Suite * static Suite *
onviftimestamp_suite (void) onviftimestamp_suite (void)
{ {
Suite *s = suite_create ("onviftimestamp"); Suite *s = suite_create ("onviftimestamp");
TCase *tc_chain = tcase_create ("apply"); TCase *tc_chain;
tc_chain = tcase_create ("apply");
suite_add_tcase (s, tc_chain); suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_apply_discont); tcase_add_test (tc_chain, test_apply_discont);
tcase_add_test (tc_chain, test_apply_not_discont); tcase_add_test (tc_chain, test_apply_not_discont);
@ -339,6 +428,12 @@ onviftimestamp_suite (void)
tcase_add_test (tc_chain, test_apply_no_e_bit); tcase_add_test (tc_chain, test_apply_no_e_bit);
tcase_add_test (tc_chain, test_apply_e_bit); tcase_add_test (tc_chain, test_apply_e_bit);
tc_chain = tcase_create ("parse");
suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_parse_no_flag);
tcase_add_test (tc_chain, test_parse_clean_point);
tcase_add_test (tc_chain, test_parse_discont);
return s; return s;
} }