]> git.sesse.net Git - vlc/blob - modules/codec/theora.c
string review
[vlc] / modules / codec / theora.c
1 /*****************************************************************************
2  * theora.c: theora decoder module making use of libtheora.
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: theora.c,v 1.23 2004/01/25 18:20:12 bigben Exp $
6  *
7  * Authors: Gildas Bazin <gbazin@netcourrier.com>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <vlc/vlc.h>
28 #include <vlc/decoder.h>
29 #include "input_ext-plugins.h"
30 #include "vlc_playlist.h"
31
32 #include <ogg/ogg.h>
33
34 #include <theora/theora.h>
35
36 /*****************************************************************************
37  * decoder_sys_t : theora decoder descriptor
38  *****************************************************************************/
39 struct decoder_sys_t
40 {
41     /* Module mode */
42     vlc_bool_t b_packetizer;
43
44     /*
45      * Input properties
46      */
47     int i_headers;
48
49     /*
50      * Theora properties
51      */
52     theora_info      ti;                        /* theora bitstream settings */
53     theora_comment   tc;                            /* theora comment header */
54     theora_state     td;                   /* theora bitstream user comments */
55
56     /*
57      * Common properties
58      */
59     mtime_t i_pts;
60 };
61
62 /*****************************************************************************
63  * Local prototypes
64  *****************************************************************************/
65 static int  OpenDecoder   ( vlc_object_t * );
66 static int  OpenPacketizer( vlc_object_t * );
67 static void CloseDecoder  ( vlc_object_t * );
68
69 static void *DecodeBlock  ( decoder_t *, block_t ** );
70 static void *ProcessPacket ( decoder_t *, ogg_packet *, block_t ** );
71
72 static picture_t *DecodePacket( decoder_t *, ogg_packet * );
73
74 static void ParseTheoraComments( decoder_t * );
75 static void theora_CopyPicture( decoder_t *, picture_t *, yuv_buffer * );
76
77 static int  OpenEncoder( vlc_object_t *p_this );
78 static void CloseEncoder( vlc_object_t *p_this );
79 static block_t *Headers( encoder_t *p_enc );
80 static block_t *Encode( encoder_t *p_enc, picture_t *p_pict );
81
82 /*****************************************************************************
83  * Module descriptor
84  *****************************************************************************/
85 vlc_module_begin();
86     set_description( _("Theora video decoder") );
87     set_capability( "decoder", 100 );
88     set_callbacks( OpenDecoder, CloseDecoder );
89     add_shortcut( "theora" );
90
91     add_submodule();
92     set_description( _("Theora video packetizer") );
93     set_capability( "packetizer", 100 );
94     set_callbacks( OpenPacketizer, CloseDecoder );
95     add_shortcut( "theora" );
96
97     add_submodule();
98     set_description( _("Theora video encoder") );
99     set_capability( "encoder", 100 );
100     set_callbacks( OpenEncoder, CloseEncoder );
101     add_shortcut( "theora" );
102 vlc_module_end();
103
104 /*****************************************************************************
105  * OpenDecoder: probe the decoder and return score
106  *****************************************************************************/
107 static int OpenDecoder( vlc_object_t *p_this )
108 {
109     decoder_t *p_dec = (decoder_t*)p_this;
110     decoder_sys_t *p_sys;
111
112     if( p_dec->fmt_in.i_codec != VLC_FOURCC('t','h','e','o') )
113     {
114         return VLC_EGENERIC;
115     }
116
117     /* Allocate the memory needed to store the decoder's structure */
118     if( ( p_dec->p_sys = p_sys =
119           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
120     {
121         msg_Err( p_dec, "out of memory" );
122         return VLC_EGENERIC;
123     }
124     p_dec->p_sys->b_packetizer = VLC_FALSE;
125
126     p_sys->i_pts = 0;
127
128     /* Set output properties */
129     p_dec->fmt_out.i_cat = VIDEO_ES;
130     p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0');
131
132     /* Set callbacks */
133     p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **))
134         DecodeBlock;
135     p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
136         DecodeBlock;
137
138     /* Init supporting Theora structures needed in header parsing */
139     theora_comment_init( &p_sys->tc );
140     theora_info_init( &p_sys->ti );
141
142     p_sys->i_headers = 0;
143
144     return VLC_SUCCESS;
145 }
146
147 static int OpenPacketizer( vlc_object_t *p_this )
148 {
149     decoder_t *p_dec = (decoder_t*)p_this;
150
151     int i_ret = OpenDecoder( p_this );
152
153     if( i_ret == VLC_SUCCESS )
154     {
155         p_dec->p_sys->b_packetizer = VLC_TRUE;
156         p_dec->fmt_out.i_codec = VLC_FOURCC( 't', 'h', 'e', 'o' );
157     }
158
159     return i_ret;
160 }
161
162 /****************************************************************************
163  * DecodeBlock: the whole thing
164  ****************************************************************************
165  * This function must be fed with ogg packets.
166  ****************************************************************************/
167 static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
168 {
169     decoder_sys_t *p_sys = p_dec->p_sys;
170     block_t *p_block;
171     ogg_packet oggpacket;
172
173     if( !pp_block || !*pp_block ) return NULL;
174
175     p_block = *pp_block;
176
177     /* Block to Ogg packet */
178     oggpacket.packet = p_block->p_buffer;
179     oggpacket.bytes = p_block->i_buffer;
180     oggpacket.granulepos = p_block->i_dts;
181     oggpacket.b_o_s = 0;
182     oggpacket.e_o_s = 0;
183     oggpacket.packetno = 0;
184
185     if( p_sys->i_headers == 0 )
186     {
187         /* Take care of the initial Theora header */
188
189         oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */
190         if( theora_decode_header( &p_sys->ti, &p_sys->tc, &oggpacket ) < 0 )
191         {
192             msg_Err( p_dec, "This bitstream does not contain Theora "
193                      "video data." );
194             block_Release( p_block );
195             return NULL;
196         }
197         p_sys->i_headers++;
198
199         /* Set output properties */
200         p_dec->fmt_out.video.i_width = p_sys->ti.width;
201         p_dec->fmt_out.video.i_height = p_sys->ti.height;
202
203         if( p_sys->ti.aspect_denominator )
204             p_dec->fmt_out.video.i_aspect = ((int64_t)VOUT_ASPECT_FACTOR) *
205                 p_sys->ti.aspect_numerator / p_sys->ti.aspect_denominator;
206         else
207             p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR *
208                 p_sys->ti.frame_width / p_sys->ti.frame_height;
209
210         msg_Dbg( p_dec, "%dx%d %.02f fps video, frame content "
211                  "is %dx%d with offset (%d,%d).",
212                  p_sys->ti.width, p_sys->ti.height,
213                  (double)p_sys->ti.fps_numerator/p_sys->ti.fps_denominator,
214                  p_sys->ti.frame_width, p_sys->ti.frame_height,
215                  p_sys->ti.offset_x, p_sys->ti.offset_y );
216
217         return ProcessPacket( p_dec, &oggpacket, pp_block );
218     }
219
220     if( p_sys->i_headers == 1 )
221     {
222         /* The next packet in order is the comments header */
223         if( theora_decode_header( &p_sys->ti, &p_sys->tc, &oggpacket ) < 0 )
224         {
225             msg_Err( p_dec, "2nd Theora header is corrupted." );
226             return NULL;
227         }
228         p_sys->i_headers++;
229
230         ParseTheoraComments( p_dec );
231
232         return ProcessPacket( p_dec, &oggpacket, pp_block );
233     }
234
235     if( p_sys->i_headers == 2 )
236     {
237         /* The next packet in order is the codebooks header
238            We need to watch out that this packet is not missing as a
239            missing or corrupted header is fatal. */
240         if( theora_decode_header( &p_sys->ti, &p_sys->tc, &oggpacket ) < 0 )
241         {
242             msg_Err( p_dec, "3rd Theora header is corrupted." );
243             return NULL;
244         }
245         p_sys->i_headers++;
246
247         if( !p_sys->b_packetizer )
248         {
249             /* We have all the headers, initialize decoder */
250             theora_decode_init( &p_sys->td, &p_sys->ti );
251         }
252
253         return ProcessPacket( p_dec, &oggpacket, pp_block );
254     }
255
256     return ProcessPacket( p_dec, &oggpacket, pp_block );
257 }
258
259 /*****************************************************************************
260  * ProcessPacket: processes a theora packet.
261  *****************************************************************************/
262 static void *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
263                             block_t **pp_block )
264 {
265     decoder_sys_t *p_sys = p_dec->p_sys;
266     block_t *p_block = *pp_block;
267     void *p_buf;
268
269     /* Date management */
270     if( p_block->i_pts > 0 && p_block->i_pts != p_sys->i_pts )
271     {
272         p_sys->i_pts = p_block->i_pts;
273     }
274
275     if( p_sys->b_packetizer )
276     {
277         /* Date management */
278         p_block->i_dts = p_block->i_pts = p_sys->i_pts;
279
280         if( p_sys->i_headers >= 3 )
281             p_block->i_length = p_sys->i_pts - p_block->i_pts;
282         else
283             p_block->i_length = 0;
284
285         p_buf = p_block;
286     }
287     else
288     {
289         if( p_sys->i_headers >= 3 )
290             p_buf = DecodePacket( p_dec, p_oggpacket );
291         else
292             p_buf = NULL;
293
294         if( p_block )
295         {
296             block_Release( p_block );
297             *pp_block = NULL;
298         }
299     }
300
301     /* Date management */
302     p_sys->i_pts += ( I64C(1000000) * p_sys->ti.fps_denominator /
303                       p_sys->ti.fps_numerator ); /* 1 frame per packet */
304
305     return p_buf;
306 }
307
308 /*****************************************************************************
309  * DecodePacket: decodes a Theora packet.
310  *****************************************************************************/
311 static picture_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
312 {
313     decoder_sys_t *p_sys = p_dec->p_sys;
314     picture_t *p_pic;
315     yuv_buffer yuv;
316
317     theora_decode_packetin( &p_sys->td, p_oggpacket );
318
319     /* Decode */
320     theora_decode_YUVout( &p_sys->td, &yuv );
321
322     /* Get a new picture */
323     p_pic = p_dec->pf_vout_buffer_new( p_dec );
324     if( !p_pic ) return NULL;
325
326     theora_CopyPicture( p_dec, p_pic, &yuv );
327
328     p_pic->date = p_sys->i_pts;
329
330     return p_pic;
331 }
332
333 /*****************************************************************************
334  * ParseTheoraComments: FIXME should be done in demuxer
335  *****************************************************************************/
336 static void ParseTheoraComments( decoder_t *p_dec )
337 {
338     input_thread_t *p_input = (input_thread_t *)p_dec->p_parent;
339     input_info_category_t *p_cat =
340         input_InfoCategory( p_input, _("Theora comment") );
341     playlist_t *p_playlist = vlc_object_find( p_dec, VLC_OBJECT_PLAYLIST,
342                                               FIND_ANYWHERE );
343     int i = 0;
344     char *psz_name, *psz_value, *psz_comment;
345     while ( i < p_dec->p_sys->tc.comments )
346     {
347         psz_comment = strdup( p_dec->p_sys->tc.user_comments[i] );
348         if( !psz_comment )
349         {
350             msg_Warn( p_dec, "out of memory" );
351             break;
352         }
353         psz_name = psz_comment;
354         psz_value = strchr( psz_comment, '=' );
355         if( psz_value )
356         {
357             *psz_value = '\0';
358             psz_value++;
359             input_AddInfo( p_cat, psz_name, psz_value );
360             playlist_AddInfo( p_playlist, -1, _("Theora comment") ,
361                               psz_name, psz_value );
362         }
363         free( psz_comment );
364         i++;
365     }
366     if( p_playlist) vlc_object_release( p_playlist );
367 }
368
369 /*****************************************************************************
370  * CloseDecoder: theora decoder destruction
371  *****************************************************************************/
372 static void CloseDecoder( vlc_object_t *p_this )
373 {
374     decoder_t *p_dec = (decoder_t *)p_this;
375     decoder_sys_t *p_sys = p_dec->p_sys;
376
377     theora_info_clear( &p_sys->ti );
378     theora_comment_clear( &p_sys->tc );
379
380     free( p_sys );
381 }
382
383 /*****************************************************************************
384  * theora_CopyPicture: copy a picture from theora internal buffers to a
385  *                     picture_t structure.
386  *****************************************************************************/
387 static void theora_CopyPicture( decoder_t *p_dec, picture_t *p_pic,
388                                 yuv_buffer *yuv )
389 {
390     int i_plane, i_line, i_width, i_dst_stride, i_src_stride;
391     int i_src_xoffset, i_src_yoffset;
392     uint8_t *p_dst, *p_src;
393
394     for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
395     {
396         p_dst = p_pic->p[i_plane].p_pixels;
397         p_src = i_plane ? (i_plane - 1 ? yuv->v : yuv->u ) : yuv->y;
398         i_width = p_pic->p[i_plane].i_visible_pitch;
399         i_dst_stride  = p_pic->p[i_plane].i_pitch;
400         i_src_stride  = i_plane ? yuv->uv_stride : yuv->y_stride;
401         i_src_xoffset = p_dec->p_sys->ti.offset_x;
402         i_src_yoffset = p_dec->p_sys->ti.offset_y;
403         if( i_plane )
404         {
405             i_src_xoffset /= 2;
406             i_src_yoffset /= 2;
407         }
408
409         p_src += (i_src_yoffset * i_src_stride + i_src_yoffset);
410
411         for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ )
412         {
413             p_dec->p_vlc->pf_memcpy( p_dst, p_src, i_width );
414             p_src += i_src_stride;
415             p_dst += i_dst_stride;
416         }
417     }
418 }
419
420 /*****************************************************************************
421  * encoder_sys_t : theora encoder descriptor
422  *****************************************************************************/
423 struct encoder_sys_t
424 {
425     /*
426      * Input properties
427      */
428     vlc_bool_t b_headers;
429
430     /*
431      * Theora properties
432      */
433     theora_info      ti;                        /* theora bitstream settings */
434     theora_comment   tc;                            /* theora comment header */
435     theora_state     td;                   /* theora bitstream user comments */
436
437     /*
438      * Common properties
439      */
440     mtime_t i_pts;
441 };
442
443 /*****************************************************************************
444  * OpenEncoder: probe the encoder and return score
445  *****************************************************************************/
446 static int OpenEncoder( vlc_object_t *p_this )
447 {
448     encoder_t *p_enc = (encoder_t *)p_this;
449     encoder_sys_t *p_sys = p_enc->p_sys;
450
451     if( p_enc->fmt_out.i_codec != VLC_FOURCC('t','h','e','o') )
452     {
453         return VLC_EGENERIC;
454     }
455
456     if( p_enc->fmt_in.video.i_width % 16 ||
457         p_enc->fmt_in.video.i_height % 16 )
458     {
459         msg_Err( p_enc, "Theora video encoding requires dimensions which are "
460                  "multiples of 16. Which is not the case here (%dx%d).",
461                  p_enc->fmt_in.video.i_width, p_enc->fmt_in.video.i_height );
462         return VLC_EGENERIC;
463     }
464
465     /* Allocate the memory needed to store the decoder's structure */
466     if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
467     {
468         msg_Err( p_enc, "out of memory" );
469         return VLC_EGENERIC;
470     }
471     p_enc->p_sys = p_sys;
472
473     p_enc->pf_header = Headers;
474     p_enc->pf_encode_video = Encode;
475     p_enc->fmt_in.i_codec = VLC_FOURCC('I','4','2','0');
476
477 #define frame_x_offset 0
478 #define frame_y_offset 0
479 #define video_hzn 25
480 #define video_hzd 1
481 #define video_q 5
482
483     theora_info_init( &p_sys->ti );
484
485     p_sys->ti.width = p_enc->fmt_in.video.i_width;
486     p_sys->ti.height = p_enc->fmt_in.video.i_height;
487     p_sys->ti.frame_width = p_enc->fmt_in.video.i_width;
488     p_sys->ti.frame_height = p_enc->fmt_in.video.i_height;
489     p_sys->ti.offset_x = frame_x_offset;
490     p_sys->ti.offset_y = frame_y_offset;
491     p_sys->ti.fps_numerator = video_hzn;
492     p_sys->ti.fps_denominator = video_hzd;
493
494     if( p_enc->fmt_in.video.i_aspect )
495     {
496         p_sys->ti.aspect_numerator = p_enc->fmt_in.video.i_aspect;
497         p_sys->ti.aspect_denominator = VOUT_ASPECT_FACTOR;
498     }
499     else
500     {
501         p_sys->ti.aspect_numerator = 4;
502         p_sys->ti.aspect_denominator = 3;
503     }
504
505     p_sys->ti.target_bitrate = p_enc->fmt_out.i_bitrate;
506     p_sys->ti.quality = video_q;
507
508     p_sys->ti.dropframes_p = 0;
509     p_sys->ti.quick_p = 1;
510     p_sys->ti.keyframe_auto_p = 1;
511     p_sys->ti.keyframe_frequency = 64;
512     p_sys->ti.keyframe_frequency_force = 64;
513     p_sys->ti.keyframe_data_target_bitrate = p_enc->fmt_out.i_bitrate * 1.5;
514     p_sys->ti.keyframe_auto_threshold = 80;
515     p_sys->ti.keyframe_mindistance = 8;
516     p_sys->ti.noise_sensitivity = 1;
517
518     theora_encode_init( &p_sys->td, &p_sys->ti );
519     theora_info_clear( &p_sys->ti );
520     theora_comment_init( &p_sys->tc );
521
522     p_sys->b_headers = VLC_FALSE;
523
524     return VLC_SUCCESS;
525 }
526
527 /****************************************************************************
528  * Encode: the whole thing
529  ****************************************************************************
530  * This function spits out ogg packets.
531  ****************************************************************************/
532 static block_t *Headers( encoder_t *p_enc )
533 {
534     encoder_sys_t *p_sys = p_enc->p_sys;
535     block_t *p_chain = NULL;
536
537     /* Create theora headers */
538     if( !p_sys->b_headers )
539     {
540         ogg_packet oggpackets;
541         int i;
542         block_t *p_block;
543
544         /* Ogg packet to block */
545         for( i = 0; i < 3; i++ )
546         {
547             switch( i )
548             {
549             case 0:
550                 theora_encode_header( &p_sys->td, &oggpackets );
551                 break;
552             case 1:
553                 theora_encode_comment( &p_sys->tc, &oggpackets );
554                 break;
555             case 2:
556                 theora_encode_tables( &p_sys->td, &oggpackets );
557                 break;
558             }
559
560             p_block = block_New( p_enc, oggpackets.bytes );
561             memcpy( p_block->p_buffer, oggpackets.packet, oggpackets.bytes );
562             p_block->i_dts = p_block->i_pts = p_block->i_length = 0;
563             block_ChainAppend( &p_chain, p_block );
564         }
565
566         p_sys->b_headers = VLC_TRUE;
567     }
568
569     return p_chain;
570 }
571
572 /****************************************************************************
573  * Encode: the whole thing
574  ****************************************************************************
575  * This function spits out ogg packets.
576  ****************************************************************************/
577 static block_t *Encode( encoder_t *p_enc, picture_t *p_pict )
578 {
579     encoder_sys_t *p_sys = p_enc->p_sys;
580     ogg_packet oggpacket;
581     block_t *p_block;
582     yuv_buffer yuv;
583
584     /* Theora is a one-frame-in, one-frame-out system. Submit a frame
585      * for compression and pull out the packet. */
586
587     yuv.y_width  = p_pict->p[0].i_visible_pitch;
588     yuv.y_height = p_pict->p[0].i_lines;
589     yuv.y_stride = p_pict->p[0].i_pitch;
590
591     yuv.uv_width  = p_pict->p[1].i_visible_pitch;
592     yuv.uv_height = p_pict->p[1].i_lines;
593     yuv.uv_stride = p_pict->p[1].i_pitch;
594
595     yuv.y = p_pict->p[0].p_pixels;
596     yuv.u = p_pict->p[1].p_pixels;
597     yuv.v = p_pict->p[2].p_pixels;
598
599     if( theora_encode_YUVin( &p_sys->td, &yuv ) < 0 )
600     {
601         msg_Warn( p_enc, "failed encoding a frame" );
602         return NULL;
603     }
604
605     theora_encode_packetout( &p_sys->td, 0, &oggpacket );
606
607     /* Ogg packet to block */
608     p_block = block_New( p_enc, oggpacket.bytes );
609     memcpy( p_block->p_buffer, oggpacket.packet, oggpacket.bytes );
610     p_block->i_dts = p_block->i_pts = p_pict->date;;
611
612     return p_block;
613 }
614
615 /*****************************************************************************
616  * CloseEncoder: theora encoder destruction
617  *****************************************************************************/
618 static void CloseEncoder( vlc_object_t *p_this )
619 {
620     encoder_t *p_enc = (encoder_t *)p_this;
621     encoder_sys_t *p_sys = p_enc->p_sys;
622
623     theora_info_clear( &p_sys->ti );
624     theora_comment_clear( &p_sys->tc );
625
626     free( p_sys );
627 }