2 * iaxclient: a cross-platform IAX softphone library
5 * Copyright (C) 2003-2006, Horizon Wimba, Inc.
6 * Copyright (C) 2007, Wimba, Inc.
9 * Steve Kann <stevek@stevek.com>
10 * Mihai Balea <mihai at hates dot ms>
12 * This program is free software, distributed under the terms of
13 * the GNU Lesser (Library) General Public License.
17 * Some comments about Theora streaming
18 * Theora video codec has two problems when it comes to streaming
19 * and broadcasting video:
21 * - Large headers that need to be passed from the encoder to the decoder
22 * to initialize it. The conventional wisdom says we should transfer the
23 * headers out of band, but that complicates things with IAX, which does
24 * not have a separate signalling channel. Also, it makes things really
25 * difficult in a video conference scenario, where video gets switched
26 * between participants regularly. To solve this issue, we initialize
27 * the encoder and the decoder at the same time, using the headers from
28 * the local encoder to initialize the decoder. This works if the
29 * endpoints use the exact same version of Theora and the exact same
30 * parameters for initialization.
32 * - No support for splitting the frame into multiple slices. Frames can
33 * be relatively large. For a 320x240 video stream, you can see key
34 * frames larger than 9KB, which is the maximum UDP packet size on Mac
35 * OS X. To work around this limitation, we use the slice API to fragment
36 * encoded frames to a reasonable size that UDP can safely transport
38 * Other miscellaneous comments:
40 * - For quality reasons, when we detect a video stream switch, we reject all
41 * incoming frames until we receive a key frame.
43 * - Theora only accepts video that has dimensions multiple of 16. If we combine
44 * his with a 4:3 aspect ratio requirement, we get a very limited number
45 * of available resolutions. To work around this limitation, we pad the video
46 * on encoding, up to the closest multiple of 16. On the decoding side, we
47 * remove the padding. This way, video resolution can be any multiple of 2
49 * We should probably look more into this (how to deal with missing and
50 * out of order slices)
54 #include "iaxclient_lib.h"
57 #include "codec_theora.h"
58 #include <theora/theora.h>
60 #define MAX_SLICE_SIZE 8000
67 struct deslicer_context *dsc;
77 struct slicer_context *sc;
78 unsigned char *pad_buffer;
81 static void destroy( struct iaxc_video_codec *c)
83 struct theora_encoder *e;
84 struct theora_decoder *d;
91 e = (struct theora_encoder *)c->encstate;
95 free_slicer_context(e->sc);
96 theora_comment_clear(&e->tc);
97 theora_info_clear(&e->ti);
103 d = (struct theora_decoder *)c->decstate;
105 free_deslicer_context(d->dsc);
106 theora_comment_clear(&d->tc);
107 theora_info_clear(&d->ti);
108 theora_clear(&d->td);
114 static int decode(struct iaxc_video_codec *c, int inlen, const char *in,
115 int *outlen, char *out)
117 struct theora_decoder *d;
127 if ( !c || !c->decstate || !in || inlen <= 0 || !out || !outlen )
131 d = (struct theora_decoder *)c->decstate;
135 frame = deslice(in, inlen, &flen, d->dsc);
139 /* decode into an OP structure */
140 memset(&op, 0, sizeof(op));
142 op.packet = (unsigned char *)frame;
144 /* reject all incoming frames until we get a key frame */
145 if ( !d->got_key_frame )
147 if ( theora_packet_iskeyframe(&op) )
148 d->got_key_frame = 1;
153 if ( theora_decode_packetin(&d->td, &op) == OC_BADPACKET )
156 "codec_theora: warning: theora_decode_packetin says bad packet\n");
160 w = d->ti.frame_width;
161 h = d->ti.frame_height;
164 my_out_len = d->ti.frame_width * d->ti.frame_height * 3 / 2;
166 /* make sure we have enough room for the goodies */
167 if ( *outlen < my_out_len )
169 fprintf(stderr, "codec_theora: not enough room for decoding\n");
173 /* finally, here's where we get our goodies */
174 if ( theora_decode_YUVout(&d->td, &picture) )
176 fprintf(stderr, "codec_theora: error getting our goodies\n");
181 memset(out, 127, my_out_len);
183 for( line = 0 ; line < d->ti.frame_height / 2 ; line++ )
186 memcpy(out + picture.y_width * 2 * line,
187 picture.y + 2 * line * picture.y_stride,
190 memcpy(out + picture.y_width * (2 * line + 1),
191 picture.y + (2 * line + 1) * picture.y_stride,
194 memcpy(out + (d->ti.frame_width * d->ti.frame_height) + line * d->ti.frame_width / 2,
195 picture.u + line * picture.uv_stride,
197 memcpy(out + (d->ti.frame_width * d->ti.frame_height * 5 / 4) + line * d->ti.frame_width / 2,
198 picture.v + line * picture.uv_stride,
202 *outlen = my_out_len;
207 // Pads a w by h frame to bring it up to pw by ph size using value
208 static void pad_channel(const char *src, int w, int h, unsigned char *dst,
209 int pw, int ph, unsigned char value)
215 // We don't need to pad each line, just copy the data
216 memcpy(dst, src, w * h);
219 // We DO need to pad each line
220 for ( i=0 ; i<h ; i++ )
222 memcpy(&dst[i*pw], &src[i*w], w);
223 memset(&dst[i*pw+w], value, pw-w);
226 // Pad the bottom of the frame if necessary
228 memset(dst + pw * h, value, (ph - h) * pw);
231 static int encode(struct iaxc_video_codec * c, int inlen, const char * in,
232 struct slice_set_t * slice_set)
234 struct theora_encoder *e;
239 if ( !c || !c->encstate || !in || !slice_set )
242 e = (struct theora_encoder *)c->encstate;
244 // Prepare the YUV buffer
245 if ( e->needs_padding )
247 // We copy a padded image into the pad buffer and set up the pointers
248 // Use pad_channel for each of the YUV channels
249 // Use a pad value of 0 for luma and 128 for chroma
258 pad_channel(in + e->ti.frame_width * e->ti.frame_height,
259 e->ti.frame_width / 2,
260 e->ti.frame_height / 2,
261 e->pad_buffer + e->ti.width * e->ti.height,
266 pad_channel(in + e->ti.frame_width * e->ti.frame_height * 5 / 4,
267 e->ti.frame_width / 2,
268 e->ti.frame_height / 2,
269 e->pad_buffer + e->ti.width * e->ti.height * 5 / 4,
274 picture.y = e->pad_buffer;
277 // use the original buffer
278 picture.y = (unsigned char *)in;
280 picture.u = picture.y + e->ti.width * e->ti.height;
281 picture.v = picture.u + e->ti.width * e->ti.height / 4;
282 picture.y_width = e->ti.width;
283 picture.y_height = e->ti.height;
284 picture.y_stride = e->ti.width;
285 picture.uv_width = e->ti.width / 2;
286 picture.uv_height = e->ti.height / 2;
287 picture.uv_stride = e->ti.width / 2;
289 // Send data in for encoding
290 if ( theora_encode_YUVin(&e->td, &picture) )
292 fprintf(stderr, "codec_theora: failed theora_encode_YUVin\n");
296 // Get data from the encoder
297 if ( theora_encode_packetout(&e->td, 0, &op) != 1 )
299 fprintf(stderr, "codec_theora: failed theora_encode_packetout\n");
303 // Check to see if we have a key frame
304 slice_set->key_frame = theora_packet_iskeyframe(&op) == 1;
307 slice((char *)op.packet, op.bytes, slice_set, e->sc);
312 struct iaxc_video_codec *codec_video_theora_new(int format, int w, int h,
313 int framerate, int bitrate, int fragsize)
315 struct iaxc_video_codec *c;
316 struct theora_encoder *e;
317 struct theora_decoder *d;
318 unsigned short source_id;
319 ogg_packet headerp, commentp, tablep;
321 /* Basic sanity checks */
322 if ( w <= 0 || h <= 0 || framerate <= 0 || bitrate <= 0 || fragsize <= 0 )
324 fprintf(stderr, "codec_theora: bogus codec params: %d %d %d %d %d\n",
325 w, h, framerate, bitrate, fragsize);
329 if ( w % 2 || h % 2 )
331 fprintf(stderr, "codec_theora: video dimensions must be multiples of 2\n");
335 if ( fragsize > MAX_SLICE_SIZE )
336 fragsize = MAX_SLICE_SIZE;
338 c = (struct iaxc_video_codec *)calloc(sizeof(struct iaxc_video_codec), 1);
343 c->decstate = calloc(sizeof(struct theora_decoder), 1);
348 c->encstate = calloc(sizeof(struct theora_encoder), 1);
356 c->framerate = framerate;
357 c->bitrate = bitrate;
358 c->fragsize = fragsize;
362 c->destroy = destroy;
364 e = (struct theora_encoder *)c->encstate;
365 d = (struct theora_decoder *)c->decstate;
368 // Generate random source id
369 srand((unsigned int)time(0));
370 source_id = rand() & 0xffff;
371 e->sc = create_slicer_context(source_id, fragsize);
376 /* set up some parameters in the contexts */
378 theora_info_init(&e->ti);
380 /* set up common parameters */
381 e->ti.frame_width = w;
382 e->ti.frame_height = h;
383 e->ti.width = ((w - 1) / 16 + 1) * 16;
384 e->ti.height = ((h - 1) / 16 + 1) * 16;
388 // We set up a padded frame with dimensions that are multiple of 16
389 // We allocate a buffer to hold this frame
390 e->needs_padding = e->ti.width != e->ti.frame_width ||
391 e->ti.height != e->ti.frame_height;
393 if ( e->needs_padding )
395 e->pad_buffer = (unsigned char *)
396 malloc(e->ti.width * e->ti.height * 3 / 2);
398 if ( !e->pad_buffer )
406 e->ti.fps_numerator = framerate;
407 e->ti.fps_denominator = 1;
409 e->ti.aspect_numerator = 1;
410 e->ti.aspect_denominator = 1;
412 e->ti.colorspace = OC_CS_UNSPECIFIED;
413 e->ti.pixelformat = OC_PF_420;
415 e->ti.target_bitrate = bitrate;
419 e->ti.dropframes_p = 0;
421 e->ti.keyframe_auto_p = 0;
422 e->ti.keyframe_frequency = framerate;
423 e->ti.keyframe_frequency_force = framerate;
424 e->ti.keyframe_data_target_bitrate = bitrate * 3;
425 e->ti.keyframe_auto_threshold = 80;
426 e->ti.keyframe_mindistance = 8;
427 e->ti.noise_sensitivity = 0;
429 if ( theora_encode_init(&e->td, &e->ti) )
432 // Obtain the encoder headers and set up the decoder headers from
433 // data in the encoder headers
434 memset(&headerp, 0, sizeof(headerp));
435 memset(&commentp, 0, sizeof(commentp));
436 memset(&tablep, 0, sizeof(tablep));
438 // Set up the decoder using the encoder headers
439 theora_info_init(&d->ti);
440 theora_comment_init(&d->tc);
441 theora_comment_init(&e->tc);
443 if ( theora_encode_header(&e->td, &headerp) )
448 if ( theora_decode_header(&d->ti, &d->tc, &headerp) )
451 if ( theora_encode_comment(&e->tc, &commentp) )
454 if ( theora_decode_header(&d->ti, &d->tc, &commentp) )
457 theora_comment_clear(&e->tc);
459 if ( theora_encode_tables(&e->td, &tablep) )
462 if ( theora_decode_header(&d->ti, &d->tc, &tablep) )
465 if ( theora_decode_init(&d->td, &d->ti) )
468 d->got_key_frame = 0;
470 // Initialize deslicer context
471 d->dsc = create_deslicer_context(c->fragsize);
475 strcpy(c->name, "Theora");
479 fprintf(stderr, "codec_theora: failed to initialize encoder or decoder\n");
485 e = (struct theora_encoder *)c->encstate;
487 free_slicer_context(e->sc);
492 d = (struct theora_decoder *)c->decstate;
494 free_deslicer_context(d->dsc);