1 /*
2 * Packet management
3 * Copyright (C) 2008 Andreas Öman
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #ifndef PACKET_H_
20 #define PACKET_H_
21
22 struct memoryinfo;
23
24 /**
25 * Packet buffer
26 */
27
28 typedef struct pktbuf {
29 int pb_refcount;
30 int pb_err;
31 uint8_t *pb_data;
32 size_t pb_size;
33 } pktbuf_t;
34
35 /**
36 * Packets
37 */
38 #define PKT_I_FRAME 1
39 #define PKT_P_FRAME 2
40 #define PKT_B_FRAME 3
41 #define PKT_NTYPES 4
42
pkt_frametype_to_char(int frametype)43 static inline char pkt_frametype_to_char ( int frametype )
44 {
45 if (frametype == PKT_I_FRAME) return 'I';
46 if (frametype == PKT_P_FRAME) return 'P';
47 if (frametype == PKT_B_FRAME) return 'B';
48 return ' ';
49 }
50
51 typedef struct th_pkt {
52 int64_t pkt_dts;
53 int64_t pkt_pts;
54 int pkt_duration;
55 int pkt_refcount;
56
57 uint8_t pkt_type;
58 uint8_t pkt_err;
59 uint8_t pkt_componentindex;
60 uint8_t pkt_commercial;
61
62 union {
63 struct {
64 uint8_t pkt_frametype;
65 uint8_t pkt_field; // Set if packet is only a half frame (a field)
66
67 uint16_t pkt_aspect_num;
68 uint16_t pkt_aspect_den;
69 } v;
70 struct {
71 uint8_t pkt_keyframe;
72 uint8_t pkt_channels;
73 uint8_t pkt_sri;
74 uint8_t pkt_ext_sri;
75 } a;
76 };
77
78 pktbuf_t *pkt_meta;
79 pktbuf_t *pkt_payload;
80
81 } th_pkt_t;
82
83
84 /**
85 * A packet reference
86 */
87 typedef struct th_pktref {
88 TAILQ_ENTRY(th_pktref) pr_link;
89 th_pkt_t *pr_pkt;
90 } th_pktref_t;
91
92
93 /**
94 *
95 */
96 extern struct memoryinfo pkt_memoryinfo;
97 extern struct memoryinfo pktbuf_memoryinfo;
98 extern struct memoryinfo pktref_memoryinfo;
99
100 /**
101 *
102 */
103 void pkt_ref_dec(th_pkt_t *pkt);
104
105 void pkt_ref_inc(th_pkt_t *pkt);
106
107 void pkt_ref_inc_poly(th_pkt_t *pkt, int n);
108
109 void pktref_clear_queue(struct th_pktref_queue *q);
110
111 // Reference count is transfered to queue
112 void pktref_enqueue(struct th_pktref_queue *q, th_pkt_t *pkt);
113
114 void pktref_remove(struct th_pktref_queue *q, th_pktref_t *pr);
115
116 th_pkt_t *pktref_get_first(struct th_pktref_queue *q);
117
118 void pktref_insert_head(struct th_pktref_queue *q, th_pkt_t *pkt);
119
120 #define PKTREF_FOREACH(item, queue) TAILQ_FOREACH((item), (queue), pr_link)
121
122 th_pkt_t *pkt_alloc(streaming_component_type_t type,
123 const void *data, size_t datalen, int64_t pts, int64_t dts);
124
125 th_pkt_t *pkt_copy_shallow(th_pkt_t *pkt);
126
127 th_pkt_t *pkt_copy_nodata(th_pkt_t *pkt);
128
129 th_pktref_t *pktref_create(th_pkt_t *pkt);
130
131 void pkt_trace_
132 (const char *file, int line, int subsys, th_pkt_t *pkt,
133 const char *fmt, ...);
134
135 #define pkt_trace(subsys, pkt, fmt, ...) \
136 do { \
137 if (tvhtrace_enabled()) \
138 pkt_trace_(__FILE__, __LINE__, subsys, pkt, fmt, ##__VA_ARGS__); \
139 } while (0)
140
141 /*
142 *
143 */
144
145 void pktbuf_ref_dec(pktbuf_t *pb);
146
147 void pktbuf_destroy(pktbuf_t *pb);
148
149 pktbuf_t *pktbuf_ref_inc(pktbuf_t *pb);
150
151 pktbuf_t *pktbuf_alloc(const void *data, size_t size);
152
153 pktbuf_t *pktbuf_make(void *data, size_t size);
154
155 pktbuf_t *pktbuf_append(pktbuf_t *pb, const void *data, size_t size);
156
pktbuf_len(pktbuf_t * pb)157 static inline size_t pktbuf_len(pktbuf_t *pb) { return pb ? pb->pb_size : 0; }
pktbuf_ptr(pktbuf_t * pb)158 static inline uint8_t *pktbuf_ptr(pktbuf_t *pb) { return pb->pb_data; }
159
160 /*
161 *
162 */
163
pts_diff(int64_t a,int64_t b)164 static inline int64_t pts_diff(int64_t a, int64_t b)
165 {
166 if (a == PTS_UNSET || b == PTS_UNSET)
167 return PTS_UNSET;
168 a &= PTS_MASK;
169 b &= PTS_MASK;
170 if (b < (PTS_MASK / 4) && a > (PTS_MASK / 2))
171 return b + PTS_MASK + 1 - a;
172 else if (b >= a)
173 return b - a;
174 else
175 return PTS_UNSET;
176 }
177
pts_is_greater_or_equal(int64_t base,int64_t value)178 static inline int pts_is_greater_or_equal(int64_t base, int64_t value)
179 {
180 if (base == PTS_UNSET || value == PTS_UNSET)
181 return -1;
182 if (value >= base)
183 return 1;
184 if (value < (PTS_MASK / 4) && base > (PTS_MASK / 2))
185 return value + PTS_MASK + 1 >= base;
186 return 0;
187 }
188
189 const char *pts_to_string(int64_t pts, char *buf);
190
191 #endif /* PACKET_H_ */
192