~ubuntu-branches/ubuntu/precise/me-tv/precise-proposed

« back to all changes in this revision

Viewing changes to src/libucsi/section_buf.c

  • Committer: Bazaar Package Importer
  • Author(s): Philipp Kern
  • Date: 2008-07-23 14:03:56 UTC
  • mfrom: (1.1.3 upstream) (3.1.1 lenny)
  • Revision ID: james.westby@ubuntu.com-20080723140356-m6ze7fbkydes42c7
Tags: 0.5.33-3
Fix xine-lib ffmpeg dependency.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * section and descriptor parser
3
 
 *
4
 
 * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
5
 
 *
6
 
 * This library is free software; you can redistribute it and/or
7
 
 * modify it under the terms of the GNU Lesser General Public
8
 
 * License as published by the Free Software Foundation; either
9
 
 * version 2.1 of the License, or (at your option) any later version.
10
 
 *
11
 
 * This library is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 
 * Lesser General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU Lesser General Public
17
 
 * License along with this library; if not, write to the Free Software
18
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
19
 
 */
20
 
 
21
 
#include <errno.h>
22
 
#include <string.h>
23
 
#include "section_buf.h"
24
 
 
25
 
#define SECTION_HDR_SIZE 3
26
 
#define SECTION_PAD 0xff
27
 
 
28
 
int section_buf_init(struct section_buf *section, int max)
29
 
{
30
 
        if (max < SECTION_HDR_SIZE)
31
 
                return -EINVAL;
32
 
 
33
 
        memset(section, 0, sizeof(struct section_buf));
34
 
        section->max = max; /* max size of data */
35
 
        section->len = SECTION_HDR_SIZE;
36
 
        section->wait_pdu = 1;
37
 
 
38
 
        return 0;
39
 
}
40
 
 
41
 
int section_buf_add(struct section_buf *section, uint8_t* frag, int len, int *section_status)
42
 
{
43
 
        int copy;
44
 
        int used = 0;
45
 
        uint8_t *data;
46
 
        uint8_t *pos = (uint8_t*) section + sizeof(struct section_buf) + section->count;
47
 
 
48
 
        /* have we finished? */
49
 
        if (section->header && (section->len == section->count)) {
50
 
                *section_status = 1;
51
 
                return 0;
52
 
        }
53
 
 
54
 
        /* skip over section padding bytes */
55
 
        *section_status = 0;
56
 
        if (section->count == 0) {
57
 
                while(len && (*frag == SECTION_PAD)) {
58
 
                        frag++;
59
 
                        len--;
60
 
                        used++;
61
 
                }
62
 
 
63
 
                if (len == 0)
64
 
                        return used;
65
 
        }
66
 
 
67
 
        /* grab the header to get the section length */
68
 
        if (!section->header) {
69
 
                /* copy the header frag */
70
 
                copy = SECTION_HDR_SIZE - section->count;
71
 
                if (copy > len)
72
 
                        copy = len;
73
 
                memcpy(pos, frag, copy);
74
 
                section->count += copy;
75
 
                pos += copy;
76
 
                frag += copy;
77
 
                used += copy;
78
 
                len -= copy;
79
 
 
80
 
                /* we need 3 bytes for the section header */
81
 
                if (section->count != SECTION_HDR_SIZE)
82
 
                        return used;
83
 
 
84
 
                /* work out the length & check it isn't too big */
85
 
                data = (uint8_t*) section + sizeof(struct section_buf);
86
 
                section->len = SECTION_HDR_SIZE + (((data[1] & 0x0f) << 8) | data[2]);
87
 
                if (section->len > section->max) {
88
 
                        *section_status = -ERANGE;
89
 
                        return len + used;
90
 
                }
91
 
 
92
 
                /* update fields */
93
 
                section->header = 1;
94
 
        }
95
 
 
96
 
        /* accumulate frag */
97
 
        copy = section->len - section->count;
98
 
        if (copy > len)
99
 
                copy = len;
100
 
        memcpy(pos, frag, copy);
101
 
        section->count += copy;
102
 
        used += copy;
103
 
 
104
 
        /* have we finished? */
105
 
        if (section->header && (section->len == section->count))
106
 
                *section_status = 1;
107
 
 
108
 
        /* return number of bytes used */
109
 
        return used;
110
 
}
111
 
 
112
 
int section_buf_add_transport_payload(struct section_buf *section,
113
 
                                      uint8_t* payload, int len,
114
 
                                      int pdu_start, int *section_status)
115
 
{
116
 
        int used = 0;
117
 
        int tmp;
118
 
 
119
 
        /* have we finished? */
120
 
        if (section->header && (section->len == section->count)) {
121
 
                *section_status = 1;
122
 
                return 0;
123
 
        }
124
 
 
125
 
        /* don't bother if we're waiting for a PDU */
126
 
        *section_status = 0;
127
 
        if (section->wait_pdu && (!pdu_start))
128
 
                return len;
129
 
 
130
 
        /* if we're at a PDU start, we need extra handling for the extra first
131
 
         * byte giving the offset to the start of the next section. */
132
 
        if (pdu_start) {
133
 
                /* we have received a pdu */
134
 
                section->wait_pdu = 0;
135
 
 
136
 
                /* work out the offset to the _next_ payload */
137
 
                int offset = payload[0];
138
 
                if ((offset+1) > len) {
139
 
                        section->wait_pdu = 1;
140
 
                        *section_status = -EINVAL;
141
 
                        return len;
142
 
                }
143
 
 
144
 
                /* accumulate the end if we need to */
145
 
                if (section->count != 0) {
146
 
                        /* add the final fragment. */
147
 
                        tmp = section_buf_add(section, payload + 1, offset, section_status);
148
 
 
149
 
                        /* the stream said this was the final fragment
150
 
                         * (PDU START bit) - check that it really was! */
151
 
                        if ((tmp != offset) || section_buf_remaining(section) || (*section_status != 1)) {
152
 
                                *section_status = -ERANGE;
153
 
                                section->wait_pdu = 1;
154
 
                                return 1 + tmp;
155
 
                        }
156
 
 
157
 
                        /* it is complete - return the number of bytes we used */
158
 
                        return 1 + tmp;
159
 
                }
160
 
 
161
 
                /* otherwise, we skip the end of the previous section, and
162
 
                 * start accumulating the new data. */
163
 
                used = 1 + offset;
164
 
        }
165
 
 
166
 
        /* ok, just accumulate the data as normal */
167
 
        tmp = section_buf_add(section, payload+used, len - used, section_status);
168
 
        if (*section_status < 0) {
169
 
                section->wait_pdu = 1;
170
 
        }
171
 
 
172
 
        return used + tmp;
173
 
}