3 * Copyright (C) 2007 Alessandro Decina
6 * Alessandro Decina <alessandro@nnva.org>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
30 #define GST_CAT_DEFAULT cam_debug_cat
35 * if (size_indicator == 0)
37 * else if (size_indicator == 1) {
39 * for (i=0; i<length_field_size; i++) {
47 cam_calc_length_field_size (guint length)
51 if (length < G_MAXUINT8)
53 else if (length <= G_MAXUINT16)
55 else if (length <= (1 << 24) - 1)
63 /* write a length_field */
65 cam_write_length_field (guint8 * buff, guint length)
67 guint8 field_len = cam_calc_length_field_size (length);
75 g_return_val_if_reached (0);
78 buff[0] = TPDU_HEADER_SIZE_INDICATOR | (field_len - 1);
79 buff[1] = length >> 8;
80 buff[2] = length & 0xFF;
83 buff[0] = TPDU_HEADER_SIZE_INDICATOR | (field_len - 1);
84 buff[1] = length >> 16;
85 buff[2] = (length >> 8) & 0xFF;
86 buff[3] = length & 0xFF;
89 buff[0] = TPDU_HEADER_SIZE_INDICATOR | (field_len - 1);
90 buff[1] = length >> 24;
91 buff[2] = (length >> 16) & 0xFF;
92 buff[3] = (length >> 8) & 0xFF;
93 buff[4] = length & 0xFF;
96 g_return_val_if_reached (0);
103 /* read a length_field */
105 cam_read_length_field (guint8 * buff, guint * length)
111 if (buff[0] <= G_MAXINT8) {
115 field_len = buff[0] & ~TPDU_HEADER_SIZE_INDICATOR;
117 GST_ERROR ("length_field length exceeds 4 bytes: %d", field_len);
122 for (i = 0; i < field_len; ++i)
123 len = (len << 8) | *++buff;
125 /* count the size indicator byte */
138 * ca_pmt_tag 24 uimsbf
140 * ca_pmt_list_management 8 uimsbf
141 * program_number 16 uimsbf
143 * version_number 5 uimsbf
144 * current_next_indicator 1 bslbf
146 * program_info_length 12 uimsbf
147 * if (program_info_length != 0) {
148 * ca_pmt_cmd_id at program level 8 uimsbf
149 * for (i=0; i<n; i++) {
150 * CA_descriptor() programme level
153 * for (i=0; i<n; i++) {
154 * stream_type 8 uimsbf
156 * elementary_PID elementary stream PID 13 uimsbf
158 * ES_info_length 12 uimsbf
159 * if (ES_info_length != 0) {
160 * ca_pmt_cmd_id at ES level 8 uimsbf
161 * for (i=0; i<n; i++) {
162 * CA_descriptor() elementary stream level
170 get_ca_descriptors_length (GValueArray * descriptors)
177 if (descriptors != NULL) {
178 for (i = 0; i < descriptors->n_values; ++i) {
179 value = g_value_array_get_nth (descriptors, i);
180 desc = (GString *) g_value_get_boxed (value);
182 if (desc->str[0] == 0x09)
191 write_ca_descriptors (guint8 * body, GValueArray * descriptors)
197 if (descriptors != NULL) {
198 for (i = 0; i < descriptors->n_values; ++i) {
199 value = g_value_array_get_nth (descriptors, i);
200 desc = (GString *) g_value_get_boxed (value);
202 if (desc->str[0] == 0x09) {
203 memcpy (body, desc->str, desc->len);
213 cam_build_ca_pmt (GstStructure * pmt, guint8 list_management, guint8 cmd_id,
219 GList *lengths = NULL;
221 const GValue *streams;
222 guint program_number;
223 guint version_number;
226 GstStructure *stream;
227 GValueArray *program_descriptors = NULL;
228 GValueArray *stream_descriptors = NULL;
230 gst_structure_get_uint (pmt, "program-number", &program_number);
231 gst_structure_get_uint (pmt, "version-number", &version_number);
232 streams = gst_structure_get_value (pmt, "streams");
233 value = gst_structure_get_value (pmt, "descriptors");
235 program_descriptors = g_value_get_boxed (value);
236 /* get the length of program level CA_descriptor()s */
237 len = get_ca_descriptors_length (program_descriptors);
239 /* add one byte for the program level cmd_id */
242 lengths = g_list_append (lengths, GINT_TO_POINTER (len));
243 body_size += 6 + len;
245 /* get the length of stream level CA_descriptor()s */
246 if (streams != NULL) {
247 for (i = 0; i < gst_value_list_get_size (streams); ++i) {
248 value = gst_value_list_get_value (streams, i);
249 stream = g_value_get_boxed (value);
251 value = gst_structure_get_value (stream, "descriptors");
253 stream_descriptors = g_value_get_boxed (value);
255 len = get_ca_descriptors_length (stream_descriptors);
257 /* one byte for the stream level cmd_id */
261 lengths = g_list_append (lengths, GINT_TO_POINTER (len));
262 body_size += 5 + len;
266 buffer = g_malloc0 (body_size);
269 *body++ = list_management;
271 GST_WRITE_UINT16_BE (body, program_number);
274 *body++ = (version_number << 1) | 0x01;
276 len = GPOINTER_TO_INT (lengths->data);
277 lengths = g_list_delete_link (lengths, lengths);
278 GST_WRITE_UINT16_BE (body, len);
284 body = write_ca_descriptors (body, program_descriptors);
287 for (i = 0; i < gst_value_list_get_size (streams); ++i) {
291 value = gst_value_list_get_value (streams, i);
292 stream = g_value_get_boxed (value);
294 gst_structure_get_uint (stream, "stream-type", &stream_type);
295 gst_structure_get_uint (stream, "pid", &stream_pid);
296 value = gst_structure_get_value (stream, "descriptors");
297 stream_descriptors = g_value_get_boxed (value);
299 *body++ = stream_type;
300 GST_WRITE_UINT16_BE (body, stream_pid);
302 len = GPOINTER_TO_INT (lengths->data);
303 lengths = g_list_delete_link (lengths, lengths);
304 GST_WRITE_UINT16_BE (body, len);
309 body = write_ca_descriptors (body, stream_descriptors);