contrib: cargo: use cargo/vendored-openssl if needed
[vlc.git] / modules / codec / daala.c
blobad516e1cd3aadc40799f4102fd8c50541fdd7330
1 /*****************************************************************************
2 * daala.c: daala codec module making use of libdaala.
3 *****************************************************************************
4 * Copyright (C) 2014 VLC authors and VideoLAN
6 * Authors: Tristan Matthews <le.businessman@gmail.com>
7 * * Based on theora.c by: Gildas Bazin <gbazin@videolan.org>
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.
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.
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 *****************************************************************************/
24 /*****************************************************************************
25 * Preamble
26 *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_codec.h>
34 #include "../demux/xiph.h"
36 #include <daala/codec.h>
37 #include <daala/daaladec.h>
38 #ifdef ENABLE_SOUT
39 #include <daala/daalaenc.h>
40 #endif
42 #include <limits.h>
44 /*****************************************************************************
45 * decoder_sys_t : daala decoder descriptor
46 *****************************************************************************/
47 typedef struct
49 /* Module mode */
50 bool b_packetizer;
53 * Input properties
55 bool b_has_headers;
58 * Daala properties
60 daala_info di; /* daala bitstream settings */
61 daala_comment dc; /* daala comment information */
62 daala_dec_ctx *dcx; /* daala decoder context */
65 * Decoding properties
67 bool b_decoded_first_keyframe;
70 * Common properties
72 vlc_tick_t i_pts;
73 } decoder_sys_t;
75 /*****************************************************************************
76 * Local prototypes
77 *****************************************************************************/
78 static int OpenDecoder ( vlc_object_t * );
79 static int OpenPacketizer( vlc_object_t * );
80 static void CloseDecoder ( vlc_object_t * );
82 static int DecodeVideo( decoder_t *p_dec, block_t *p_block );
83 static block_t *Packetize ( decoder_t *, block_t ** );
84 static int ProcessHeaders( decoder_t * );
85 static void *ProcessPacket ( decoder_t *, daala_packet *, block_t * );
87 static picture_t *DecodePacket( decoder_t *, daala_packet * );
89 static void ParseDaalaComments( decoder_t * );
90 static void daala_CopyPicture( picture_t *, daala_image * );
92 #ifdef ENABLE_SOUT
93 static int OpenEncoder( vlc_object_t *p_this );
94 static void CloseEncoder( vlc_object_t *p_this );
95 static block_t *Encode( encoder_t *p_enc, picture_t *p_pict );
97 static const char *const enc_chromafmt_list[] = {
98 "420", "444"
100 static const char *const enc_chromafmt_list_text[] = {
101 "4:2:0", "4:4:4"
103 #endif
105 /*****************************************************************************
106 * Module descriptor
107 *****************************************************************************/
108 #define ENC_QUALITY_TEXT N_("Encoding quality")
109 #define ENC_QUALITY_LONGTEXT N_( \
110 "Enforce a quality between 0 (lossless) and 511 (worst)." )
111 #define ENC_KEYINT_TEXT N_("Keyframe interval")
112 #define ENC_KEYINT_LONGTEXT N_( \
113 "Enforce a keyframe interval between 1 and 1000." )
115 vlc_module_begin ()
116 set_category( CAT_INPUT )
117 set_subcategory( SUBCAT_INPUT_VCODEC )
118 set_shortname( "Daala" )
119 set_description( N_("Daala video decoder") )
120 set_capability( "video decoder", 100 )
121 set_callbacks( OpenDecoder, CloseDecoder )
122 add_shortcut( "daala" )
123 add_submodule ()
124 set_description( N_("Daala video packetizer") )
125 set_capability( "packetizer", 100 )
126 set_callbacks( OpenPacketizer, CloseDecoder )
127 add_shortcut( "daala" )
129 #ifdef ENABLE_SOUT
130 add_submodule ()
131 set_description( N_("Daala video encoder") )
132 set_capability( "encoder", 150 )
133 set_callbacks( OpenEncoder, CloseEncoder )
134 add_shortcut( "daala" )
136 # define ENC_CFG_PREFIX "sout-daala-"
137 add_integer_with_range( ENC_CFG_PREFIX "quality", 10, 0, 511,
138 ENC_QUALITY_TEXT, ENC_QUALITY_LONGTEXT, false )
139 add_integer_with_range( ENC_CFG_PREFIX "keyint", 256, 1, 1000,
140 ENC_KEYINT_TEXT, ENC_KEYINT_LONGTEXT, false )
142 # define ENC_CHROMAFMT_TEXT N_("Chroma format")
143 # define ENC_CHROMAFMT_LONGTEXT N_("Picking chroma format will force a " \
144 "conversion of the video into that format")
146 add_string( ENC_CFG_PREFIX "chroma-fmt", "420", ENC_CHROMAFMT_TEXT,
147 ENC_CHROMAFMT_LONGTEXT, false )
148 change_string_list( enc_chromafmt_list, enc_chromafmt_list_text )
149 vlc_module_end ()
151 static const char *const ppsz_enc_options[] = {
152 "quality", "keyint", "chroma-fmt", NULL
154 #endif
156 static int OpenCommon( vlc_object_t *p_this, bool b_packetizer )
158 decoder_t *p_dec = (decoder_t*)p_this;
159 decoder_sys_t *p_sys;
161 if( p_dec->fmt_in.i_codec != VLC_CODEC_DAALA )
163 return VLC_EGENERIC;
166 /* Allocate the memory needed to store the decoder's structure */
167 p_sys = malloc(sizeof(*p_sys));
168 if( p_sys == NULL )
169 return VLC_ENOMEM;
171 p_dec->p_sys = p_sys;
172 p_dec->p_sys->b_packetizer = b_packetizer;
173 p_sys->b_has_headers = false;
174 p_sys->i_pts = VLC_TICK_INVALID;
175 p_sys->b_decoded_first_keyframe = false;
176 p_sys->dcx = NULL;
178 if( b_packetizer )
180 p_dec->fmt_out.i_codec = VLC_CODEC_DAALA;
181 p_dec->pf_packetize = Packetize;
183 else
185 p_dec->fmt_out.i_codec = VLC_CODEC_I420;
186 p_dec->pf_decode = DecodeVideo;
189 /* Init supporting Daala structures needed in header parsing */
190 daala_comment_init( &p_sys->dc );
191 daala_info_init( &p_sys->di );
193 return VLC_SUCCESS;
196 /*****************************************************************************
197 * OpenDecoder: probe the decoder and return score
198 *****************************************************************************/
199 static int OpenDecoder( vlc_object_t *p_this )
201 return OpenCommon( p_this, false );
204 static int OpenPacketizer( vlc_object_t *p_this )
206 return OpenCommon( p_this, true );
209 /****************************************************************************
210 * DecodeBlock: the whole thing
211 ****************************************************************************
212 * This function must be fed with Daala packets.
213 ****************************************************************************/
214 static void *DecodeBlock( decoder_t *p_dec, block_t *p_block )
216 decoder_sys_t *p_sys = p_dec->p_sys;
217 daala_packet dpacket;
219 /* Block to Daala packet */
220 dpacket.packet = p_block->p_buffer;
221 dpacket.bytes = p_block->i_buffer;
222 dpacket.granulepos = p_block->i_dts;
223 dpacket.b_o_s = 0;
224 dpacket.e_o_s = 0;
225 dpacket.packetno = 0;
227 /* Check for headers */
228 if( !p_sys->b_has_headers )
230 if( ProcessHeaders( p_dec ) )
232 block_Release( p_block );
233 return NULL;
235 p_sys->b_has_headers = true;
238 /* If we haven't seen a single keyframe yet, set to preroll,
239 * otherwise we'll get display artifacts. (This is impossible
240 * in the general case, but can happen if e.g. we play a network stream
241 * using a timed URL, such that the server doesn't start the video with a
242 * keyframe). */
243 if( !p_sys->b_decoded_first_keyframe )
244 p_block->i_flags |= BLOCK_FLAG_PREROLL; /* Wait until we've decoded the first keyframe */
246 return ProcessPacket( p_dec, &dpacket, p_block );
249 static int DecodeVideo( decoder_t *p_dec, block_t *p_block )
251 if( p_block == NULL ) /* No Drain */
252 return VLCDEC_SUCCESS;
254 picture_t *p_pic = DecodeBlock( p_dec, p_block );
255 if( p_pic != NULL )
256 decoder_QueueVideo( p_dec, p_pic );
257 return VLCDEC_SUCCESS;
260 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
262 if( pp_block == NULL ) /* No Drain */
263 return NULL;
264 block_t *p_block = *pp_block; *pp_block = NULL;
265 if( p_block == NULL )
266 return NULL;
267 return DecodeBlock( p_dec, p_block );
270 /*****************************************************************************
271 * ProcessHeaders: process Daala headers.
272 *****************************************************************************/
273 static int ProcessHeaders( decoder_t *p_dec )
275 int ret = VLC_SUCCESS;
276 decoder_sys_t *p_sys = p_dec->p_sys;
277 daala_packet dpacket;
278 daala_setup_info *ds = NULL; /* daala setup information */
280 unsigned pi_size[XIPH_MAX_HEADER_COUNT];
281 const void *pp_data[XIPH_MAX_HEADER_COUNT];
282 unsigned i_count;
283 if( xiph_SplitHeaders( pi_size, pp_data, &i_count,
284 p_dec->fmt_in.i_extra, p_dec->fmt_in.p_extra) )
285 return VLC_EGENERIC;
286 if( i_count < 3 )
287 return VLC_EGENERIC;
289 dpacket.granulepos = -1;
290 dpacket.e_o_s = 0;
291 dpacket.packetno = 0;
293 /* Take care of the initial info header */
294 dpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */
295 dpacket.bytes = pi_size[0];
296 dpacket.packet = (void *)pp_data[0];
297 if( daala_decode_header_in( &p_sys->di, &p_sys->dc, &ds, &dpacket ) < 0 )
299 msg_Err( p_dec, "this bitstream does not contain Daala video data" );
300 ret = VLC_EGENERIC;
301 goto cleanup;
304 /* Set output properties */
305 if( !p_sys->b_packetizer )
307 if( p_sys->di.plane_info[0].xdec == 0 && p_sys->di.plane_info[0].ydec == 0 &&
308 p_sys->di.plane_info[1].xdec == 1 && p_sys->di.plane_info[1].ydec == 1 &&
309 p_sys->di.plane_info[2].xdec == 1 && p_sys->di.plane_info[2].ydec == 1 )
311 p_dec->fmt_out.i_codec = VLC_CODEC_I420;
313 else if( p_sys->di.plane_info[0].xdec == 0 && p_sys->di.plane_info[0].ydec == 0 &&
314 p_sys->di.plane_info[1].xdec == 0 && p_sys->di.plane_info[1].ydec == 0 &&
315 p_sys->di.plane_info[2].xdec == 0 && p_sys->di.plane_info[2].ydec == 0 )
317 p_dec->fmt_out.i_codec = VLC_CODEC_I444;
319 else
321 msg_Err( p_dec, "unknown chroma in daala sample" );
325 p_dec->fmt_out.video.i_width = p_sys->di.pic_width;
326 p_dec->fmt_out.video.i_height = p_sys->di.pic_height;
327 if( p_sys->di.pic_width && p_sys->di.pic_height )
329 p_dec->fmt_out.video.i_visible_width = p_sys->di.pic_width;
330 p_dec->fmt_out.video.i_visible_height = p_sys->di.pic_height;
333 if( p_sys->di.pixel_aspect_denominator && p_sys->di.pixel_aspect_numerator )
335 p_dec->fmt_out.video.i_sar_num = p_sys->di.pixel_aspect_numerator;
336 p_dec->fmt_out.video.i_sar_den = p_sys->di.pixel_aspect_denominator;
338 else
340 p_dec->fmt_out.video.i_sar_num = 1;
341 p_dec->fmt_out.video.i_sar_den = 1;
344 if( p_sys->di.timebase_numerator > 0 && p_sys->di.timebase_denominator > 0 )
346 p_dec->fmt_out.video.i_frame_rate = p_sys->di.timebase_numerator;
347 p_dec->fmt_out.video.i_frame_rate_base = p_sys->di.timebase_denominator;
350 msg_Dbg( p_dec, "%dx%d %.02f fps video, frame content ",
351 p_sys->di.pic_width, p_sys->di.pic_height,
352 (double)p_sys->di.timebase_numerator/p_sys->di.timebase_denominator );
354 /* The next packet in order is the comments header */
355 dpacket.b_o_s = 0;
356 dpacket.bytes = pi_size[1];
357 dpacket.packet = (void *)pp_data[1];
359 if( daala_decode_header_in( &p_sys->di, &p_sys->dc, &ds, &dpacket ) < 0 )
361 msg_Err( p_dec, "Daala comment header is corrupted" );
362 ret = VLC_EGENERIC;
363 goto cleanup;
366 ParseDaalaComments( p_dec );
368 /* The next packet in order is the setup header
369 * We need to watch out that this packet is not missing as a
370 * missing or corrupted header is fatal. */
371 dpacket.b_o_s = 0;
372 dpacket.bytes = pi_size[2];
373 dpacket.packet = (void *)pp_data[2];
374 if( daala_decode_header_in( &p_sys->di, &p_sys->dc, &ds, &dpacket ) < 0 )
376 msg_Err( p_dec, "Daala setup header is corrupted" );
377 ret = VLC_EGENERIC;
378 goto cleanup;
381 if( !p_sys->b_packetizer )
383 /* We have all the headers, initialize decoder */
384 if ( ( p_sys->dcx = daala_decode_create( &p_sys->di, ds ) ) == NULL )
386 msg_Err( p_dec, "Could not allocate Daala decoder" );
387 ret = VLC_EGENERIC;
388 goto cleanup;
391 else
393 void* p_extra = realloc( p_dec->fmt_out.p_extra,
394 p_dec->fmt_in.i_extra );
395 if( unlikely( p_extra == NULL ) )
397 ret = VLC_ENOMEM;
398 goto cleanup;
400 p_dec->fmt_out.p_extra = p_extra;
401 p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra;
402 memcpy( p_dec->fmt_out.p_extra,
403 p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra );
406 cleanup:
407 /* Clean up the decoder setup info... we're done with it */
408 daala_setup_free( ds );
410 return ret;
413 /*****************************************************************************
414 * ProcessPacket: processes a daala packet.
415 *****************************************************************************/
416 static void *ProcessPacket( decoder_t *p_dec, daala_packet *p_dpacket,
417 block_t *p_block )
419 decoder_sys_t *p_sys = p_dec->p_sys;
420 void *p_buf;
422 if( ( p_block->i_flags&(BLOCK_FLAG_CORRUPTED) ) != 0 )
424 /* Don't send the the first packet after a discontinuity to
425 * daala_decode, otherwise we get purple/green display artifacts
426 * appearing in the video output */
427 block_Release(p_block);
428 return NULL;
431 /* Date management */
432 if( p_block->i_pts != VLC_TICK_INVALID && p_block->i_pts != p_sys->i_pts )
434 p_sys->i_pts = p_block->i_pts;
437 if( p_sys->b_packetizer )
439 /* Date management */
440 p_block->i_dts = p_block->i_pts = p_sys->i_pts;
442 p_block->i_length = p_sys->i_pts - p_block->i_pts;
444 p_buf = p_block;
446 else
448 p_buf = DecodePacket( p_dec, p_dpacket );
449 block_Release( p_block );
452 /* Date management */
453 p_sys->i_pts += vlc_tick_from_samples( p_sys->di.timebase_denominator,
454 p_sys->di.timebase_numerator ); /* 1 frame per packet */
456 return p_buf;
459 /*****************************************************************************
460 * DecodePacket: decodes a Daala packet.
461 *****************************************************************************/
462 static picture_t *DecodePacket( decoder_t *p_dec, daala_packet *p_dpacket )
464 decoder_sys_t *p_sys = p_dec->p_sys;
465 picture_t *p_pic;
466 daala_image ycbcr;
468 if (daala_decode_packet_in( p_sys->dcx, p_dpacket ) < 0)
469 return NULL; /* bad packet */
471 if (!daala_decode_img_out( p_sys->dcx, &ycbcr ))
472 return NULL;
474 /* Check for keyframe */
475 if( daala_packet_iskeyframe( p_dpacket ) )
476 p_sys->b_decoded_first_keyframe = true;
478 /* Get a new picture */
479 if( decoder_UpdateVideoFormat( p_dec ) )
480 return NULL;
481 p_pic = decoder_NewPicture( p_dec );
482 if( !p_pic ) return NULL;
484 daala_CopyPicture( p_pic, &ycbcr );
486 p_pic->date = p_sys->i_pts;
488 return p_pic;
491 /*****************************************************************************
492 * ParseDaalaComments:
493 *****************************************************************************/
494 static void ParseDaalaComments( decoder_t *p_dec )
496 char *psz_name, *psz_value, *psz_comment;
497 /* Regarding the daala_comment structure: */
499 /* The metadata is stored as a series of (tag, value) pairs, in
500 length-encoded string vectors. The first occurrence of the '='
501 character delimits the tag and value. A particular tag may
502 occur more than once, and order is significant. The character
503 set encoding for the strings is always UTF-8, but the tag names
504 are limited to ASCII, and treated as case-insensitive. See the
505 Theora specification, Section 6.3.3 for details. */
507 /* In filling in this structure, daala_decode_header_in() will
508 null-terminate the user_comment strings for safety. However,
509 the bitstream format itself treats them as 8-bit clean vectors,
510 possibly containing null characters, and so the length array
511 should be treated as their authoritative length. */
512 for ( int i = 0; i < p_dec->p_sys->dc.comments; i++ )
514 int clen = p_dec->p_sys->dc.comment_lengths[i];
515 if ( clen <= 0 || clen >= INT_MAX ) { continue; }
516 psz_comment = malloc( clen + 1 );
517 if( !psz_comment )
518 break;
519 memcpy( (void*)psz_comment, (void*)p_dec->p_sys->dc.user_comments[i], clen + 1 );
520 psz_comment[clen] = '\0';
522 psz_name = psz_comment;
523 psz_value = strchr( psz_comment, '=' );
524 if( psz_value )
526 *psz_value = '\0';
527 psz_value++;
529 if( !p_dec->p_description )
530 p_dec->p_description = vlc_meta_New();
531 /* TODO: Since psz_value can contain NULLs see if there is an
532 * instance where we need to preserve the full length of this string */
533 if( p_dec->p_description )
534 vlc_meta_AddExtra( p_dec->p_description, psz_name, psz_value );
536 free( psz_comment );
540 /*****************************************************************************
541 * CloseDecoder: daala decoder destruction
542 *****************************************************************************/
543 static void CloseDecoder( vlc_object_t *p_this )
545 decoder_t *p_dec = (decoder_t *)p_this;
546 decoder_sys_t *p_sys = p_dec->p_sys;
548 daala_info_clear(&p_sys->di);
549 daala_comment_clear(&p_sys->dc);
550 daala_decode_free(p_sys->dcx);
551 free( p_sys );
554 /*****************************************************************************
555 * daala_CopyPicture: copy a picture from daala internal buffers to a
556 * picture_t structure.
557 *****************************************************************************/
558 static void daala_CopyPicture( picture_t *p_pic,
559 daala_image *ycbcr )
561 const int i_planes = p_pic->i_planes < 3 ? p_pic->i_planes : 3;
562 for( int i_plane = 0; i_plane < i_planes; i_plane++ )
564 const int i_total_lines = __MIN(p_pic->p[i_plane].i_lines,
565 ycbcr->height >> ycbcr->planes[i_plane].ydec);
566 uint8_t *p_dst = p_pic->p[i_plane].p_pixels;
567 uint8_t *p_src = ycbcr->planes[i_plane].data;
568 const int i_dst_stride = p_pic->p[i_plane].i_pitch;
569 const int i_src_stride = ycbcr->planes[i_plane].ystride;
570 for( int i_line = 0; i_line < i_total_lines; i_line++ )
572 memcpy( p_dst, p_src, i_src_stride );
573 p_src += i_src_stride;
574 p_dst += i_dst_stride;
579 #ifdef ENABLE_SOUT
580 typedef struct
582 daala_info di; /* daala bitstream settings */
583 daala_comment dc; /* daala comment header */
584 daala_enc_ctx *dcx; /* daala context */
585 } encoder_sys_t;
587 static int OpenEncoder( vlc_object_t *p_this )
589 encoder_t *p_enc = (encoder_t *)p_this;
590 encoder_sys_t *p_sys;
591 daala_packet header;
592 int status;
594 if( p_enc->fmt_out.i_codec != VLC_CODEC_DAALA &&
595 !p_enc->obj.force )
597 return VLC_EGENERIC;
600 /* Allocate the memory needed to store the encoder's structure */
601 p_sys = malloc( sizeof( encoder_sys_t ) );
602 if( !p_sys )
603 return VLC_ENOMEM;
604 p_enc->p_sys = p_sys;
606 p_enc->pf_encode_video = Encode;
607 p_enc->fmt_in.i_codec = VLC_CODEC_I420;
608 p_enc->fmt_out.i_codec = VLC_CODEC_DAALA;
610 config_ChainParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg );
612 char *psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX "chroma-fmt" );
613 uint32_t i_codec;
614 if( !psz_tmp ) {
615 free(p_sys);
616 return VLC_ENOMEM;
617 } else {
618 if( !strcmp( psz_tmp, "420" ) ) {
619 i_codec = VLC_CODEC_I420;
621 else if( !strcmp( psz_tmp, "444" ) ) {
622 i_codec = VLC_CODEC_I444;
624 else {
625 msg_Err( p_enc, "Invalid chroma format: %s", psz_tmp );
626 free( psz_tmp );
627 free( p_sys );
628 return VLC_EGENERIC;
630 free( psz_tmp );
631 p_enc->fmt_in.i_codec = i_codec;
632 /* update bits_per_pixel */
633 video_format_Setup(&p_enc->fmt_in.video, i_codec,
634 p_enc->fmt_in.video.i_width,
635 p_enc->fmt_in.video.i_height,
636 p_enc->fmt_in.video.i_visible_width,
637 p_enc->fmt_in.video.i_visible_height,
638 p_enc->fmt_in.video.i_sar_num,
639 p_enc->fmt_in.video.i_sar_den);
642 daala_info_init( &p_sys->di );
644 p_sys->di.pic_width = p_enc->fmt_in.video.i_visible_width;
645 p_sys->di.pic_height = p_enc->fmt_in.video.i_visible_height;
647 p_sys->di.nplanes = 3;
648 for (int i = 0; i < p_sys->di.nplanes; i++)
650 p_sys->di.plane_info[i].xdec = i > 0 && i_codec != VLC_CODEC_I444;
651 p_sys->di.plane_info[i].ydec = i_codec == VLC_CODEC_I420 ?
652 p_sys->di.plane_info[i].xdec : 0;
654 p_sys->di.frame_duration = 1;
656 if( !p_enc->fmt_in.video.i_frame_rate ||
657 !p_enc->fmt_in.video.i_frame_rate_base )
659 p_sys->di.timebase_numerator = 25;
660 p_sys->di.timebase_denominator = 1;
662 else
664 p_sys->di.timebase_numerator = p_enc->fmt_in.video.i_frame_rate;
665 p_sys->di.timebase_denominator = p_enc->fmt_in.video.i_frame_rate_base;
668 if( p_enc->fmt_in.video.i_sar_num > 0 && p_enc->fmt_in.video.i_sar_den > 0 )
670 unsigned i_dst_num, i_dst_den;
671 vlc_ureduce( &i_dst_num, &i_dst_den,
672 p_enc->fmt_in.video.i_sar_num,
673 p_enc->fmt_in.video.i_sar_den, 0 );
674 p_sys->di.pixel_aspect_numerator = i_dst_num;
675 p_sys->di.pixel_aspect_denominator = i_dst_den;
677 else
679 p_sys->di.pixel_aspect_numerator = 4;
680 p_sys->di.pixel_aspect_denominator = 3;
683 p_sys->di.keyframe_rate = var_GetInteger( p_enc, ENC_CFG_PREFIX "keyint" );
685 daala_enc_ctx *dcx;
686 p_sys->dcx = dcx = daala_encode_create( &p_sys->di );
687 if( !dcx )
689 free( p_sys );
690 return VLC_ENOMEM;
693 daala_comment_init( &p_sys->dc );
695 int i_quality = var_GetInteger( p_enc, ENC_CFG_PREFIX "quality" );
696 daala_encode_ctl( dcx, OD_SET_QUANT, &i_quality, sizeof(i_quality) );
698 /* Create and store headers */
699 while( ( status = daala_encode_flush_header( dcx, &p_sys->dc, &header ) ) )
701 if ( status < 0 )
703 CloseEncoder( p_this );
704 return VLC_EGENERIC;
706 if( xiph_AppendHeaders( &p_enc->fmt_out.i_extra,
707 &p_enc->fmt_out.p_extra, header.bytes,
708 header.packet ) )
710 p_enc->fmt_out.i_extra = 0;
711 p_enc->fmt_out.p_extra = NULL;
714 return VLC_SUCCESS;
717 static block_t *Encode( encoder_t *p_enc, picture_t *p_pict )
719 encoder_sys_t *p_sys = p_enc->p_sys;
720 daala_packet dpacket;
721 block_t *p_block;
722 daala_image img;
724 if( !p_pict ) return NULL;
726 const int i_width = p_sys->di.pic_width;
727 const int i_height = p_sys->di.pic_height;
729 /* Sanity check */
730 if( p_pict->p[0].i_pitch < i_width ||
731 p_pict->p[0].i_lines < i_height )
733 msg_Err( p_enc, "frame is smaller than encoding size"
734 "(%ix%i->%ix%i) -> dropping frame",
735 p_pict->p[0].i_pitch, p_pict->p[0].i_lines,
736 i_width, i_height );
737 return NULL;
740 /* Daala is a one-frame-in, one-frame-out system. Submit a frame
741 * for compression and pull out the packet. */
743 img.nplanes = p_sys->di.nplanes;
744 img.width = i_width;
745 img.height = i_height;
746 for( int i = 0; i < img.nplanes; i++ )
748 img.planes[i].data = p_pict->p[i].p_pixels;
749 img.planes[i].xdec = p_sys->di.plane_info[i].xdec;
750 img.planes[i].ydec = p_sys->di.plane_info[i].ydec;
751 img.planes[i].xstride = 1;
752 img.planes[i].ystride = p_pict->p[i].i_pitch;
753 img.planes[i].bitdepth = 8; /*FIXME: support higher bit depths*/
756 if( daala_encode_img_in( p_sys->dcx, &img, 0 ) < 0 )
758 msg_Warn( p_enc, "failed encoding a frame" );
759 return NULL;
762 daala_encode_packet_out( p_sys->dcx, 0, &dpacket );
764 /* Daala packet to block */
765 p_block = block_Alloc( dpacket.bytes );
766 memcpy( p_block->p_buffer, dpacket.packet, dpacket.bytes );
767 p_block->i_dts = p_block->i_pts = p_pict->date;
769 if( daala_packet_iskeyframe( &dpacket ) )
770 p_block->i_flags |= BLOCK_FLAG_TYPE_I;
772 return p_block;
775 static void CloseEncoder( vlc_object_t *p_this )
777 encoder_t *p_enc = (encoder_t *)p_this;
778 encoder_sys_t *p_sys = p_enc->p_sys;
780 daala_info_clear(&p_sys->di);
781 daala_comment_clear(&p_sys->dc);
782 daala_encode_free(p_sys->dcx);
783 free( p_sys );
785 #endif