be3826796eb8b85c0b626c109992cd3c9be0b481
[vlc.git] / modules / codec / daala.c
1 /*****************************************************************************
2  * daala.c: daala codec module making use of libdaala.
3  *****************************************************************************
4  * Copyright (C) 2014 VLC authors and VideoLAN
5  *
6  * Authors: Tristan Matthews <le.businessman@gmail.com>
7  *   * Based on theora.c by: Gildas Bazin <gbazin@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_codec.h>
34 #include <vlc_meta.h>
35 #include "../demux/xiph.h"
36
37 #include <daala/codec.h>
38 #include <daala/daaladec.h>
39 #ifdef ENABLE_SOUT
40 #include <daala/daalaenc.h>
41 #endif
42
43 #include <limits.h>
44
45 /*****************************************************************************
46  * decoder_sys_t : daala decoder descriptor
47  *****************************************************************************/
48 typedef struct
49 {
50     /* Module mode */
51     bool b_packetizer;
52
53     /*
54      * Input properties
55      */
56     bool b_has_headers;
57
58     /*
59      * Daala properties
60      */
61     daala_info          di;       /* daala bitstream settings */
62     daala_comment       dc;       /* daala comment information */
63     daala_dec_ctx       *dcx;     /* daala decoder context */
64
65     /*
66      * Decoding properties
67      */
68     bool b_decoded_first_keyframe;
69
70     /*
71      * Common properties
72      */
73     vlc_tick_t i_pts;
74 } decoder_sys_t;
75
76 /*****************************************************************************
77  * Local prototypes
78  *****************************************************************************/
79 static int  OpenDecoder   ( vlc_object_t * );
80 static int  OpenPacketizer( vlc_object_t * );
81 static void CloseDecoder  ( vlc_object_t * );
82
83 static int DecodeVideo( decoder_t *p_dec, block_t *p_block );
84 static block_t *Packetize ( decoder_t *, block_t ** );
85 static int  ProcessHeaders( decoder_t * );
86 static void *ProcessPacket ( decoder_t *, daala_packet *, block_t * );
87
88 static picture_t *DecodePacket( decoder_t *, daala_packet * );
89
90 static void ParseDaalaComments( decoder_t * );
91 static void daala_CopyPicture( picture_t *, daala_image * );
92
93 #ifdef ENABLE_SOUT
94 static int  OpenEncoder( vlc_object_t *p_this );
95 static void CloseEncoder( vlc_object_t *p_this );
96 static block_t *Encode( encoder_t *p_enc, picture_t *p_pict );
97
98 static const char *const enc_chromafmt_list[] = {
99     "420", "444"
100 };
101 static const char *const enc_chromafmt_list_text[] = {
102     "4:2:0", "4:4:4"
103 };
104 #endif
105
106 /*****************************************************************************
107  * Module descriptor
108  *****************************************************************************/
109 #define ENC_QUALITY_TEXT N_("Encoding quality")
110 #define ENC_QUALITY_LONGTEXT N_( \
111   "Enforce a quality between 0 (lossless) and 511 (worst)." )
112 #define ENC_KEYINT_TEXT N_("Keyframe interval")
113 #define ENC_KEYINT_LONGTEXT N_( \
114   "Enforce a keyframe interval between 1 and 1000." )
115
116 vlc_module_begin ()
117     set_category( CAT_INPUT )
118     set_subcategory( SUBCAT_INPUT_VCODEC )
119     set_shortname( "Daala" )
120     set_description( N_("Daala video decoder") )
121     set_capability( "video decoder", 100 )
122     set_callbacks( OpenDecoder, CloseDecoder )
123     add_shortcut( "daala" )
124     add_submodule ()
125     set_description( N_("Daala video packetizer") )
126     set_capability( "packetizer", 100 )
127     set_callbacks( OpenPacketizer, CloseDecoder )
128     add_shortcut( "daala" )
129
130 #ifdef ENABLE_SOUT
131     add_submodule ()
132     set_description( N_("Daala video encoder") )
133     set_capability( "encoder", 150 )
134     set_callbacks( OpenEncoder, CloseEncoder )
135     add_shortcut( "daala" )
136
137 #   define ENC_CFG_PREFIX "sout-daala-"
138     add_integer_with_range( ENC_CFG_PREFIX "quality", 10, 0, 511,
139                  ENC_QUALITY_TEXT, ENC_QUALITY_LONGTEXT, false )
140     add_integer_with_range( ENC_CFG_PREFIX "keyint", 256, 1, 1000,
141                  ENC_KEYINT_TEXT, ENC_KEYINT_LONGTEXT, false )
142
143 #   define ENC_CHROMAFMT_TEXT N_("Chroma format")
144 #   define ENC_CHROMAFMT_LONGTEXT N_("Picking chroma format will force a " \
145                                      "conversion of the video into that format")
146
147     add_string( ENC_CFG_PREFIX "chroma-fmt", "420", ENC_CHROMAFMT_TEXT,
148                 ENC_CHROMAFMT_LONGTEXT, false )
149     change_string_list( enc_chromafmt_list, enc_chromafmt_list_text )
150 #endif
151 vlc_module_end ()
152
153 #ifdef ENABLE_SOUT
154 static const char *const ppsz_enc_options[] = {
155     "quality", "keyint", "chroma-fmt", NULL
156 };
157 #endif
158
159 static int OpenCommon( vlc_object_t *p_this, bool b_packetizer )
160 {
161     decoder_t *p_dec = (decoder_t*)p_this;
162     decoder_sys_t *p_sys;
163
164     if( p_dec->fmt_in.i_codec != VLC_CODEC_DAALA )
165     {
166         return VLC_EGENERIC;
167     }
168
169     /* Allocate the memory needed to store the decoder's structure */
170     p_sys = malloc(sizeof(*p_sys));
171     if( p_sys == NULL )
172         return VLC_ENOMEM;
173
174     p_dec->p_sys = p_sys;
175     p_sys->b_packetizer = b_packetizer;
176     p_sys->b_has_headers = false;
177     p_sys->i_pts = VLC_TICK_INVALID;
178     p_sys->b_decoded_first_keyframe = false;
179     p_sys->dcx = NULL;
180
181     if( b_packetizer )
182     {
183         p_dec->fmt_out.i_codec = VLC_CODEC_DAALA;
184         p_dec->pf_packetize = Packetize;
185     }
186     else
187     {
188         p_dec->fmt_out.i_codec = VLC_CODEC_I420;
189         p_dec->pf_decode = DecodeVideo;
190     }
191
192     /* Init supporting Daala structures needed in header parsing */
193     daala_comment_init( &p_sys->dc );
194     daala_info_init( &p_sys->di );
195
196     return VLC_SUCCESS;
197 }
198
199 /*****************************************************************************
200  * OpenDecoder: probe the decoder and return score
201  *****************************************************************************/
202 static int OpenDecoder( vlc_object_t *p_this )
203 {
204     return OpenCommon( p_this, false );
205 }
206
207 static int OpenPacketizer( vlc_object_t *p_this )
208 {
209     return OpenCommon( p_this, true );
210 }
211
212 /****************************************************************************
213  * DecodeBlock: the whole thing
214  ****************************************************************************
215  * This function must be fed with Daala packets.
216  ****************************************************************************/
217 static void *DecodeBlock( decoder_t *p_dec, block_t *p_block )
218 {
219     decoder_sys_t *p_sys = p_dec->p_sys;
220     daala_packet dpacket;
221
222     /* Block to Daala packet */
223     dpacket.packet = p_block->p_buffer;
224     dpacket.bytes = p_block->i_buffer;
225     dpacket.granulepos = p_block->i_dts;
226     dpacket.b_o_s = 0;
227     dpacket.e_o_s = 0;
228     dpacket.packetno = 0;
229
230     /* Check for headers */
231     if( !p_sys->b_has_headers )
232     {
233         if( ProcessHeaders( p_dec ) )
234         {
235             block_Release( p_block );
236             return NULL;
237         }
238         p_sys->b_has_headers = true;
239     }
240
241     /* If we haven't seen a single keyframe yet, set to preroll,
242      * otherwise we'll get display artifacts.  (This is impossible
243      * in the general case, but can happen if e.g. we play a network stream
244      * using a timed URL, such that the server doesn't start the video with a
245      * keyframe). */
246     if( !p_sys->b_decoded_first_keyframe )
247         p_block->i_flags |= BLOCK_FLAG_PREROLL; /* Wait until we've decoded the first keyframe */
248
249     return ProcessPacket( p_dec, &dpacket, p_block );
250 }
251
252 static int DecodeVideo( decoder_t *p_dec, block_t *p_block )
253 {
254     if( p_block == NULL ) /* No Drain */
255         return VLCDEC_SUCCESS;
256
257     picture_t *p_pic = DecodeBlock( p_dec, p_block );
258     if( p_pic != NULL )
259         decoder_QueueVideo( p_dec, p_pic );
260     return VLCDEC_SUCCESS;
261 }
262
263 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
264 {
265     if( pp_block == NULL ) /* No Drain */
266         return NULL;
267     block_t *p_block = *pp_block; *pp_block = NULL;
268     if( p_block == NULL )
269         return NULL;
270     return DecodeBlock( p_dec, p_block );
271 }
272
273 /*****************************************************************************
274  * ProcessHeaders: process Daala headers.
275  *****************************************************************************/
276 static int ProcessHeaders( decoder_t *p_dec )
277 {
278     int ret = VLC_SUCCESS;
279     decoder_sys_t *p_sys = p_dec->p_sys;
280     daala_packet dpacket;
281     daala_setup_info *ds = NULL; /* daala setup information */
282
283     unsigned pi_size[XIPH_MAX_HEADER_COUNT];
284     const void *pp_data[XIPH_MAX_HEADER_COUNT];
285     unsigned i_count;
286     if( xiph_SplitHeaders( pi_size, pp_data, &i_count,
287                            p_dec->fmt_in.i_extra, p_dec->fmt_in.p_extra) )
288         return VLC_EGENERIC;
289     if( i_count < 3 )
290         return VLC_EGENERIC;
291
292     dpacket.granulepos = -1;
293     dpacket.e_o_s = 0;
294     dpacket.packetno = 0;
295
296     /* Take care of the initial info header */
297     dpacket.b_o_s  = 1; /* yes this actually is a b_o_s packet :) */
298     dpacket.bytes  = pi_size[0];
299     dpacket.packet = (void *)pp_data[0];
300     if( daala_decode_header_in( &p_sys->di, &p_sys->dc, &ds, &dpacket ) < 0 )
301     {
302         msg_Err( p_dec, "this bitstream does not contain Daala video data" );
303         ret = VLC_EGENERIC;
304         goto cleanup;
305     }
306
307     /* Set output properties */
308     if( !p_sys->b_packetizer )
309     {
310         if( p_sys->di.plane_info[0].xdec == 0 && p_sys->di.plane_info[0].ydec == 0 &&
311             p_sys->di.plane_info[1].xdec == 1 && p_sys->di.plane_info[1].ydec == 1 &&
312             p_sys->di.plane_info[2].xdec == 1 && p_sys->di.plane_info[2].ydec == 1 )
313         {
314             p_dec->fmt_out.i_codec = VLC_CODEC_I420;
315         }
316         else if( p_sys->di.plane_info[0].xdec == 0 && p_sys->di.plane_info[0].ydec == 0 &&
317                  p_sys->di.plane_info[1].xdec == 0 && p_sys->di.plane_info[1].ydec == 0 &&
318                  p_sys->di.plane_info[2].xdec == 0 && p_sys->di.plane_info[2].ydec == 0 )
319         {
320             p_dec->fmt_out.i_codec = VLC_CODEC_I444;
321         }
322         else
323         {
324             msg_Err( p_dec, "unknown chroma in daala sample" );
325         }
326     }
327
328     p_dec->fmt_out.video.i_width = p_sys->di.pic_width;
329     p_dec->fmt_out.video.i_height = p_sys->di.pic_height;
330     if( p_sys->di.pic_width && p_sys->di.pic_height )
331     {
332         p_dec->fmt_out.video.i_visible_width = p_sys->di.pic_width;
333         p_dec->fmt_out.video.i_visible_height = p_sys->di.pic_height;
334     }
335
336     if( p_sys->di.pixel_aspect_denominator && p_sys->di.pixel_aspect_numerator )
337     {
338         p_dec->fmt_out.video.i_sar_num = p_sys->di.pixel_aspect_numerator;
339         p_dec->fmt_out.video.i_sar_den = p_sys->di.pixel_aspect_denominator;
340     }
341     else
342     {
343         p_dec->fmt_out.video.i_sar_num = 1;
344         p_dec->fmt_out.video.i_sar_den = 1;
345     }
346
347     if( p_sys->di.timebase_numerator > 0 && p_sys->di.timebase_denominator > 0 )
348     {
349         p_dec->fmt_out.video.i_frame_rate = p_sys->di.timebase_numerator;
350         p_dec->fmt_out.video.i_frame_rate_base = p_sys->di.timebase_denominator;
351     }
352
353     msg_Dbg( p_dec, "%dx%d %.02f fps video, frame content ",
354              p_sys->di.pic_width, p_sys->di.pic_height,
355              (double)p_sys->di.timebase_numerator/p_sys->di.timebase_denominator );
356
357     /* The next packet in order is the comments header */
358     dpacket.b_o_s  = 0;
359     dpacket.bytes  = pi_size[1];
360     dpacket.packet = (void *)pp_data[1];
361
362     if( daala_decode_header_in( &p_sys->di, &p_sys->dc, &ds, &dpacket ) < 0 )
363     {
364         msg_Err( p_dec, "Daala comment header is corrupted" );
365         ret = VLC_EGENERIC;
366         goto cleanup;
367     }
368
369     ParseDaalaComments( p_dec );
370
371     /* The next packet in order is the setup header
372      * We need to watch out that this packet is not missing as a
373      * missing or corrupted header is fatal. */
374     dpacket.b_o_s  = 0;
375     dpacket.bytes  = pi_size[2];
376     dpacket.packet = (void *)pp_data[2];
377     if( daala_decode_header_in( &p_sys->di, &p_sys->dc, &ds, &dpacket ) < 0 )
378     {
379         msg_Err( p_dec, "Daala setup header is corrupted" );
380         ret = VLC_EGENERIC;
381         goto cleanup;
382     }
383
384     if( !p_sys->b_packetizer )
385     {
386         /* We have all the headers, initialize decoder */
387         if ( ( p_sys->dcx = daala_decode_create( &p_sys->di, ds ) ) == NULL )
388         {
389             msg_Err( p_dec, "Could not allocate Daala decoder" );
390             ret = VLC_EGENERIC;
391             goto cleanup;
392         }
393     }
394     else
395     {
396         void* p_extra = realloc( p_dec->fmt_out.p_extra,
397                                  p_dec->fmt_in.i_extra );
398         if( unlikely( p_extra == NULL ) )
399         {
400             ret = VLC_ENOMEM;
401             goto cleanup;
402         }
403         p_dec->fmt_out.p_extra = p_extra;
404         p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra;
405         memcpy( p_dec->fmt_out.p_extra,
406                 p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra );
407     }
408
409 cleanup:
410     /* Clean up the decoder setup info... we're done with it */
411     daala_setup_free( ds );
412
413     return ret;
414 }
415
416 /*****************************************************************************
417  * ProcessPacket: processes a daala packet.
418  *****************************************************************************/
419 static void *ProcessPacket( decoder_t *p_dec, daala_packet *p_dpacket,
420                             block_t *p_block )
421 {
422     decoder_sys_t *p_sys = p_dec->p_sys;
423     void *p_buf;
424
425     if( ( p_block->i_flags&(BLOCK_FLAG_CORRUPTED) ) != 0 )
426     {
427         /* Don't send the the first packet after a discontinuity to
428          * daala_decode, otherwise we get purple/green display artifacts
429          * appearing in the video output */
430         block_Release(p_block);
431         return NULL;
432     }
433
434     /* Date management */
435     if( p_block->i_pts != VLC_TICK_INVALID && p_block->i_pts != p_sys->i_pts )
436     {
437         p_sys->i_pts = p_block->i_pts;
438     }
439
440     if( p_sys->b_packetizer )
441     {
442         /* Date management */
443         p_block->i_dts = p_block->i_pts = p_sys->i_pts;
444
445         p_block->i_length = p_sys->i_pts - p_block->i_pts;
446
447         p_buf = p_block;
448     }
449     else
450     {
451         p_buf = DecodePacket( p_dec, p_dpacket );
452         block_Release( p_block );
453     }
454
455     /* Date management */
456     p_sys->i_pts += vlc_tick_from_samples( p_sys->di.timebase_denominator,
457                       p_sys->di.timebase_numerator ); /* 1 frame per packet */
458
459     return p_buf;
460 }
461
462 /*****************************************************************************
463  * DecodePacket: decodes a Daala packet.
464  *****************************************************************************/
465 static picture_t *DecodePacket( decoder_t *p_dec, daala_packet *p_dpacket )
466 {
467     decoder_sys_t *p_sys = p_dec->p_sys;
468     picture_t *p_pic;
469     daala_image ycbcr;
470
471     if (daala_decode_packet_in( p_sys->dcx, p_dpacket ) < 0)
472         return NULL; /* bad packet */
473
474     if (!daala_decode_img_out( p_sys->dcx, &ycbcr ))
475         return NULL;
476
477     /* Check for keyframe */
478     if( daala_packet_iskeyframe( p_dpacket ) )
479         p_sys->b_decoded_first_keyframe = true;
480
481     /* Get a new picture */
482     if( decoder_UpdateVideoFormat( p_dec ) )
483         return NULL;
484     p_pic = decoder_NewPicture( p_dec );
485     if( !p_pic ) return NULL;
486
487     daala_CopyPicture( p_pic, &ycbcr );
488
489     p_pic->date = p_sys->i_pts;
490
491     return p_pic;
492 }
493
494 /*****************************************************************************
495  * ParseDaalaComments:
496  *****************************************************************************/
497 static void ParseDaalaComments( decoder_t *p_dec )
498 {
499     char *psz_name, *psz_value, *psz_comment;
500     /* Regarding the daala_comment structure: */
501
502     /* The metadata is stored as a series of (tag, value) pairs, in
503        length-encoded string vectors. The first occurrence of the '='
504        character delimits the tag and value. A particular tag may
505        occur more than once, and order is significant. The character
506        set encoding for the strings is always UTF-8, but the tag names
507        are limited to ASCII, and treated as case-insensitive. See the
508        Theora specification, Section 6.3.3 for details. */
509
510     /* In filling in this structure, daala_decode_header_in() will
511        null-terminate the user_comment strings for safety. However,
512        the bitstream format itself treats them as 8-bit clean vectors,
513        possibly containing null characters, and so the length array
514        should be treated as their authoritative length. */
515     decoder_sys_t *p_sys = p_dec->p_sys;
516     for ( int i = 0; i < p_sys->dc.comments; i++ )
517     {
518         int clen = p_sys->dc.comment_lengths[i];
519         if ( clen <= 0 || clen >= INT_MAX ) { continue; }
520         psz_comment = malloc( clen + 1 );
521         if( !psz_comment )
522             break;
523         memcpy( (void*)psz_comment, (void*)p_sys->dc.user_comments[i], clen + 1 );
524         psz_comment[clen] = '\0';
525
526         psz_name = psz_comment;
527         psz_value = strchr( psz_comment, '=' );
528         if( psz_value )
529         {
530             *psz_value = '\0';
531             psz_value++;
532
533             if( !p_dec->p_description )
534                 p_dec->p_description = vlc_meta_New();
535             /* TODO:  Since psz_value can contain NULLs see if there is an
536              * instance where we need to preserve the full length of this string */
537             if( p_dec->p_description )
538                 vlc_meta_AddExtra( p_dec->p_description, psz_name, psz_value );
539         }
540         free( psz_comment );
541     }
542 }
543
544 /*****************************************************************************
545  * CloseDecoder: daala decoder destruction
546  *****************************************************************************/
547 static void CloseDecoder( vlc_object_t *p_this )
548 {
549     decoder_t *p_dec = (decoder_t *)p_this;
550     decoder_sys_t *p_sys = p_dec->p_sys;
551
552     daala_info_clear(&p_sys->di);
553     daala_comment_clear(&p_sys->dc);
554     daala_decode_free(p_sys->dcx);
555     free( p_sys );
556 }
557
558 /*****************************************************************************
559  * daala_CopyPicture: copy a picture from daala internal buffers to a
560  *                     picture_t structure.
561  *****************************************************************************/
562 static void daala_CopyPicture( picture_t *p_pic,
563                                daala_image *ycbcr )
564 {
565     const int i_planes = p_pic->i_planes < 3 ? p_pic->i_planes : 3;
566     for( int i_plane = 0; i_plane < i_planes; i_plane++ )
567     {
568         const int i_total_lines = __MIN(p_pic->p[i_plane].i_lines,
569                 ycbcr->height >> ycbcr->planes[i_plane].ydec);
570         uint8_t *p_dst = p_pic->p[i_plane].p_pixels;
571         uint8_t *p_src = ycbcr->planes[i_plane].data;
572         const int i_dst_stride  = p_pic->p[i_plane].i_pitch;
573         const int i_src_stride  = ycbcr->planes[i_plane].ystride;
574         for( int i_line = 0; i_line < i_total_lines; i_line++ )
575         {
576             memcpy( p_dst, p_src, i_src_stride );
577             p_src += i_src_stride;
578             p_dst += i_dst_stride;
579         }
580     }
581 }
582
583 #ifdef ENABLE_SOUT
584 typedef struct
585 {
586     daala_info      di;                     /* daala bitstream settings */
587     daala_comment   dc;                     /* daala comment header */
588     daala_enc_ctx   *dcx;                   /* daala context */
589 } encoder_sys_t;
590
591 static int OpenEncoder( vlc_object_t *p_this )
592 {
593     encoder_t *p_enc = (encoder_t *)p_this;
594     encoder_sys_t *p_sys;
595     daala_packet header;
596     int status;
597
598     if( p_enc->fmt_out.i_codec != VLC_CODEC_DAALA &&
599         !p_enc->obj.force )
600     {
601         return VLC_EGENERIC;
602     }
603
604     /* Allocate the memory needed to store the encoder's structure */
605     p_sys = malloc( sizeof( encoder_sys_t ) );
606     if( !p_sys )
607         return VLC_ENOMEM;
608     p_enc->p_sys = p_sys;
609
610     p_enc->pf_encode_video = Encode;
611     p_enc->fmt_in.i_codec = VLC_CODEC_I420;
612     p_enc->fmt_out.i_codec = VLC_CODEC_DAALA;
613
614     config_ChainParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg );
615
616     char *psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX "chroma-fmt" );
617     uint32_t i_codec;
618     if( !psz_tmp ) {
619         free(p_sys);
620         return VLC_ENOMEM;
621     } else {
622         if( !strcmp( psz_tmp, "420" ) ) {
623             i_codec = VLC_CODEC_I420;
624         }
625         else if( !strcmp( psz_tmp, "444" ) ) {
626             i_codec = VLC_CODEC_I444;
627         }
628         else {
629             msg_Err( p_enc, "Invalid chroma format: %s", psz_tmp );
630             free( psz_tmp );
631             free( p_sys );
632             return VLC_EGENERIC;
633         }
634         free( psz_tmp );
635         p_enc->fmt_in.i_codec = i_codec;
636         /* update bits_per_pixel */
637         video_format_Setup(&p_enc->fmt_in.video, i_codec,
638                 p_enc->fmt_in.video.i_width,
639                 p_enc->fmt_in.video.i_height,
640                 p_enc->fmt_in.video.i_visible_width,
641                 p_enc->fmt_in.video.i_visible_height,
642                 p_enc->fmt_in.video.i_sar_num,
643                 p_enc->fmt_in.video.i_sar_den);
644     }
645
646     daala_info_init( &p_sys->di );
647
648     p_sys->di.pic_width = p_enc->fmt_in.video.i_visible_width;
649     p_sys->di.pic_height = p_enc->fmt_in.video.i_visible_height;
650
651     p_sys->di.nplanes = 3;
652     for (int i = 0; i < p_sys->di.nplanes; i++)
653     {
654         p_sys->di.plane_info[i].xdec = i > 0 && i_codec != VLC_CODEC_I444;
655         p_sys->di.plane_info[i].ydec = i_codec == VLC_CODEC_I420 ?
656             p_sys->di.plane_info[i].xdec : 0;
657     }
658     p_sys->di.frame_duration = 1;
659
660     if( !p_enc->fmt_in.video.i_frame_rate ||
661         !p_enc->fmt_in.video.i_frame_rate_base )
662     {
663         p_sys->di.timebase_numerator = 25;
664         p_sys->di.timebase_denominator = 1;
665     }
666     else
667     {
668         p_sys->di.timebase_numerator = p_enc->fmt_in.video.i_frame_rate;
669         p_sys->di.timebase_denominator = p_enc->fmt_in.video.i_frame_rate_base;
670     }
671
672     if( p_enc->fmt_in.video.i_sar_num > 0 && p_enc->fmt_in.video.i_sar_den > 0 )
673     {
674         unsigned i_dst_num, i_dst_den;
675         vlc_ureduce( &i_dst_num, &i_dst_den,
676                      p_enc->fmt_in.video.i_sar_num,
677                      p_enc->fmt_in.video.i_sar_den, 0 );
678         p_sys->di.pixel_aspect_numerator = i_dst_num;
679         p_sys->di.pixel_aspect_denominator = i_dst_den;
680     }
681     else
682     {
683         p_sys->di.pixel_aspect_numerator = 4;
684         p_sys->di.pixel_aspect_denominator = 3;
685     }
686
687     p_sys->di.keyframe_rate = var_GetInteger( p_enc, ENC_CFG_PREFIX "keyint" );
688
689     daala_enc_ctx *dcx;
690     p_sys->dcx = dcx = daala_encode_create( &p_sys->di );
691     if( !dcx )
692     {
693         free( p_sys );
694         return VLC_ENOMEM;
695     }
696
697     daala_comment_init( &p_sys->dc );
698
699     int i_quality = var_GetInteger( p_enc, ENC_CFG_PREFIX "quality" );
700     daala_encode_ctl( dcx, OD_SET_QUANT, &i_quality, sizeof(i_quality) );
701
702     /* Create and store headers */
703     while( ( status = daala_encode_flush_header( dcx, &p_sys->dc, &header ) ) )
704     {
705         if ( status < 0 )
706         {
707             CloseEncoder( p_this );
708             return VLC_EGENERIC;
709         }
710         if( xiph_AppendHeaders( &p_enc->fmt_out.i_extra,
711                                 &p_enc->fmt_out.p_extra, header.bytes,
712                                 header.packet ) )
713         {
714             p_enc->fmt_out.i_extra = 0;
715             p_enc->fmt_out.p_extra = NULL;
716         }
717     }
718     return VLC_SUCCESS;
719 }
720
721 static block_t *Encode( encoder_t *p_enc, picture_t *p_pict )
722 {
723     encoder_sys_t *p_sys = p_enc->p_sys;
724     daala_packet dpacket;
725     block_t *p_block;
726     daala_image img;
727
728     if( !p_pict ) return NULL;
729
730     const int i_width = p_sys->di.pic_width;
731     const int i_height = p_sys->di.pic_height;
732
733     /* Sanity check */
734     if( p_pict->p[0].i_pitch < i_width ||
735         p_pict->p[0].i_lines < i_height )
736     {
737         msg_Err( p_enc, "frame is smaller than encoding size"
738                  "(%ix%i->%ix%i) -> dropping frame",
739                  p_pict->p[0].i_pitch, p_pict->p[0].i_lines,
740                  i_width, i_height );
741         return NULL;
742     }
743
744     /* Daala is a one-frame-in, one-frame-out system. Submit a frame
745      * for compression and pull out the packet. */
746
747     img.nplanes = p_sys->di.nplanes;
748     img.width = i_width;
749     img.height = i_height;
750     for( int i = 0; i < img.nplanes; i++ )
751     {
752         img.planes[i].data = p_pict->p[i].p_pixels;
753         img.planes[i].xdec = p_sys->di.plane_info[i].xdec;
754         img.planes[i].ydec = p_sys->di.plane_info[i].ydec;
755         img.planes[i].xstride = 1;
756         img.planes[i].ystride = p_pict->p[i].i_pitch;
757         img.planes[i].bitdepth = 8; /*FIXME: support higher bit depths*/
758     }
759
760     if( daala_encode_img_in( p_sys->dcx, &img, 0 ) < 0 )
761     {
762         msg_Warn( p_enc, "failed encoding a frame" );
763         return NULL;
764     }
765
766     daala_encode_packet_out( p_sys->dcx, 0, &dpacket );
767
768     /* Daala packet to block */
769     p_block = block_Alloc( dpacket.bytes );
770     memcpy( p_block->p_buffer, dpacket.packet, dpacket.bytes );
771     p_block->i_dts = p_block->i_pts = p_pict->date;
772
773     if( daala_packet_iskeyframe( &dpacket ) )
774         p_block->i_flags |= BLOCK_FLAG_TYPE_I;
775
776     return p_block;
777 }
778
779 static void CloseEncoder( vlc_object_t *p_this )
780 {
781     encoder_t *p_enc = (encoder_t *)p_this;
782     encoder_sys_t *p_sys = p_enc->p_sys;
783
784     daala_info_clear(&p_sys->di);
785     daala_comment_clear(&p_sys->dc);
786     daala_encode_free(p_sys->dcx);
787     free( p_sys );
788 }
789 #endif