1 /* GStreamer
2 * Copyright (C) 2015 Sebastian Dröge <sebastian@centricular.com>
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., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #include "gstrtputils.h"
21
22 typedef struct
23 {
24 GstElement *element;
25 GstBuffer *outbuf;
26 GQuark copy_tag;
27 } CopyMetaData;
28
29 GQuark rtp_quark_meta_tag_video;
30 GQuark rtp_quark_meta_tag_audio;
31
32 static gboolean
foreach_metadata_copy(GstBuffer * inbuf,GstMeta ** meta,gpointer user_data)33 foreach_metadata_copy (GstBuffer * inbuf, GstMeta ** meta, gpointer user_data)
34 {
35 CopyMetaData *data = user_data;
36 GstElement *element = data->element;
37 GstBuffer *outbuf = data->outbuf;
38 GQuark copy_tag = data->copy_tag;
39 const GstMetaInfo *info = (*meta)->info;
40 const gchar *const *tags = gst_meta_api_type_get_tags (info->api);
41
42 if (!tags || (copy_tag != 0 && g_strv_length ((gchar **) tags) == 1
43 && gst_meta_api_type_has_tag (info->api, copy_tag))) {
44 GstMetaTransformCopy copy_data = { FALSE, 0, -1 };
45 GST_DEBUG_OBJECT (element, "copy metadata %s", g_type_name (info->api));
46 /* simply copy then */
47 info->transform_func (outbuf, *meta, inbuf,
48 _gst_meta_transform_copy, ©_data);
49 } else {
50 GST_DEBUG_OBJECT (element, "not copying metadata %s",
51 g_type_name (info->api));
52 }
53
54 return TRUE;
55 }
56
57 /* TODO: Should probably make copy_tag an array at some point */
58 void
gst_rtp_copy_meta(GstElement * element,GstBuffer * outbuf,GstBuffer * inbuf,GQuark copy_tag)59 gst_rtp_copy_meta (GstElement * element, GstBuffer * outbuf, GstBuffer * inbuf,
60 GQuark copy_tag)
61 {
62 CopyMetaData data = { element, outbuf, copy_tag };
63
64 gst_buffer_foreach_meta (inbuf, foreach_metadata_copy, &data);
65 }
66
67 void
gst_rtp_copy_video_meta(gpointer element,GstBuffer * outbuf,GstBuffer * inbuf)68 gst_rtp_copy_video_meta (gpointer element, GstBuffer * outbuf,
69 GstBuffer * inbuf)
70 {
71 gst_rtp_copy_meta (element, outbuf, inbuf, rtp_quark_meta_tag_video);
72 }
73
74 void
gst_rtp_copy_audio_meta(gpointer element,GstBuffer * outbuf,GstBuffer * inbuf)75 gst_rtp_copy_audio_meta (gpointer element, GstBuffer * outbuf,
76 GstBuffer * inbuf)
77 {
78 gst_rtp_copy_meta (element, outbuf, inbuf, rtp_quark_meta_tag_audio);
79 }
80
81 typedef struct
82 {
83 GstElement *element;
84 GQuark keep_tag;
85 } DropMetaData;
86
87 static gboolean
foreach_metadata_drop(GstBuffer * inbuf,GstMeta ** meta,gpointer user_data)88 foreach_metadata_drop (GstBuffer * inbuf, GstMeta ** meta, gpointer user_data)
89 {
90 DropMetaData *data = user_data;
91 GstElement *element = data->element;
92 GQuark keep_tag = data->keep_tag;
93 const GstMetaInfo *info = (*meta)->info;
94 const gchar *const *tags = gst_meta_api_type_get_tags (info->api);
95
96 if (!tags || (keep_tag != 0 && g_strv_length ((gchar **) tags) == 1
97 && gst_meta_api_type_has_tag (info->api, keep_tag))) {
98 GST_DEBUG_OBJECT (element, "keeping metadata %s", g_type_name (info->api));
99 } else {
100 GST_DEBUG_OBJECT (element, "dropping metadata %s", g_type_name (info->api));
101 *meta = NULL;
102 }
103
104 return TRUE;
105 }
106
107 /* TODO: Should probably make keep_tag an array at some point */
108 void
gst_rtp_drop_meta(GstElement * element,GstBuffer * buf,GQuark keep_tag)109 gst_rtp_drop_meta (GstElement * element, GstBuffer * buf, GQuark keep_tag)
110 {
111 DropMetaData data = { element, keep_tag };
112
113 gst_buffer_foreach_meta (buf, foreach_metadata_drop, &data);
114 }
115
116 void
gst_rtp_drop_non_audio_meta(gpointer element,GstBuffer * buf)117 gst_rtp_drop_non_audio_meta (gpointer element, GstBuffer * buf)
118 {
119 gst_rtp_drop_meta (element, buf, rtp_quark_meta_tag_audio);
120 }
121
122 void
gst_rtp_drop_non_video_meta(gpointer element,GstBuffer * buf)123 gst_rtp_drop_non_video_meta (gpointer element, GstBuffer * buf)
124 {
125 gst_rtp_drop_meta (element, buf, rtp_quark_meta_tag_video);
126 }
127
128 /* Stolen from bad/gst/mpegtsdemux/payloader_parsers.c */
129 /* variable length Exp-Golomb parsing according to H.265 spec section 9.2*/
130 gboolean
gst_rtp_read_golomb(GstBitReader * br,guint32 * value)131 gst_rtp_read_golomb (GstBitReader * br, guint32 * value)
132 {
133 guint8 b, leading_zeros = -1;
134 *value = 1;
135
136 for (b = 0; !b; leading_zeros++) {
137 if (!gst_bit_reader_get_bits_uint8 (br, &b, 1))
138 return FALSE;
139 *value *= 2;
140 }
141
142 *value = (*value >> 1) - 1;
143 if (leading_zeros > 0) {
144 guint32 tmp = 0;
145 if (!gst_bit_reader_get_bits_uint32 (br, &tmp, leading_zeros))
146 return FALSE;
147 *value += tmp;
148 }
149
150 return TRUE;
151 }
152