2 * Copyright (C) <2005> Wim Taymans <wim.taymans@gmail.com>
3 * Copyright (C) <2008> Dejan Sakelsak <dejan.sakelsak@marand.si>
4 * Copyright (C) <2009> Janin Kolenc <janin.kolenc@marand.si>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
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 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
29 #include <gst/rtp/gstrtpbuffer.h>
31 #include "gstrtph263pay.h"
35 GST_H263_FRAME_TYPE_I = 0,
36 GST_H263_FRAME_TYPE_P = 1,
37 GST_H263_FRAME_TYPE_PB = 2
38 } GstRtpH263PayFrameType;
42 GST_RTP_H263_PAYLOAD_PICTURE_FORMAT_RES1 = 0,
43 GST_RTP_H263_PAYLOAD_PICTURE_FORMAT_SQCIF = 1,
44 GST_RTP_H263_PAYLOAD_PICTURE_FORMAT_QCIF = 2,
45 GST_RTP_H263_PAYLOAD_PICTURE_FORMAT_CIF = 3,
46 GST_RTP_H263_PAYLOAD_PICTURE_FORMAT_4CIF = 4,
47 GST_RTP_H263_PAYLOAD_PICTURE_FORMAT_16CIF = 5,
48 GST_RTP_H263_PAYLOAD_PICTURE_FORMAT_RES2 = 6,
49 GST_H263_PAYLOAD_PICTURE_FORMAT_PLUS = 7
50 } GstRtpH263PayPictureFormat;
52 static const guint format_props[8][2] = { {254, 254},
63 * I-frame MCBPC table: code, mask, nbits, cb, cr, mb type -> 10 = undefined (because we have guint)
67 static const guint32 mcbpc_I[9][6] = {
68 {0x8000, 0x8000, 1, 0, 0, 3},
69 {0x2000, 0xe000, 3, 0, 1, 3},
70 {0x4000, 0xe000, 3, 1, 0, 3},
71 {0x6000, 0xe000, 3, 1, 1, 3},
72 {0x1000, 0xf000, 4, 0, 0, 4},
73 {0x0400, 0xfc00, 6, 0, 1, 4},
74 {0x0800, 0xfc00, 6, 1, 0, 4},
75 {0x0c00, 0xfc00, 6, 1, 1, 4},
76 {0x0080, 0xff80, 9, 10, 10, 10}
80 * P-frame MCBPC table: code, mask, nbits, cb, cr, mb type -> 10 = undefined (because we have guint)
82 #define MCBPC_P_LEN 21
84 static const guint16 mcbpc_P[21][6] = {
85 {0x8000, 0x8000, 1, 0, 0, 0},
86 {0x3000, 0xf000, 4, 0, 1, 0},
87 {0x2000, 0xf000, 4, 1, 0, 0},
88 {0x1400, 0xfc00, 6, 1, 1, 0},
89 {0x6000, 0xe000, 3, 0, 0, 1},
90 {0x0e00, 0xfe00, 7, 0, 1, 1},
91 {0x0c00, 0xfe00, 7, 1, 0, 1},
92 {0x0280, 0xff80, 9, 1, 1, 1},
93 {0x4000, 0xe000, 3, 0, 0, 2},
94 {0x0a00, 0xfe00, 7, 0, 1, 2},
95 {0x0800, 0xfe00, 7, 1, 0, 2},
96 {0x0500, 0xff00, 8, 1, 1, 2},
97 {0x1800, 0xf800, 5, 0, 0, 3},
98 {0x0400, 0xff00, 8, 0, 1, 3},
99 {0x0300, 0xff00, 8, 1, 0, 3},
100 {0x0600, 0xfe00, 7, 1, 1, 3},
101 {0x1000, 0xfc00, 6, 0, 0, 4},
102 {0x0200, 0xff80, 9, 0, 1, 4},
103 {0x0180, 0xff80, 9, 1, 0, 4},
104 {0x0100, 0xff80, 9, 1, 1, 4},
105 {0x0080, 0xff80, 9, 10, 10, 10}
109 * I-frame CBPY (code, mask, nbits, Y0, Y1, Y2, Y3)
113 static const guint8 cbpy_I[16][7] = {
114 {0x30, 0xf0, 4, 0, 0, 0, 0},
115 {0x28, 0xf8, 5, 0, 0, 0, 1},
116 {0x20, 0xf8, 5, 0, 0, 1, 0},
117 {0x90, 0xf0, 4, 0, 0, 1, 1},
118 {0x18, 0xf8, 5, 0, 1, 0, 0},
119 {0x70, 0xf0, 4, 0, 1, 0, 1},
120 {0x08, 0xfc, 6, 0, 1, 1, 0},
121 {0xb0, 0xf0, 4, 0, 1, 1, 1},
122 {0x10, 0xf8, 5, 1, 0, 0, 0},
123 {0x0c, 0xfc, 6, 1, 0, 0, 1},
124 {0x50, 0xf0, 4, 1, 0, 1, 0},
125 {0xa0, 0xf0, 4, 1, 0, 1, 1},
126 {0x40, 0xf0, 4, 1, 1, 0, 0},
127 {0x80, 0xf0, 4, 1, 1, 0, 1},
128 {0x60, 0xf0, 4, 1, 1, 1, 0},
129 {0xc0, 0xc0, 2, 1, 1, 1, 1}
133 * P-frame CBPY (code, mask, nbits, Y0, Y1, Y2, Y3)
135 static const guint8 cbpy_P[16][7] = {
136 {0x30, 0xf0, 4, 1, 1, 1, 1},
137 {0x28, 0xf8, 5, 1, 1, 1, 0},
138 {0x20, 0xf8, 5, 1, 1, 0, 1},
139 {0x90, 0xf0, 4, 1, 1, 0, 0},
140 {0x18, 0xf8, 5, 1, 0, 1, 1},
141 {0x70, 0xf0, 4, 1, 0, 1, 0},
142 {0x08, 0xfc, 6, 1, 0, 0, 1},
143 {0xb0, 0xf0, 4, 1, 0, 0, 0},
144 {0x10, 0xf8, 5, 0, 1, 1, 1},
145 {0x0c, 0xfc, 6, 0, 1, 1, 0},
146 {0x50, 0xf0, 4, 0, 1, 0, 1},
147 {0xa0, 0xf0, 4, 0, 1, 0, 0},
148 {0x40, 0xf0, 4, 0, 0, 1, 1},
149 {0x80, 0xf0, 4, 0, 0, 1, 0},
150 {0x60, 0xf0, 4, 0, 0, 0, 1},
151 {0xc0, 0xc0, 2, 0, 0, 0, 0}
155 * Block TCOEF table (code, mask, nbits, LAST, RUN, LEVEL)
157 #define TCOEF_LEN 103
159 static const guint16 tcoef[103][6] = {
160 {0x8000, 0xc000, 3, 0, 0, 1},
161 {0xf000, 0xf000, 5, 0, 0, 2},
162 {0x5400, 0xfc00, 7, 0, 0, 3},
163 {0x2e00, 0xfe00, 8, 0, 0, 4},
164 {0x1f00, 0xff00, 9, 0, 0, 5},
165 {0x1280, 0xff80, 10, 0, 0, 6},
166 {0x1200, 0xff80, 10, 0, 0, 7},
167 {0x0840, 0xffc0, 11, 0, 0, 8},
168 {0x0800, 0xffc0, 11, 0, 0, 9},
169 {0x00e0, 0xffe0, 12, 0, 0, 10}, //10
170 {0x00c0, 0xffe0, 12, 0, 0, 11},
171 {0x0400, 0xffe0, 12, 0, 0, 12},
172 {0xc000, 0xe000, 4, 0, 1, 1},
173 {0x5000, 0xfc00, 7, 0, 1, 2},
174 {0x1e00, 0xff00, 9, 0, 1, 3},
175 {0x03c0, 0xffc0, 11, 0, 1, 4},
176 {0x0420, 0xffe0, 12, 0, 1, 5},
177 {0x0500, 0xfff0, 13, 0, 1, 6},
178 {0xe000, 0xf000, 5, 0, 2, 1},
179 {0x1d00, 0xff00, 9, 0, 2, 2}, //20
180 {0x0380, 0xffc0, 11, 0, 2, 3},
181 {0x0510, 0xfff0, 13, 0, 2, 4},
182 {0x6800, 0xf800, 6, 0, 3, 1},
183 {0x1180, 0xff80, 10, 0, 3, 2},
184 {0x0340, 0xffc0, 11, 0, 3, 3},
185 {0x6000, 0xf800, 6, 0, 4, 1},
186 {0x1100, 0xff80, 10, 0, 4, 2},
187 {0x0520, 0xfff0, 13, 0, 4, 3},
188 {0x5800, 0xf800, 6, 0, 5, 1},
189 {0x0300, 0xffc0, 11, 0, 5, 2}, // 30
190 {0x0530, 0xfff0, 13, 0, 5, 3},
191 {0x4c00, 0xfc00, 7, 0, 6, 1},
192 {0x02c0, 0xffc0, 11, 0, 6, 2},
193 {0x0540, 0xfff0, 13, 0, 6, 3},
194 {0x4800, 0xfc00, 7, 0, 7, 1},
195 {0x0280, 0xffc0, 11, 0, 7, 2},
196 {0x4400, 0xfc00, 7, 0, 8, 1},
197 {0x0240, 0xffc0, 11, 0, 8, 2},
198 {0x4000, 0xfc00, 7, 0, 9, 1},
199 {0x0200, 0xffc0, 11, 0, 9, 2}, // 40
200 {0x2c00, 0xfe00, 8, 0, 10, 1},
201 {0x0550, 0xfff0, 13, 0, 10, 2},
202 {0x2a00, 0xfe00, 8, 0, 11, 1},
203 {0x2800, 0xfe00, 8, 0, 12, 1},
204 {0x1c00, 0xff00, 9, 0, 13, 1},
205 {0x1b00, 0xff00, 9, 0, 14, 1},
206 {0x1080, 0xff80, 10, 0, 15, 1},
207 {0x1000, 0xff80, 10, 0, 16, 1},
208 {0x0f80, 0xff80, 10, 0, 17, 1},
209 {0x0f00, 0xff80, 10, 0, 18, 1}, // 50
210 {0x0e80, 0xff80, 10, 0, 19, 1},
211 {0x0e00, 0xff80, 10, 0, 20, 1},
212 {0x0d80, 0xff80, 10, 0, 21, 1},
213 {0x0d00, 0xff80, 10, 0, 22, 1},
214 {0x0440, 0xffe0, 12, 0, 23, 1},
215 {0x0460, 0xffe0, 12, 0, 24, 1},
216 {0x0560, 0xfff0, 13, 0, 25, 1},
217 {0x0570, 0xfff0, 13, 0, 26, 1},
218 {0x7000, 0xf000, 5, 1, 0, 1},
219 {0x0c80, 0xff80, 10, 1, 0, 2}, // 60
220 {0x00a0, 0xffe0, 12, 1, 0, 3},
221 {0x3c00, 0xfc00, 7, 1, 1, 1},
222 {0x0080, 0xffe0, 12, 1, 1, 2},
223 {0x3800, 0xfc00, 7, 1, 2, 1},
224 {0x3400, 0xfc00, 7, 1, 3, 1},
225 {0x3000, 0xfc00, 7, 1, 4, 1},
226 {0x2600, 0xfe00, 8, 1, 5, 1},
227 {0x2400, 0xfe00, 8, 1, 6, 1},
228 {0x2200, 0xfe00, 8, 1, 7, 1},
229 {0x2000, 0xfe00, 8, 1, 8, 1}, // 70
230 {0x1a00, 0xff00, 9, 1, 9, 1},
231 {0x1900, 0xff00, 9, 1, 10, 1},
232 {0x1800, 0xff00, 9, 1, 11, 1},
233 {0x1700, 0xff00, 9, 1, 12, 1},
234 {0x1600, 0xff00, 9, 1, 13, 1},
235 {0x1500, 0xff00, 9, 1, 14, 1},
236 {0x1400, 0xff00, 9, 1, 15, 1},
237 {0x1300, 0xff00, 9, 1, 16, 1},
238 {0x0c00, 0xff80, 10, 1, 17, 1},
239 {0x0b80, 0xff80, 10, 1, 18, 1}, // 80
240 {0x0b00, 0xff80, 10, 1, 19, 1},
241 {0x0a80, 0xff80, 10, 1, 20, 1},
242 {0x0a00, 0xff80, 10, 1, 21, 1},
243 {0x0980, 0xff80, 10, 1, 22, 1},
244 {0x0900, 0xff80, 10, 1, 23, 1},
245 {0x0880, 0xff80, 10, 1, 24, 1},
246 {0x01c0, 0xffc0, 11, 1, 25, 1},
247 {0x0180, 0xffc0, 11, 1, 26, 1},
248 {0x0140, 0xffc0, 11, 1, 27, 1},
249 {0x0100, 0xffc0, 11, 1, 28, 1}, // 90
250 {0x0480, 0xffe0, 12, 1, 29, 1},
251 {0x04a0, 0xffe0, 12, 1, 30, 1},
252 {0x04c0, 0xffe0, 12, 1, 31, 1},
253 {0x04e0, 0xffe0, 12, 1, 32, 1},
254 {0x0580, 0xfff0, 13, 1, 33, 1},
255 {0x0590, 0xfff0, 13, 1, 34, 1},
256 {0x05a0, 0xfff0, 13, 1, 35, 1},
257 {0x05b0, 0xfff0, 13, 1, 36, 1},
258 {0x05c0, 0xfff0, 13, 1, 37, 1},
259 {0x05d0, 0xfff0, 13, 1, 38, 1}, // 100
260 {0x05e0, 0xfff0, 13, 1, 39, 1},
261 {0x05f0, 0xfff0, 13, 1, 40, 1},
262 {0x0600, 0xfe00, 7, 0, 0xffff, 0xffff}
266 * Motion vector code table (Code, mask, nbits, vector (halfpixel, two's complement), diff (halfpixel, two's complement))
270 static const guint16 mvd[64][5] = {
271 {0x0028, 0xfff8, 13, 0x0060, 0x0020},
272 {0x0038, 0xfff8, 13, 0x0061, 0x0021},
273 {0x0050, 0xfff0, 12, 0x0062, 0x0022},
274 {0x0070, 0xfff0, 12, 0x0063, 0x0023},
275 {0x0090, 0xfff0, 12, 0x0064, 0x0024},
276 {0x00b0, 0xfff0, 12, 0x0065, 0x0025},
277 {0x00d0, 0xfff0, 12, 0x0066, 0x0026},
278 {0x00f0, 0xfff0, 12, 0x0067, 0x0027},
279 {0x0120, 0xffe0, 11, 0x0068, 0x0028},
280 {0x0160, 0xffe0, 11, 0x0069, 0x0029},
281 {0x01a0, 0xffe0, 11, 0x006a, 0x002a},
282 {0x01e0, 0xffe0, 11, 0x006b, 0x002b},
283 {0x0220, 0xffe0, 11, 0x006c, 0x002c},
284 {0x0260, 0xffe0, 11, 0x006d, 0x002d},
285 {0x02a0, 0xffe0, 11, 0x006e, 0x002e},
286 {0x02e0, 0xffe0, 11, 0x006f, 0x002f},
287 {0x0320, 0xffe0, 11, 0x0070, 0x0030},
288 {0x0360, 0xffe0, 11, 0x0071, 0x0031},
289 {0x03a0, 0xffe0, 11, 0x0072, 0x0032},
290 {0x03e0, 0xffe0, 11, 0x0073, 0x0033},
291 {0x0420, 0xffe0, 11, 0x0074, 0x0034},
292 {0x0460, 0xffe0, 11, 0x0075, 0x0035},
293 {0x04c0, 0xffc0, 10, 0x0076, 0x0036},
294 {0x0540, 0xffc0, 10, 0x0077, 0x0037},
295 {0x05c0, 0xffc0, 10, 0x0078, 0x0038},
296 {0x0700, 0xff00, 8, 0x0079, 0x0039},
297 {0x0900, 0xff00, 8, 0x007a, 0x003a},
298 {0x0b00, 0xff00, 8, 0x007b, 0x003b},
299 {0x0e00, 0xfe00, 7, 0x007c, 0x003c},
300 {0x1800, 0xf800, 5, 0x007d, 0x003d},
301 {0x3000, 0xf000, 4, 0x007e, 0x003e},
302 {0x6000, 0xe000, 3, 0x007f, 0x003f},
303 {0x8000, 0x8000, 1, 0x0000, 0x0000},
304 {0x4000, 0xe000, 3, 0x0001, 0x0041},
305 {0x2000, 0xf000, 4, 0x0002, 0x0042},
306 {0x1000, 0xf800, 5, 0x0003, 0x0043},
307 {0x0c00, 0xfe00, 7, 0x0004, 0x0044},
308 {0x0a00, 0xff00, 8, 0x0005, 0x0045},
309 {0x0800, 0xff00, 8, 0x0006, 0x0046},
310 {0x0600, 0xff00, 8, 0x0007, 0x0047},
311 {0x0580, 0xffc0, 10, 0x0008, 0x0048},
312 {0x0500, 0xffc0, 10, 0x0009, 0x0049},
313 {0x0480, 0xffc0, 10, 0x000a, 0x004a},
314 {0x0440, 0xffe0, 11, 0x000b, 0x004b},
315 {0x0400, 0xffe0, 11, 0x000c, 0x004c},
316 {0x03c0, 0xffe0, 11, 0x000d, 0x004d},
317 {0x0380, 0xffe0, 11, 0x000e, 0x004e},
318 {0x0340, 0xffe0, 11, 0x000f, 0x004f},
319 {0x0300, 0xffe0, 11, 0x0010, 0x0050},
320 {0x02c0, 0xffe0, 11, 0x0011, 0x0051},
321 {0x0280, 0xffe0, 11, 0x0012, 0x0052},
322 {0x0240, 0xffe0, 11, 0x0013, 0x0053},
323 {0x0200, 0xffe0, 11, 0x0014, 0x0054},
324 {0x01c0, 0xffe0, 11, 0x0015, 0x0055},
325 {0x0180, 0xffe0, 11, 0x0016, 0x0056},
326 {0x0140, 0xffe0, 11, 0x0017, 0x0057},
327 {0x0100, 0xffe0, 11, 0x0018, 0x0058},
328 {0x00e0, 0xfff0, 12, 0x0019, 0x0059},
329 {0x00c0, 0xfff0, 12, 0x001a, 0x005a},
330 {0x00a0, 0xfff0, 12, 0x001b, 0x005b},
331 {0x0080, 0xfff0, 12, 0x001c, 0x005c},
332 {0x0060, 0xfff0, 12, 0x001d, 0x005d},
333 {0x0040, 0xfff0, 12, 0x001e, 0x005e},
334 {0x0030, 0xfff8, 13, 0x001f, 0x005f}
337 GST_DEBUG_CATEGORY_STATIC (rtph263pay_debug);
338 #define GST_CAT_DEFAULT (rtph263pay_debug)
340 #define GST_RTP_HEADER_LEN 12
348 static GstStaticPadTemplate gst_rtp_h263_pay_sink_template =
349 GST_STATIC_PAD_TEMPLATE ("sink",
352 GST_STATIC_CAPS ("video/x-h263, "
353 "variant = (string) \"itu\", " "h263version = (string) \"h263\"")
356 static GstStaticPadTemplate gst_rtp_h263_pay_src_template =
357 GST_STATIC_PAD_TEMPLATE ("src",
360 GST_STATIC_CAPS ("application/x-rtp, "
361 "media = (string) \"video\", "
362 "payload = (int) " GST_RTP_PAYLOAD_H263_STRING ", "
363 "clock-rate = (int) 90000, " "encoding-name = (string) \"H263\"; "
364 "application/x-rtp, "
365 "media = (string) \"video\", "
366 "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
367 "clock-rate = (int) 90000, " "encoding-name = (string) \"H263\"")
370 static void gst_rtp_h263_pay_finalize (GObject * object);
372 static gboolean gst_rtp_h263_pay_setcaps (GstRTPBasePayload * payload,
374 static void gst_rtp_h263_pay_set_property (GObject * object, guint prop_id,
375 const GValue * value, GParamSpec * pspec);
376 static void gst_rtp_h263_pay_get_property (GObject * object, guint prop_id,
377 GValue * value, GParamSpec * pspec);
378 static GstFlowReturn gst_rtp_h263_pay_handle_buffer (GstRTPBasePayload *
379 payload, GstBuffer * buffer);
381 static void gst_rtp_h263_pay_boundry_init (GstRtpH263PayBoundry * boundry,
382 guint8 * start, guint8 * end, guint8 sbit, guint8 ebit);
383 static GstRtpH263PayGob *gst_rtp_h263_pay_gob_new (GstRtpH263PayBoundry *
384 boundry, guint gobn);
385 static GstRtpH263PayMB *gst_rtp_h263_pay_mb_new (GstRtpH263PayBoundry * boundry,
387 static GstRtpH263PayPackage *gst_rtp_h263_pay_package_new_empty ();
388 static GstRtpH263PayPackage *gst_rtp_h263_pay_package_new (guint8 * start,
389 guint8 * end, guint length, guint8 sbit, guint8 ebit, GstBuffer * outbuf,
392 static void gst_rtp_h263_pay_mb_destroy (GstRtpH263PayMB * mb);
393 static void gst_rtp_h263_pay_gob_destroy (GstRtpH263PayGob * gob, guint ind);
394 static void gst_rtp_h263_pay_context_destroy (GstRtpH263PayContext * context,
396 static void gst_rtp_h263_pay_package_destroy (GstRtpH263PayPackage * pack);
398 #define gst_rtp_h263_pay_parent_class parent_class
399 G_DEFINE_TYPE (GstRtpH263Pay, gst_rtp_h263_pay, GST_TYPE_RTP_BASE_PAYLOAD);
402 gst_rtp_h263_pay_class_init (GstRtpH263PayClass * klass)
404 GObjectClass *gobject_class;
405 GstElementClass *gstelement_class;
406 GstRTPBasePayloadClass *gstrtpbasepayload_class;
408 gobject_class = (GObjectClass *) klass;
409 gstelement_class = (GstElementClass *) klass;
410 gstrtpbasepayload_class = (GstRTPBasePayloadClass *) klass;
412 gobject_class->finalize = gst_rtp_h263_pay_finalize;
414 gstrtpbasepayload_class->set_caps = gst_rtp_h263_pay_setcaps;
415 gstrtpbasepayload_class->handle_buffer = gst_rtp_h263_pay_handle_buffer;
416 gobject_class->set_property = gst_rtp_h263_pay_set_property;
417 gobject_class->get_property = gst_rtp_h263_pay_get_property;
419 g_object_class_install_property (G_OBJECT_CLASS (klass),
420 PROP_MODE_A_ONLY, g_param_spec_boolean ("modea-only",
421 "Fragment packets in mode A Only",
422 "Disable packetization modes B and C", DEFAULT_MODE_A,
423 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
425 gst_element_class_add_pad_template (gstelement_class,
426 gst_static_pad_template_get (&gst_rtp_h263_pay_src_template));
427 gst_element_class_add_pad_template (gstelement_class,
428 gst_static_pad_template_get (&gst_rtp_h263_pay_sink_template));
430 gst_element_class_set_static_metadata (gstelement_class,
431 "RTP H263 packet payloader", "Codec/Payloader/Network/RTP",
432 "Payload-encodes H263 video in RTP packets (RFC 2190)",
433 "Neil Stratford <neils@vipadia.com>"
434 "Dejan Sakelsak <dejan.sakelsak@marand.si>");
436 GST_DEBUG_CATEGORY_INIT (rtph263pay_debug, "rtph263pay", 0,
437 "H263 RTP Payloader");
441 gst_rtp_h263_pay_init (GstRtpH263Pay * rtph263pay)
443 rtph263pay->adapter = gst_adapter_new ();
445 rtph263pay->prop_payload_mode = DEFAULT_MODE_A;
449 gst_rtp_h263_pay_finalize (GObject * object)
451 GstRtpH263Pay *rtph263pay;
453 rtph263pay = GST_RTP_H263_PAY (object);
455 g_object_unref (rtph263pay->adapter);
456 rtph263pay->adapter = NULL;
458 G_OBJECT_CLASS (parent_class)->finalize (object);
462 gst_rtp_h263_pay_setcaps (GstRTPBasePayload * payload, GstCaps * caps)
466 payload->pt = GST_RTP_PAYLOAD_H263;
467 gst_rtp_base_payload_set_options (payload, "video", TRUE, "H263", 90000);
468 res = gst_rtp_base_payload_set_outcaps (payload, NULL);
474 gst_rtp_h263_pay_context_destroy (GstRtpH263PayContext * context, guint ind)
482 for (i = 0; i < format_props[ind][0]; i++) {
483 if (context->gobs[i]) {
484 gst_rtp_h263_pay_gob_destroy (context->gobs[i], ind);
488 g_free (context->gobs);
495 gst_rtp_h263_pay_set_property (GObject * object, guint prop_id,
496 const GValue * value, GParamSpec * pspec)
498 GstRtpH263Pay *rtph263pay;
500 rtph263pay = GST_RTP_H263_PAY (object);
503 case PROP_MODE_A_ONLY:
504 rtph263pay->prop_payload_mode = g_value_get_boolean (value);
507 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
513 gst_rtp_h263_pay_get_property (GObject * object, guint prop_id,
514 GValue * value, GParamSpec * pspec)
516 GstRtpH263Pay *rtph263pay;
518 rtph263pay = GST_RTP_H263_PAY (object);
521 case PROP_MODE_A_ONLY:
522 g_value_set_boolean (value, rtph263pay->prop_payload_mode);
525 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
530 static GstRtpH263PayPackage *
531 gst_rtp_h263_pay_package_new_empty (void)
533 return (GstRtpH263PayPackage *) g_malloc0 (sizeof (GstRtpH263PayPackage));
536 static GstRtpH263PayPackage *
537 gst_rtp_h263_pay_package_new (guint8 * start, guint8 * end, guint length,
538 guint8 sbit, guint8 ebit, GstBuffer * outbuf, gboolean marker)
541 GstRtpH263PayPackage *package;
543 package = gst_rtp_h263_pay_package_new_empty ();
545 package->payload_start = start;
546 package->payload_end = end;
547 package->payload_len = length;
548 package->sbit = sbit;
549 package->ebit = ebit;
550 package->outbuf = outbuf;
551 package->marker = marker;
557 gst_rtp_h263_pay_package_destroy (GstRtpH263PayPackage * pack)
564 gst_rtp_h263_pay_boundry_init (GstRtpH263PayBoundry * boundry,
565 guint8 * start, guint8 * end, guint8 sbit, guint8 ebit)
567 boundry->start = start;
569 boundry->sbit = sbit;
570 boundry->ebit = ebit;
574 gst_rtp_h263_pay_splat_header_A (guint8 * header,
575 GstRtpH263PayPackage * package, GstRtpH263PayPic * piclayer)
578 GstRtpH263PayAHeader *a_header;
580 a_header = (GstRtpH263PayAHeader *) header;
584 a_header->sbit = package->sbit;
585 a_header->ebit = package->ebit;
586 a_header->src = GST_H263_PICTURELAYER_PLSRC (piclayer);
587 a_header->i = GST_H263_PICTURELAYER_PLTYPE (piclayer);
588 a_header->u = GST_H263_PICTURELAYER_PLUMV (piclayer);
589 a_header->s = GST_H263_PICTURELAYER_PLSAC (piclayer);
590 a_header->a = GST_H263_PICTURELAYER_PLAP (piclayer);
600 gst_rtp_h263_pay_splat_header_B (guint8 * header,
601 GstRtpH263PayPackage * package, GstRtpH263PayPic * piclayer)
604 GstRtpH263PayBHeader *b_header;
606 b_header = (GstRtpH263PayBHeader *) header;
610 b_header->sbit = package->sbit;
611 b_header->ebit = package->ebit;
612 b_header->src = GST_H263_PICTURELAYER_PLSRC (piclayer);
613 b_header->quant = package->quant;
614 b_header->gobn = package->gobn;
615 b_header->mba1 = package->mba >> 6;
616 b_header->mba2 = package->mba & 0x003f;
618 b_header->i = GST_H263_PICTURELAYER_PLTYPE (piclayer);
619 b_header->u = GST_H263_PICTURELAYER_PLUMV (piclayer);
620 b_header->s = GST_H263_PICTURELAYER_PLSAC (piclayer);
621 b_header->a = GST_H263_PICTURELAYER_PLAP (piclayer);
631 if (package->nmvd > 0) {
633 b_header->hmv11 = (package->mvd[0] & 0x7f) >> 3;
634 b_header->hmv12 = (package->mvd[0] & 0x07);
636 b_header->vmv11 = (package->mvd[1] & 0x07f) >> 2;
637 b_header->vmv12 = (package->mvd[1] & 0x03);
639 if (package->nmvd == 8) {
641 b_header->hmv21 = (package->mvd[4] & 0x7f) >> 1;
642 b_header->hmv22 = (package->mvd[4] & 0x01);
644 b_header->vmv21 = (package->mvd[5] & 0x7f);
651 gst_rtp_h263_pay_gobfinder (GstRtpH263Pay * rtph263pay,
652 GstRtpH263PayBoundry * boundry)
658 current = boundry->end + 1;
659 range = (rtph263pay->data - current) + rtph263pay->available_data;
662 GST_DEBUG ("Searching for next GOB, data:%p, len:%u, payload_len:%p,"
663 " current:%p, range:%u", rtph263pay->data, rtph263pay->available_data,
664 boundry->end + 1, current, range);
666 /* If we are past the end, stop */
667 if (current >= rtph263pay->data + rtph263pay->available_data)
670 for (i = 3; i < range - 3; i++) {
671 if ((current[i] == 0x0) &&
672 (current[i + 1] == 0x0) && (current[i + 2] >> 7 == 0x1)) {
673 GST_LOG ("GOB end found at: %p start: %p len: %u", current + i - 1,
674 boundry->end + 1, (guint) (current + i - boundry->end + 2));
675 gst_rtp_h263_pay_boundry_init (boundry, boundry->end + 1,
676 current + i - 1, 0, 0);
682 GST_DEBUG ("Couldn't find any new GBSC in this frame, range:%u", range);
684 gst_rtp_h263_pay_boundry_init (boundry, boundry->end + 1,
685 (guint8 *) (rtph263pay->data + rtph263pay->available_data - 1), 0, 0);
690 static GstRtpH263PayGob *
691 gst_rtp_h263_pay_gob_new (GstRtpH263PayBoundry * boundry, guint gobn)
693 GstRtpH263PayGob *gob;
695 gob = (GstRtpH263PayGob *) g_malloc0 (sizeof (GstRtpH263PayGob));
697 gob->start = boundry->start;
698 gob->end = boundry->end;
699 gob->length = boundry->end - boundry->start + 1;
700 gob->ebit = boundry->ebit;
701 gob->sbit = boundry->sbit;
704 gob->macroblocks = NULL;
705 gob->nmacroblocs = 0;
711 gst_rtp_h263_pay_gob_destroy (GstRtpH263PayGob * gob, guint ind)
717 if (gob->macroblocks) {
721 for (i = 0; i < gob->nmacroblocs; i++) {
722 gst_rtp_h263_pay_mb_destroy (gob->macroblocks[i]);
725 g_free (gob->macroblocks);
732 * decode MCBPC for I frames and return index in table or -1 if not found
735 gst_rtp_h263_pay_decode_mcbpc_I (guint32 value)
743 GST_DEBUG ("value:0x%08x, code:0x%04x", value, code);
745 for (i = 0; i < MCBPC_I_LEN; i++) {
746 if ((code & mcbpc_I[i][1]) == mcbpc_I[i][0]) {
751 GST_WARNING ("Couldn't find code, returning -1");
757 * decode MCBPC for P frames and return index in table or -1 if not found
760 gst_rtp_h263_pay_decode_mcbpc_P (guint32 value)
768 GST_DEBUG ("value:0x%08x, code:0x%04x", value, code);
770 for (i = 0; i < MCBPC_P_LEN; i++) {
771 if ((code & mcbpc_P[i][1]) == mcbpc_P[i][0]) {
776 GST_WARNING ("Couldn't find code, returning -1");
782 * decode CBPY and return index in table or -1 if not found
785 gst_rtp_h263_pay_decode_cbpy (guint32 value, const guint8 cbpy_table[16][7])
793 GST_DEBUG ("value:0x%08x, code:0x%04x", value, code);
795 for (i = 0; i < CBPY_LEN; i++) {
796 if ((code & cbpy_table[i][1]) == cbpy_table[i][0]) {
801 GST_WARNING ("Couldn't find code, returning -1");
807 * decode MVD and return index in table or -1 if not found
810 gst_rtp_h263_pay_decode_mvd (guint32 value)
818 GST_DEBUG ("value:0x%08x, code:0x%04x", value, code);
820 for (i = 0; i < MVD_LEN; i++) {
821 if ((code & mvd[i][1]) == mvd[i][0]) {
826 GST_WARNING ("Couldn't find code, returning -1");
832 * decode TCOEF and return index in table or -1 if not found
835 gst_rtp_h263_pay_decode_tcoef (guint32 value)
843 GST_DEBUG ("value:0x%08x, code:0x%04x", value, code);
845 for (i = 0; i < TCOEF_LEN; i++) {
846 if ((code & tcoef[i][1]) == tcoef[i][0]) {
847 GST_LOG ("tcoef is %d", i);
852 GST_WARNING ("Couldn't find code, returning -1");
858 * the 32-bit register is like a window that we move right for "move_bits" to get the next v "data" h263 field
859 * "rest_bits" tells how many bits in the "data" byte address are still not used
863 gst_rtp_h263_pay_move_window_right (GstRtpH263PayContext * context, guint n,
864 guint rest_bits, guint8 ** orig_data, guint8 ** data_end)
867 GST_DEBUG ("Moving window: 0x%08x from: %p for %d bits, rest_bits: %d",
868 context->window, context->win_end, n, rest_bits);
873 while (n != 0 || context->win_end == ((*data_end) + 1)) {
875 if (rest_bits == 0) {
877 context->window = (context->window << 8) | *context->win_end;
881 (context->window << n) | (*context->win_end >> (8 - n));
890 (context->window << rest_bits) | (*context->
891 win_end & (((guint) pow (2.0, (double) rest_bits)) - 1));
896 (context->window << n) | ((*context->win_end & (((guint) pow (2.0,
897 (double) rest_bits)) - 1)) >> (rest_bits - n));
908 *orig_data = context->win_end - 4;
911 ("Window moved to %p with value: 0x%08x and orig_data: %p rest_bits: %d",
912 context->win_end, context->window, *orig_data, rest_bits);
917 * Find the start of the next MB (end of the current MB)
918 * returns the number of excess bits and stores the end of the MB in end
919 * data must be placed on first MB byte
921 static GstRtpH263PayMB *
922 gst_rtp_h263_pay_B_mbfinder (GstRtpH263PayContext * context,
923 GstRtpH263PayGob * gob, GstRtpH263PayMB * macroblock, guint mba)
927 guint cbpy_type_index;
928 guint tcoef_type_index;
929 GstRtpH263PayMB *mac;
930 GstRtpH263PayBoundry boundry;
933 gst_rtp_h263_pay_boundry_init (&boundry, macroblock->end,
934 macroblock->end, 8 - macroblock->ebit, macroblock->ebit);
935 mac = gst_rtp_h263_pay_mb_new (&boundry, mba);
938 if (mac->sbit == 8) {
944 GST_LOG ("current_pos:%p, end:%p, rest_bits:%d, window:%x",
945 mac->start, mac->end, macroblock->ebit, context->window);
947 GST_LOG ("Current pos after COD: %p", mac->end);
949 if (context->piclayer->ptype_pictype == 0) {
955 //Step 2 decode MCBPC I
956 mb_type_index = gst_rtp_h263_pay_decode_mcbpc_I (context->window);
958 GST_DEBUG ("MCBPC index: %d", mb_type_index);
959 if (mb_type_index == -1) {
960 GST_ERROR ("MB index shouldn't be -1 in window: %08x", context->window);
965 gst_rtp_h263_pay_move_window_right (context, mcbpc_I[mb_type_index][2],
966 mac->ebit, &mac->end, &gob->end);
968 mac->mb_type = mcbpc_I[mb_type_index][5];
970 if (mb_type_index == 8) {
971 GST_LOG ("Stuffing skipping rest of MB header");
974 //Step 3 decode CBPY I
975 cbpy_type_index = gst_rtp_h263_pay_decode_cbpy (context->window, cbpy_I);
977 GST_DEBUG ("CBPY index: %d", cbpy_type_index);
978 if (cbpy_type_index == -1) {
979 GST_ERROR ("CBPY index shouldn't be -1 in window: %08x", context->window);
984 gst_rtp_h263_pay_move_window_right (context, cbpy_I[cbpy_type_index][2],
985 mac->ebit, &mac->end, &gob->end);
987 //Step 4 decode rest of MB
988 //MB type 1 and 4 have DQUANT - we store it for packaging purposes
989 if (mcbpc_I[mb_type_index][5] == 4) {
990 GST_DEBUG ("Shifting DQUANT");
992 mac->quant = (context->window >> 30);
995 gst_rtp_h263_pay_move_window_right (context, 2, mac->ebit, &mac->end,
998 //Step 5 go trough the blocks - decode DC and TCOEF
1000 for (i = 0; i < N_BLOCKS; i++) {
1002 GST_DEBUG ("Decoding INTRADC and TCOEF, i:%d", i);
1004 gst_rtp_h263_pay_move_window_right (context, 8, mac->ebit, &mac->end,
1008 ind = mcbpc_I[mb_type_index][i - 1];
1010 ind = cbpy_I[cbpy_type_index][i + 3];
1015 tcoef_type_index = gst_rtp_h263_pay_decode_tcoef (context->window);
1017 GST_DEBUG ("TCOEF index: %d", tcoef_type_index);
1018 if (tcoef_type_index == -1) {
1019 GST_ERROR ("TCOEF index shouldn't be -1 in window: %08x",
1024 gst_rtp_h263_pay_move_window_right (context,
1025 tcoef[tcoef_type_index][2], mac->ebit, &mac->end, &gob->end);
1027 last = tcoef[tcoef_type_index][3];
1028 if (tcoef_type_index == 102) {
1029 if ((context->window & 0x80000000) == 0x80000000)
1035 gst_rtp_h263_pay_move_window_right (context, 15,
1036 mac->ebit, &mac->end, &gob->end);
1050 GST_DEBUG ("Checking for COD");
1051 if ((context->window & 0x80000000) == 0x80000000) {
1052 //The MB is not coded
1054 gst_rtp_h263_pay_move_window_right (context, 1, mac->ebit, &mac->end,
1056 GST_DEBUG ("COOOOOOOOOOOD = 1");
1062 gst_rtp_h263_pay_move_window_right (context, 1, mac->ebit, &mac->end,
1066 //Step 2 decode MCBPC P
1067 mb_type_index = gst_rtp_h263_pay_decode_mcbpc_P (context->window);
1069 GST_DEBUG ("MCBPC index: %d", mb_type_index);
1070 if (mb_type_index == -1) {
1071 GST_ERROR ("MB index shouldn't be -1 in window: %08x", context->window);
1075 gst_rtp_h263_pay_move_window_right (context, mcbpc_P[mb_type_index][2],
1076 mac->ebit, &mac->end, &gob->end);
1078 mac->mb_type = mcbpc_P[mb_type_index][5];
1080 if (mb_type_index == 20) {
1081 GST_LOG ("Stuffing skipping rest of MB header");
1084 //Step 3 decode CBPY P
1085 cbpy_type_index = gst_rtp_h263_pay_decode_cbpy (context->window, cbpy_P);
1087 GST_DEBUG ("CBPY index: %d", cbpy_type_index);
1088 if (cbpy_type_index == -1) {
1089 GST_ERROR ("CBPY index shouldn't be -1 in window: %08x", context->window);
1093 gst_rtp_h263_pay_move_window_right (context, cbpy_P[cbpy_type_index][2],
1094 mac->ebit, &mac->end, &gob->end);
1096 //MB type 1 and 4 have DQUANT - we add it to MB object and jump over
1097 if (mcbpc_P[mb_type_index][5] == 4 || mcbpc_P[mb_type_index][5] == 1) {
1098 GST_DEBUG ("Shifting DQUANT");
1100 mac->quant = context->window >> 30;
1103 gst_rtp_h263_pay_move_window_right (context, 2, mac->ebit, &mac->end,
1106 //MB types < 3 have MVD1-4
1107 if (mcbpc_P[mb_type_index][5] < 3) {
1113 if (mcbpc_P[mb_type_index][5] == 2)
1116 for (j = 0; j < nmvd; j++) {
1119 mvd_type = gst_rtp_h263_pay_decode_mvd (context->window);
1121 if (mvd_type == -1) {
1122 GST_ERROR ("MVD1-4 index shouldn't be -1 in window: %08x",
1126 //set the MB mvd values
1127 mac->mvd[j] = mvd[mvd_type][3];
1130 gst_rtp_h263_pay_move_window_right (context, mvd[mvd_type][2],
1131 mac->ebit, &mac->end, &gob->end);
1136 //Step 5 go trough the blocks - decode DC and TCOEF
1138 for (i = 0; i < N_BLOCKS; i++) {
1140 //if MB type 3 or 4 then INTRADC coef are present in blocks
1141 if (mcbpc_P[mb_type_index][5] > 2) {
1142 GST_DEBUG ("INTRADC coef: %d", i);
1144 gst_rtp_h263_pay_move_window_right (context, 8, mac->ebit,
1145 &mac->end, &gob->end);
1147 GST_DEBUG ("INTRADC coef is not present");
1150 //check if the block has TCOEF
1152 ind = mcbpc_P[mb_type_index][i - 1];
1154 if (mcbpc_P[mb_type_index][5] > 2) {
1155 ind = cbpy_I[cbpy_type_index][i + 3];
1157 ind = cbpy_P[cbpy_type_index][i + 3];
1163 tcoef_type_index = gst_rtp_h263_pay_decode_tcoef (context->window);
1165 GST_DEBUG ("TCOEF index: %d", tcoef_type_index);
1166 if (tcoef_type_index == -1) {
1167 GST_ERROR ("TCOEF index shouldn't be -1 in window: %08x",
1173 gst_rtp_h263_pay_move_window_right (context,
1174 tcoef[tcoef_type_index][2], mac->ebit, &mac->end, &gob->end);
1176 last = tcoef[tcoef_type_index][3];
1177 if (tcoef_type_index == 102) {
1178 if ((context->window & 0x80000000) == 0x80000000)
1184 gst_rtp_h263_pay_move_window_right (context, 15,
1185 mac->ebit, &mac->end, &gob->end);
1193 mac->length = mac->end - mac->start + 1;
1198 gst_rtp_h263_pay_mb_destroy (mac);
1202 static GstRtpH263PayMB *
1203 gst_rtp_h263_pay_mb_new (GstRtpH263PayBoundry * boundry, guint mba)
1205 GstRtpH263PayMB *mb;
1208 mb = (GstRtpH263PayMB *) g_malloc0 (sizeof (GstRtpH263PayMB));
1210 mb->start = boundry->start;
1211 mb->end = boundry->end;
1212 mb->length = boundry->end - boundry->start + 1;
1213 mb->sbit = boundry->sbit;
1214 mb->ebit = boundry->ebit;
1217 for (i = 0; i < 5; i++)
1224 gst_rtp_h263_pay_mb_destroy (GstRtpH263PayMB * mb)
1232 static GstFlowReturn
1233 gst_rtp_h263_pay_push (GstRtpH263Pay * rtph263pay,
1234 GstRtpH263PayContext * context, GstRtpH263PayPackage * package)
1238 * Splat the payload header values
1243 GstRTPBuffer rtp = { NULL };
1245 gst_rtp_buffer_map (package->outbuf, GST_MAP_WRITE, &rtp);
1247 header = gst_rtp_buffer_get_payload (&rtp);
1248 payload = header + package->mode;
1250 switch (package->mode) {
1251 case GST_RTP_H263_PAYLOAD_HEADER_MODE_A:
1252 GST_LOG ("Pushing A packet");
1253 gst_rtp_h263_pay_splat_header_A (header, package, context->piclayer);
1255 case GST_RTP_H263_PAYLOAD_HEADER_MODE_B:
1256 GST_LOG ("Pushing B packet");
1257 gst_rtp_h263_pay_splat_header_B (header, package, context->piclayer);
1259 case GST_RTP_H263_PAYLOAD_HEADER_MODE_C:
1260 //gst_rtp_h263_pay_splat_header_C(header, package, context->piclayer);
1263 return GST_FLOW_ERROR;
1268 * Copy the payload data in the buffer
1270 GST_DEBUG ("Copying memory");
1271 memcpy (payload, (guint8 *) package->payload_start, package->payload_len);
1274 * timestamp the buffer
1276 GST_BUFFER_TIMESTAMP (package->outbuf) = rtph263pay->first_ts;
1278 gst_rtp_buffer_set_marker (&rtp, package->marker);
1279 if (package->marker)
1280 GST_DEBUG ("Marker set!");
1282 gst_rtp_buffer_unmap (&rtp);
1285 gst_rtp_base_payload_push (GST_RTP_BASE_PAYLOAD (rtph263pay),
1287 GST_DEBUG ("Package pushed, returning");
1289 gst_rtp_h263_pay_package_destroy (package);
1294 static GstFlowReturn
1295 gst_rtp_h263_pay_A_fragment_push (GstRtpH263Pay * rtph263pay,
1296 GstRtpH263PayContext * context, guint first, guint last)
1299 GstRtpH263PayPackage *pack;
1301 pack = gst_rtp_h263_pay_package_new_empty ();
1303 pack->payload_start = context->gobs[first]->start;
1304 pack->sbit = context->gobs[first]->sbit;
1305 pack->ebit = context->gobs[last]->ebit;
1307 (context->gobs[last]->end - context->gobs[first]->start) + 1;
1308 pack->marker = FALSE;
1310 if (last == context->no_gobs - 1) {
1311 pack->marker = TRUE;
1314 pack->gobn = context->gobs[first]->gobn;
1315 pack->mode = GST_RTP_H263_PAYLOAD_HEADER_MODE_A;
1317 gst_rtp_buffer_new_allocate (pack->payload_len + pack->mode, 0, 0);
1319 GST_DEBUG ("Sending len:%d data to push function", pack->payload_len);
1321 return gst_rtp_h263_pay_push (rtph263pay, context, pack);
1324 static GstFlowReturn
1325 gst_rtp_h263_pay_B_fragment_push (GstRtpH263Pay * rtph263pay,
1326 GstRtpH263PayContext * context, GstRtpH263PayGob * gob, guint first,
1327 guint last, GstRtpH263PayBoundry * boundry)
1330 GstRtpH263PayPackage *pack;
1333 pack = gst_rtp_h263_pay_package_new_empty ();
1335 pack->payload_start = gob->macroblocks[first]->start;
1336 pack->sbit = gob->macroblocks[first]->sbit;
1338 pack->payload_start = boundry->start;
1339 pack->sbit = boundry->sbit;
1340 pack->quant = gob->quant;
1342 pack->quant = gob->macroblocks[first]->quant;
1344 pack->payload_end = gob->macroblocks[last]->end;
1346 pack->ebit = gob->macroblocks[last]->ebit;
1347 pack->mba = gob->macroblocks[first]->mba;
1348 pack->gobn = gob->gobn;
1349 pack->mode = GST_RTP_H263_PAYLOAD_HEADER_MODE_B;
1352 if (gob->macroblocks[first]->mb_type < 3) {
1353 if (gob->macroblocks[first]->mb_type == 2)
1355 else if (gob->macroblocks[first]->mb_type < 2)
1358 for (mv = 0; mv < pack->nmvd; mv++)
1359 pack->mvd[mv] = gob->macroblocks[first]->mvd[mv];
1362 pack->marker = FALSE;
1363 if (last == gob->nmacroblocs - 1) {
1367 if ((format_props[context->piclayer->ptype_srcformat][0] - 1 == gob->gobn)
1368 && (last == gob->nmacroblocs - 1)) {
1369 pack->marker = TRUE;
1372 pack->payload_len = pack->payload_end - pack->payload_start + 1;
1374 gst_rtp_buffer_new_allocate (pack->payload_len + pack->mode, 0, 0);
1376 return gst_rtp_h263_pay_push (rtph263pay, context, pack);
1381 gst_rtp_h263_pay_mode_B_fragment (GstRtpH263Pay * rtph263pay,
1382 GstRtpH263PayContext * context, GstRtpH263PayGob * gob)
1386 /*---------- MODE B MODE FRAGMENTATION ----------*/
1387 GstRtpH263PayMB *mac;
1388 guint max_payload_size;
1389 GstRtpH263PayBoundry boundry;
1398 context->mtu - GST_RTP_H263_PAYLOAD_HEADER_MODE_B - GST_RTP_HEADER_LEN;
1400 gst_rtp_h263_pay_boundry_init (&boundry, gob->start, gob->start, gob->sbit,
1404 (GstRtpH263PayMB **) g_malloc0 (sizeof (GstRtpH263PayMB *) *
1405 format_props[context->piclayer->ptype_srcformat][1]);
1407 GST_LOG ("GOB isn't PB frame, applying mode B");
1409 //initializing window
1410 context->win_end = boundry.end;
1411 if (gst_rtp_h263_pay_move_window_right (context, 32, boundry.ebit,
1412 &boundry.end, &gob->end) != 0) {
1414 ("The rest of the bits should be 0, exiting, because something bad happend");
1415 gst_adapter_flush (rtph263pay->adapter, rtph263pay->available_data);
1418 //The first GOB of a frame "has no" actual header - PICTURE header is his header
1419 if (gob->gobn == 0) {
1421 GST_LOG ("Initial GOB");
1425 gst_rtp_h263_pay_move_window_right (context, shift, boundry.ebit,
1426 &boundry.end, &gob->end);
1428 //We need PQUANT for mode B packages - so we store it
1429 gob->quant = context->window >> 27;
1431 //if PCM == 1, then PSBI is present - header has 51 bits
1432 //shift for PQUANT (5) and PCM (1) = 6 bits
1434 if (context->cpm == 1)
1437 gst_rtp_h263_pay_move_window_right (context, shift, boundry.ebit,
1438 &boundry.end, &gob->end);
1440 GST_DEBUG ("window: 0x%08x", context->window);
1442 //Shifting the PEI and PSPARE fields
1443 while ((context->window & 0x80000000) == 0x80000000) {
1445 gst_rtp_h263_pay_move_window_right (context, 9,
1446 boundry.ebit, &boundry.end, &gob->end);
1447 GST_LOG ("window: 0x%x", context->window);
1450 //shift the last PEI field
1452 gst_rtp_h263_pay_move_window_right (context, 1, boundry.ebit,
1453 &boundry.end, &gob->end);
1456 //skipping GOBs 24 header bits + 5 GQUANT
1459 GST_LOG ("INTER GOB");
1461 //if CPM == 1, there are 2 more bits in the header - GSBI header is 31 bits long
1462 if (context->cpm == 1)
1465 GST_LOG ("window: 0x%x", context->window);
1467 gst_rtp_h263_pay_move_window_right (context, shift,
1468 boundry.ebit, &boundry.end, &gob->end);
1470 //We need GQUANT for mode B packages - so we store it
1471 gob->quant = context->window >> 27;
1475 gst_rtp_h263_pay_move_window_right (context, shift,
1476 boundry.ebit, &boundry.end, &gob->end);
1478 GST_LOG ("window: 0x%x", context->window);
1481 GST_DEBUG ("GQUANT IS: %08x", gob->quant);
1483 // We are on MB layer
1485 m = mac = gst_rtp_h263_pay_mb_new (&boundry, 0);
1486 for (mb = 0; mb < format_props[context->piclayer->ptype_srcformat][1]; mb++) {
1488 GST_DEBUG ("================ START MB %d =================", mb);
1490 //Find next macroblock boundaries
1491 if (!(mac = gst_rtp_h263_pay_B_mbfinder (context, gob, mac, mb))) {
1493 GST_DEBUG ("Error decoding MB - sbit: %d", 8 - m->ebit);
1494 GST_ERROR ("Error decoding in GOB");
1498 //If mb_type == stuffing, don't increment the mb address
1499 if (mac->mb_type == 10) {
1506 gob->macroblocks[mb] = mac;
1508 if (mac->end >= gob->end) {
1509 GST_LOG ("No more MBs in this GOB");
1513 gob->end = mac->end;
1517 GST_DEBUG ("Found MB: mba: %d start: %p end: %p len: %d sbit: %d ebit: %d",
1518 mac->mba, mac->start, mac->end, mac->length, mac->sbit, mac->ebit);
1519 GST_DEBUG ("================ END MB %d =================", mb);
1524 payload_len = boundry.end - boundry.start + 1;
1525 GST_DEBUG ("------------------------- NEW PACKAGE ----------------------");
1526 while (mb < gob->nmacroblocs) {
1527 if (payload_len + gob->macroblocks[mb]->length < max_payload_size) {
1529 //FIXME: payload_len is not the real length -> ignoring sbit/ebit
1530 payload_len += gob->macroblocks[mb]->length;
1534 //FIXME: we should include the last few bits of the GOB in the package - do we do that now?
1535 //GST_DEBUG ("Pushing GOBS %d to %d because payload size is %d", first,
1536 // first == mb - 1, payload_len);
1538 if (gst_rtp_h263_pay_B_fragment_push (rtph263pay, context, gob, first,
1539 mb - 1, &boundry)) {
1540 GST_ERROR ("Oooops, there was an error sending");
1547 ("------------------------- END PACKAGE ----------------------");
1549 ("------------------------- NEW PACKAGE ----------------------");
1554 GST_DEBUG ("Remainder first: %d, MB: %d", first, mb);
1555 if (payload_len != 0) {
1556 if (gst_rtp_h263_pay_B_fragment_push (rtph263pay, context, gob, first,
1557 mb - 1, &boundry)) {
1558 GST_ERROR ("Oooops, there was an error sending!");
1563 /*---------- END OF MODE B FRAGMENTATION ----------*/
1571 static GstFlowReturn
1572 gst_rtp_h263_send_entire_frame (GstRtpH263Pay * rtph263pay,
1573 GstRtpH263PayContext * context)
1575 GstRtpH263PayPackage *pack;
1577 gst_rtp_h263_pay_package_new (rtph263pay->data,
1578 rtph263pay->data + rtph263pay->available_data,
1579 rtph263pay->available_data, 0, 0, NULL, TRUE);
1580 pack->mode = GST_RTP_H263_PAYLOAD_HEADER_MODE_A;
1582 GST_DEBUG ("Available data: %d", rtph263pay->available_data);
1585 gst_rtp_buffer_new_allocate (pack->payload_len +
1586 GST_RTP_H263_PAYLOAD_HEADER_MODE_A, 0, 0);
1588 return gst_rtp_h263_pay_push (rtph263pay, context, pack);
1591 static GstFlowReturn
1592 gst_rtp_h263_pay_flush (GstRtpH263Pay * rtph263pay)
1596 * FIXME: GSTUF bits are ignored right now,
1597 * - not using EBIT/SBIT payload header fields in mode A fragmentation - ffmpeg doesn't need them, but others?
1601 GstRtpH263PayContext *context;
1605 context = (GstRtpH263PayContext *) g_malloc0 (sizeof (GstRtpH263PayContext));
1607 rtph263pay->payload.mtu - (MTU_SECURITY_OFFSET + GST_RTP_HEADER_LEN +
1608 GST_RTP_H263_PAYLOAD_HEADER_MODE_C);
1610 GST_DEBUG ("MTU: %d", context->mtu);
1611 rtph263pay->available_data = gst_adapter_available (rtph263pay->adapter);
1612 if (rtph263pay->available_data == 0) {
1617 /* Get a pointer to all the data for the frame */
1619 (guint8 *) gst_adapter_map (rtph263pay->adapter,
1620 rtph263pay->available_data);
1622 /* Picture header */
1623 context->piclayer = (GstRtpH263PayPic *) rtph263pay->data;
1625 if (context->piclayer->ptype_pictype == 0)
1626 GST_DEBUG ("We got an I-frame");
1628 GST_DEBUG ("We got a P-frame");
1630 context->cpm = rtph263pay->data[6] >> 7;
1632 GST_DEBUG ("CPM: %d", context->cpm);
1634 GST_DEBUG ("Payload length is: %d", rtph263pay->available_data);
1637 * - MODE A - If normal, I and P frames, -> mode A
1638 * - GOB layer fragmentation
1639 * - MODE B - If normal, I and P frames, but GOBs > mtu
1640 * - MB layer fragmentation
1641 * - MODE C - For P frames with PB option, but GOBs > mtu
1642 * - MB layer fragmentation
1644 if (rtph263pay->available_data + GST_RTP_H263_PAYLOAD_HEADER_MODE_A +
1645 GST_RTP_HEADER_LEN < context->mtu) {
1646 ret = gst_rtp_h263_send_entire_frame (rtph263pay, context);
1649 /*---------- FRAGMENTING THE FRAME BECAUSE TOO LARGE TO FIT IN MTU ----------*/
1650 GstRtpH263PayBoundry bound;
1653 gboolean forcea = FALSE;
1655 GST_DEBUG ("Frame too large for MTU");
1657 * Let's go trough all the data and fragment it untill end is reached
1660 gst_rtp_h263_pay_boundry_init (&bound, NULL, rtph263pay->data - 1, 0, 0);
1662 (GstRtpH263PayGob **) g_malloc0 (format_props[context->piclayer->
1663 ptype_srcformat][0] * sizeof (GstRtpH263PayGob *));
1666 for (i = 0; i < format_props[context->piclayer->ptype_srcformat][0]; i++) {
1667 GST_DEBUG ("Searching for gob %d", i);
1668 if (!gst_rtp_h263_pay_gobfinder (rtph263pay, &bound)) {
1671 ("No GOB's were found in data stream! Please enable RTP mode in encoder. Forcing mode A for now.");
1672 ret = gst_rtp_h263_send_entire_frame (rtph263pay, context);
1675 /* try to send fragments corresponding to found GOBs */
1681 context->gobs[i] = gst_rtp_h263_pay_gob_new (&bound, i);
1682 //FIXME - encoders may generate an EOS gob that has to be processed
1684 ("Gob values are: gobn: %d, start: %p len: %d ebit: %d sbit: %d", i,
1685 context->gobs[i]->start, context->gobs[i]->length,
1686 context->gobs[i]->ebit, context->gobs[i]->sbit);
1688 /* NOTE some places may still assume this to be the max possible */
1689 context->no_gobs = i;
1690 GST_DEBUG ("Found %d GOBS of maximum %d",
1691 context->no_gobs, format_props[context->piclayer->ptype_srcformat][0]);
1693 // Make packages smaller than MTU
1695 // - if ( GOB > MTU) -> B mode || C mode
1701 while (i < context->no_gobs) {
1703 if (context->gobs[i]->length >= context->mtu) {
1704 if (payload_len == 0) {
1706 GST_DEBUG ("GOB len > MTU");
1707 if (rtph263pay->prop_payload_mode || forcea) {
1708 payload_len = context->gobs[i]->length;
1711 if (!context->piclayer->ptype_pbmode) {
1712 GST_DEBUG ("MODE B on GOB %d needed", i);
1713 if (!gst_rtp_h263_pay_mode_B_fragment (rtph263pay, context,
1714 context->gobs[i])) {
1715 GST_ERROR ("There was an error fragmenting in mode B");
1716 return GST_FLOW_ERROR;
1720 GST_ERROR ("MODE C on GOB %d needed, but not supported yet", i);
1721 /*if(!gst_rtp_h263_pay_mode_C_fragment(rtph263pay, context, context->gobs[i])) {
1723 GST_ERROR("There was an error fragmenting in mode C");
1734 goto payload_a_push;
1738 if (payload_len + context->gobs[i]->length < context->mtu) {
1739 GST_DEBUG ("GOB %d fills mtu", i);
1740 payload_len += context->gobs[i]->length;
1742 if (i == context->no_gobs) {
1743 GST_DEBUG ("LAST GOB %d", i);
1744 goto payload_a_push;
1749 GST_DEBUG ("Pushing GOBS %d to %d because payload size is %d", first,
1750 first == i ? i : i - 1, payload_len);
1751 gst_rtp_h263_pay_A_fragment_push (rtph263pay, context, first,
1752 first == i ? i : i - 1);
1759 GST_DEBUG ("Pushing GOBS %d to %d because payload size is %d", first, i,
1761 gst_rtp_h263_pay_A_fragment_push (rtph263pay, context, first, i);
1768 }/*---------- END OF FRAGMENTATION ----------*/
1770 /* Flush the input buffer data */
1773 gst_rtp_h263_pay_context_destroy (context,
1774 context->piclayer->ptype_srcformat);
1775 gst_adapter_unmap (rtph263pay->adapter);
1776 gst_adapter_flush (rtph263pay->adapter, rtph263pay->available_data);
1781 static GstFlowReturn
1782 gst_rtp_h263_pay_handle_buffer (GstRTPBasePayload * payload, GstBuffer * buffer)
1785 GstRtpH263Pay *rtph263pay;
1788 GST_DEBUG ("-------------------- NEW FRAME ---------------");
1789 rtph263pay = GST_RTP_H263_PAY (payload);
1791 rtph263pay->first_ts = GST_BUFFER_TIMESTAMP (buffer);
1793 /* we always encode and flush a full picture */
1794 gst_adapter_push (rtph263pay->adapter, buffer);
1795 ret = gst_rtp_h263_pay_flush (rtph263pay);
1796 GST_DEBUG ("-------------------- END FRAME ---------------");
1802 gst_rtp_h263_pay_plugin_init (GstPlugin * plugin)
1804 return gst_element_register (plugin, "rtph263pay",
1805 GST_RANK_SECONDARY, GST_TYPE_RTP_H263_PAY);