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