1 /*****************************************************************************
2 * theora.c: theora decoder module making use of libtheora.
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: theora.c,v 1.14 2003/11/16 21:07:30 gbazin Exp $
7 * Authors: Gildas Bazin <gbazin@netcourrier.com>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
27 #include <stdlib.h> /* malloc(), free() */
28 #include <string.h> /* memcpy(), memset() */
31 #include <vlc/decoder.h>
32 #include <vlc/input.h>
36 #include <theora/theora.h>
38 /*****************************************************************************
39 * decoder_sys_t : theora decoder descriptor
40 *****************************************************************************/
44 vlc_bool_t b_packetizer;
54 theora_info ti; /* theora bitstream settings */
55 theora_comment tc; /* theora comment header */
56 theora_state td; /* theora bitstream user comments */
64 /*****************************************************************************
66 *****************************************************************************/
67 static int OpenDecoder ( vlc_object_t * );
68 static int OpenPacketizer( vlc_object_t * );
69 static void CloseDecoder ( vlc_object_t * );
71 static void *DecodeBlock ( decoder_t *, block_t ** );
72 static void *ProcessPacket ( decoder_t *, ogg_packet *, block_t ** );
74 static picture_t *DecodePacket( decoder_t *, ogg_packet * );
76 static void ParseTheoraComments( decoder_t * );
77 static void theora_CopyPicture( decoder_t *, picture_t *, yuv_buffer * );
79 static int OpenEncoder( vlc_object_t *p_this );
80 static void CloseEncoder( vlc_object_t *p_this );
81 static block_t *Headers( encoder_t *p_enc );
82 static block_t *Encode( encoder_t *p_enc, picture_t *p_pict );
84 /*****************************************************************************
86 *****************************************************************************/
88 set_description( _("Theora video decoder") );
89 set_capability( "decoder", 100 );
90 set_callbacks( OpenDecoder, CloseDecoder );
91 add_shortcut( "theora" );
94 set_description( _("Theora video packetizer") );
95 set_capability( "packetizer", 100 );
96 set_callbacks( OpenPacketizer, CloseDecoder );
97 add_shortcut( "theora" );
100 set_description( _("Theora video encoder") );
101 set_capability( "encoder", 100 );
102 set_callbacks( OpenEncoder, CloseEncoder );
103 add_shortcut( "theora" );
106 /*****************************************************************************
107 * OpenDecoder: probe the decoder and return score
108 *****************************************************************************/
109 static int OpenDecoder( vlc_object_t *p_this )
111 decoder_t *p_dec = (decoder_t*)p_this;
112 decoder_sys_t *p_sys;
114 if( p_dec->fmt_in.i_codec != VLC_FOURCC('t','h','e','o') )
119 /* Allocate the memory needed to store the decoder's structure */
120 if( ( p_dec->p_sys = p_sys =
121 (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
123 msg_Err( p_dec, "out of memory" );
126 p_dec->p_sys->b_packetizer = VLC_FALSE;
130 /* Set output properties */
131 p_dec->fmt_out.i_cat = VIDEO_ES;
132 p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0');
135 p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **))
137 p_dec->pf_packetize = (block_t *(*)(decoder_t *, block_t **))
140 /* Init supporting Theora structures needed in header parsing */
141 theora_comment_init( &p_sys->tc );
142 theora_info_init( &p_sys->ti );
144 p_sys->i_headers = 0;
149 static int OpenPacketizer( vlc_object_t *p_this )
151 decoder_t *p_dec = (decoder_t*)p_this;
153 int i_ret = OpenDecoder( p_this );
155 if( i_ret == VLC_SUCCESS )
157 p_dec->p_sys->b_packetizer = VLC_TRUE;
158 p_dec->fmt_out.i_codec = VLC_FOURCC( 't', 'h', 'e', 'o' );
164 /****************************************************************************
165 * DecodeBlock: the whole thing
166 ****************************************************************************
167 * This function must be fed with ogg packets.
168 ****************************************************************************/
169 static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
171 decoder_sys_t *p_sys = p_dec->p_sys;
173 ogg_packet oggpacket;
175 if( !pp_block || !*pp_block ) return NULL;
179 /* Block to Ogg packet */
180 oggpacket.packet = p_block->p_buffer;
181 oggpacket.bytes = p_block->i_buffer;
182 oggpacket.granulepos = p_block->i_dts;
185 oggpacket.packetno = 0;
187 if( p_sys->i_headers == 0 )
189 /* Take care of the initial Theora header */
191 oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */
192 if( theora_decode_header( &p_sys->ti, &p_sys->tc, &oggpacket ) < 0 )
194 msg_Err( p_dec, "This bitstream does not contain Theora "
196 block_Release( p_block );
201 /* Set output properties */
202 p_dec->fmt_out.video.i_width = p_sys->ti.width;
203 p_dec->fmt_out.video.i_height = p_sys->ti.height;
205 if( p_sys->ti.aspect_denominator )
206 p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR *
207 p_sys->ti.aspect_numerator / p_sys->ti.aspect_denominator;
209 p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR *
210 p_sys->ti.frame_width / p_sys->ti.frame_height;
212 msg_Dbg( p_dec, "%dx%d %.02f fps video, frame content "
213 "is %dx%d with offset (%d,%d)",
214 p_sys->ti.width, p_sys->ti.height,
215 (double)p_sys->ti.fps_numerator/p_sys->ti.fps_denominator,
216 p_sys->ti.frame_width, p_sys->ti.frame_height,
217 p_sys->ti.offset_x, p_sys->ti.offset_y );
219 return ProcessPacket( p_dec, &oggpacket, pp_block );
222 if( p_sys->i_headers == 1 )
224 /* The next packet in order is the comments header */
225 if( theora_decode_header( &p_sys->ti, &p_sys->tc, &oggpacket ) < 0 )
227 msg_Err( p_dec, "2nd Theora header is corrupted" );
232 ParseTheoraComments( p_dec );
234 return ProcessPacket( p_dec, &oggpacket, pp_block );
237 if( p_sys->i_headers == 2 )
239 /* The next packet in order is the codebooks header
240 We need to watch out that this packet is not missing as a
241 missing or corrupted header is fatal. */
242 if( theora_decode_header( &p_sys->ti, &p_sys->tc, &oggpacket ) < 0 )
244 msg_Err( p_dec, "3rd Theora header is corrupted" );
249 if( !p_sys->b_packetizer )
251 /* We have all the headers, initialize decoder */
252 theora_decode_init( &p_sys->td, &p_sys->ti );
255 return ProcessPacket( p_dec, &oggpacket, pp_block );
258 return ProcessPacket( p_dec, &oggpacket, pp_block );
261 /*****************************************************************************
262 * ProcessPacket: processes a theora packet.
263 *****************************************************************************/
264 static void *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
267 decoder_sys_t *p_sys = p_dec->p_sys;
268 block_t *p_block = *pp_block;
271 /* Date management */
272 if( p_block->i_pts > 0 && p_block->i_pts != p_sys->i_pts )
274 p_sys->i_pts = p_block->i_pts;
277 if( p_sys->b_packetizer )
279 /* Date management */
280 p_block->i_dts = p_block->i_pts = p_sys->i_pts;
282 if( p_sys->i_headers >= 3 )
283 p_block->i_length = p_sys->i_pts - p_block->i_pts;
285 p_block->i_length = 0;
291 if( p_sys->i_headers >= 3 )
292 p_buf = DecodePacket( p_dec, p_oggpacket );
298 block_Release( p_block );
303 /* Date management */
304 p_sys->i_pts += ( I64C(1000000) * p_sys->ti.fps_denominator /
305 p_sys->ti.fps_numerator ); /* 1 frame per packet */
310 /*****************************************************************************
311 * DecodePacket: decodes a Theora packet.
312 *****************************************************************************/
313 static picture_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
315 decoder_sys_t *p_sys = p_dec->p_sys;
319 theora_decode_packetin( &p_sys->td, p_oggpacket );
322 theora_decode_YUVout( &p_sys->td, &yuv );
324 /* Get a new picture */
325 p_pic = p_dec->pf_vout_buffer_new( p_dec );
326 if( !p_pic ) return NULL;
328 theora_CopyPicture( p_dec, p_pic, &yuv );
330 p_pic->date = p_sys->i_pts;
335 /*****************************************************************************
336 * ParseTheoraComments: FIXME should be done in demuxer
337 *****************************************************************************/
338 static void ParseTheoraComments( decoder_t *p_dec )
340 input_thread_t *p_input = (input_thread_t *)p_dec->p_parent;
341 input_info_category_t *p_cat =
342 input_InfoCategory( p_input, _("Theora Comment") );
344 char *psz_name, *psz_value, *psz_comment;
345 while ( i < p_dec->p_sys->tc.comments )
347 psz_comment = strdup( p_dec->p_sys->tc.user_comments[i] );
350 msg_Warn( p_dec, "Out of memory" );
353 psz_name = psz_comment;
354 psz_value = strchr( psz_comment, '=' );
359 input_AddInfo( p_cat, psz_name, psz_value );
366 /*****************************************************************************
367 * CloseDecoder: theora decoder destruction
368 *****************************************************************************/
369 static void CloseDecoder( vlc_object_t *p_this )
371 decoder_t *p_dec = (decoder_t *)p_this;
372 decoder_sys_t *p_sys = p_dec->p_sys;
374 theora_info_clear( &p_sys->ti );
375 theora_comment_clear( &p_sys->tc );
380 /*****************************************************************************
381 * theora_CopyPicture: copy a picture from theora internal buffers to a
382 * picture_t structure.
383 *****************************************************************************/
384 static void theora_CopyPicture( decoder_t *p_dec, picture_t *p_pic,
387 int i_plane, i_line, i_width, i_dst_stride, i_src_stride;
388 int i_src_xoffset, i_src_yoffset;
389 uint8_t *p_dst, *p_src;
391 for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
393 p_dst = p_pic->p[i_plane].p_pixels;
394 p_src = i_plane ? (i_plane - 1 ? yuv->v : yuv->u ) : yuv->y;
395 i_width = p_pic->p[i_plane].i_visible_pitch;
396 i_dst_stride = p_pic->p[i_plane].i_pitch;
397 i_src_stride = i_plane ? yuv->uv_stride : yuv->y_stride;
398 i_src_xoffset = p_dec->p_sys->ti.offset_x;
399 i_src_yoffset = p_dec->p_sys->ti.offset_y;
406 p_src += (i_src_yoffset * i_src_stride + i_src_yoffset);
408 for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ )
410 p_dec->p_vlc->pf_memcpy( p_dst, p_src, i_width );
411 p_src += i_src_stride;
412 p_dst += i_dst_stride;
417 /*****************************************************************************
418 * encoder_sys_t : theora encoder descriptor
419 *****************************************************************************/
425 vlc_bool_t b_headers;
430 theora_info ti; /* theora bitstream settings */
431 theora_comment tc; /* theora comment header */
432 theora_state td; /* theora bitstream user comments */
440 /*****************************************************************************
441 * OpenEncoder: probe the encoder and return score
442 *****************************************************************************/
443 static int OpenEncoder( vlc_object_t *p_this )
445 encoder_t *p_enc = (encoder_t *)p_this;
446 encoder_sys_t *p_sys = p_enc->p_sys;
448 if( p_enc->fmt_out.i_codec != VLC_FOURCC('t','h','e','o') )
453 /* Allocate the memory needed to store the decoder's structure */
454 if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
456 msg_Err( p_enc, "out of memory" );
459 p_enc->p_sys = p_sys;
461 p_enc->pf_header = Headers;
462 p_enc->pf_encode_video = Encode;
463 p_enc->fmt_in.i_codec = VLC_FOURCC('I','4','2','0');
465 #define frame_x_offset 0
466 #define frame_y_offset 0
473 theora_info_init( &p_sys->ti );
475 p_sys->ti.width = p_enc->fmt_in.video.i_width;
476 p_sys->ti.height = p_enc->fmt_in.video.i_height;
477 p_sys->ti.frame_width = p_enc->fmt_in.video.i_width;
478 p_sys->ti.frame_height = p_enc->fmt_in.video.i_height;
479 p_sys->ti.offset_x = frame_x_offset;
480 p_sys->ti.offset_y = frame_y_offset;
481 p_sys->ti.fps_numerator = video_hzn;
482 p_sys->ti.fps_denominator = video_hzd;
483 p_sys->ti.aspect_numerator = video_an;
484 p_sys->ti.aspect_denominator = video_ad;
485 p_sys->ti.colorspace = not_specified;
486 p_sys->ti.target_bitrate = p_enc->fmt_out.i_bitrate;
487 p_sys->ti.quality = video_q;
489 p_sys->ti.dropframes_p = 0;
490 p_sys->ti.quick_p = 1;
491 p_sys->ti.keyframe_auto_p = 1;
492 p_sys->ti.keyframe_frequency = 64;
493 p_sys->ti.keyframe_frequency_force = 64;
494 p_sys->ti.keyframe_data_target_bitrate = p_enc->fmt_out.i_bitrate * 1.5;
495 p_sys->ti.keyframe_auto_threshold = 80;
496 p_sys->ti.keyframe_mindistance = 8;
497 p_sys->ti.noise_sensitivity = 1;
499 theora_encode_init( &p_sys->td, &p_sys->ti );
500 theora_info_clear( &p_sys->ti );
501 theora_comment_init( &p_sys->tc );
503 p_sys->b_headers = VLC_FALSE;
508 /****************************************************************************
509 * Encode: the whole thing
510 ****************************************************************************
511 * This function spits out ogg packets.
512 ****************************************************************************/
513 static block_t *Headers( encoder_t *p_enc )
515 encoder_sys_t *p_sys = p_enc->p_sys;
516 block_t *p_chain = NULL;
518 /* Create theora headers */
519 if( !p_sys->b_headers )
521 ogg_packet oggpackets[3];
524 theora_encode_header( &p_sys->td, &oggpackets[0] );
525 theora_encode_comment( &p_sys->tc, &oggpackets[1] );
526 theora_encode_tables( &p_sys->td, &oggpackets[2] );
528 /* Ogg packet to block */
529 for( i = 0; i < 3; i++ )
531 block_t *p_block = block_New( p_enc, oggpackets[i].bytes );
532 memcpy( p_block->p_buffer, oggpackets[i].packet,
533 oggpackets[i].bytes );
534 p_block->i_dts = p_block->i_pts = p_block->i_length = 0;
535 block_ChainAppend( &p_chain, p_block );
538 p_sys->b_headers = VLC_TRUE;
544 /****************************************************************************
545 * Encode: the whole thing
546 ****************************************************************************
547 * This function spits out ogg packets.
548 ****************************************************************************/
549 static block_t *Encode( encoder_t *p_enc, picture_t *p_pict )
551 encoder_sys_t *p_sys = p_enc->p_sys;
552 ogg_packet oggpacket;
556 /* Theora is a one-frame-in, one-frame-out system. Submit a frame
557 * for compression and pull out the packet. */
559 yuv.y_width = p_pict->p[0].i_visible_pitch;
560 yuv.y_height = p_pict->p[0].i_lines;
561 yuv.y_stride = p_pict->p[0].i_pitch;
563 yuv.uv_width = p_pict->p[1].i_visible_pitch;
564 yuv.uv_height = p_pict->p[1].i_lines;
565 yuv.uv_stride = p_pict->p[1].i_pitch;
567 yuv.y = p_pict->p[0].p_pixels;
568 yuv.u = p_pict->p[1].p_pixels;
569 yuv.v = p_pict->p[2].p_pixels;
571 if( theora_encode_YUVin( &p_sys->td, &yuv ) < 0 )
573 msg_Warn( p_enc, "failed encoding a frame" );
577 theora_encode_packetout( &p_sys->td, 0, &oggpacket );
579 /* Ogg packet to block */
580 p_block = block_New( p_enc, oggpacket.bytes );
581 memcpy( p_block->p_buffer, oggpacket.packet, oggpacket.bytes );
582 p_block->i_dts = p_block->i_pts = p_pict->date;;
587 /*****************************************************************************
588 * CloseEncoder: theora encoder destruction
589 *****************************************************************************/
590 static void CloseEncoder( vlc_object_t *p_this )
592 encoder_t *p_enc = (encoder_t *)p_this;
593 encoder_sys_t *p_sys = p_enc->p_sys;
595 theora_info_clear( &p_sys->ti );
596 theora_comment_clear( &p_sys->tc );