demux: adaptive: inflate streamUrl streams
[vlc.git] / modules / codec / daala.c
blob95e61bb9ff6167eedb44580aba1f7e1623e03ec8
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 <vlc_input.h>
35 #include "../demux/xiph.h"
37 #include <daala/codec.h>
38 #include <daala/daaladec.h>
39 #ifdef ENABLE_SOUT
40 #include <daala/daalaenc.h>
41 #endif
43 #include <limits.h>
45 /*****************************************************************************
46 * decoder_sys_t : daala decoder descriptor
47 *****************************************************************************/
48 struct decoder_sys_t
50 /* Module mode */
51 bool b_packetizer;
54 * Input properties
56 bool b_has_headers;
59 * Daala properties
61 daala_info di; /* daala bitstream settings */
62 daala_comment dc; /* daala comment information */
63 daala_dec_ctx *dcx; /* daala decoder context */
66 * Decoding properties
68 bool b_decoded_first_keyframe;
71 * Common properties
73 mtime_t i_pts;
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 * );
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 * );
88 static picture_t *DecodePacket( decoder_t *, daala_packet * );
90 static void ParseDaalaComments( decoder_t * );
91 static void daala_CopyPicture( picture_t *, daala_image * );
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 );
98 static const char *const enc_chromafmt_list[] = {
99 "420", "444"
101 static const char *const enc_chromafmt_list_text[] = {
102 "4:2:0", "4:4:4"
104 #endif
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." )
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" )
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" )
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 )
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")
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 vlc_module_end ()
152 static const char *const ppsz_enc_options[] = {
153 "quality", "keyint", "chroma-fmt", NULL
155 #endif
157 /*****************************************************************************
158 * OpenDecoder: probe the decoder and return score
159 *****************************************************************************/
160 static int OpenDecoder( vlc_object_t *p_this )
162 decoder_t *p_dec = (decoder_t*)p_this;
163 decoder_sys_t *p_sys;
165 if( p_dec->fmt_in.i_codec != VLC_CODEC_DAALA )
167 return VLC_EGENERIC;
170 /* Allocate the memory needed to store the decoder's structure */
171 p_sys = malloc(sizeof(*p_sys));
172 if( p_sys == NULL )
173 return VLC_ENOMEM;
175 p_dec->p_sys = p_sys;
176 p_dec->p_sys->b_packetizer = false;
177 p_sys->b_has_headers = false;
178 p_sys->i_pts = VLC_TS_INVALID;
179 p_sys->b_decoded_first_keyframe = false;
180 p_sys->dcx = NULL;
182 /* Set output properties */
183 p_dec->fmt_out.i_codec = VLC_CODEC_I420;
185 /* Set callbacks */
186 p_dec->pf_decode = DecodeVideo;
187 p_dec->pf_packetize = Packetize;
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 static int OpenPacketizer( vlc_object_t *p_this )
198 decoder_t *p_dec = (decoder_t*)p_this;
200 int i_ret = OpenDecoder( p_this );
202 if( i_ret == VLC_SUCCESS )
204 p_dec->p_sys->b_packetizer = true;
205 p_dec->fmt_out.i_codec = VLC_CODEC_DAALA;
208 return i_ret;
211 /****************************************************************************
212 * DecodeBlock: the whole thing
213 ****************************************************************************
214 * This function must be fed with Daala packets.
215 ****************************************************************************/
216 static void *DecodeBlock( decoder_t *p_dec, block_t *p_block )
218 decoder_sys_t *p_sys = p_dec->p_sys;
219 daala_packet dpacket;
221 /* Block to Daala packet */
222 dpacket.packet = p_block->p_buffer;
223 dpacket.bytes = p_block->i_buffer;
224 dpacket.granulepos = p_block->i_dts;
225 dpacket.b_o_s = 0;
226 dpacket.e_o_s = 0;
227 dpacket.packetno = 0;
229 /* Check for headers */
230 if( !p_sys->b_has_headers )
232 if( ProcessHeaders( p_dec ) )
234 block_Release( p_block );
235 return NULL;
237 p_sys->b_has_headers = true;
240 /* If we haven't seen a single keyframe yet, set to preroll,
241 * otherwise we'll get display artifacts. (This is impossible
242 * in the general case, but can happen if e.g. we play a network stream
243 * using a timed URL, such that the server doesn't start the video with a
244 * keyframe). */
245 if( !p_sys->b_decoded_first_keyframe )
246 p_block->i_flags |= BLOCK_FLAG_PREROLL; /* Wait until we've decoded the first keyframe */
248 return ProcessPacket( p_dec, &dpacket, p_block );
251 static int DecodeVideo( decoder_t *p_dec, block_t *p_block )
253 if( p_block == NULL ) /* No Drain */
254 return VLCDEC_SUCCESS;
256 picture_t *p_pic = DecodeBlock( p_dec, p_block );
257 if( p_pic != NULL )
258 decoder_QueueVideo( p_dec, p_pic );
259 return VLCDEC_SUCCESS;
262 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
264 if( pp_block == NULL ) /* No Drain */
265 return NULL;
266 block_t *p_block = *pp_block; *pp_block = NULL;
267 if( p_block == NULL )
268 return NULL;
269 return DecodeBlock( p_dec, p_block );
272 /*****************************************************************************
273 * ProcessHeaders: process Daala headers.
274 *****************************************************************************/
275 static int ProcessHeaders( decoder_t *p_dec )
277 int ret = VLC_SUCCESS;
278 decoder_sys_t *p_sys = p_dec->p_sys;
279 daala_packet dpacket;
280 daala_setup_info *ds = NULL; /* daala setup information */
282 unsigned pi_size[XIPH_MAX_HEADER_COUNT];
283 void *pp_data[XIPH_MAX_HEADER_COUNT];
284 unsigned i_count;
285 if( xiph_SplitHeaders( pi_size, pp_data, &i_count,
286 p_dec->fmt_in.i_extra, p_dec->fmt_in.p_extra) )
287 return VLC_EGENERIC;
288 if( i_count < 3 )
289 return VLC_EGENERIC;
291 dpacket.granulepos = -1;
292 dpacket.e_o_s = 0;
293 dpacket.packetno = 0;
295 /* Take care of the initial info header */
296 dpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */
297 dpacket.bytes = pi_size[0];
298 dpacket.packet = pp_data[0];
299 if( daala_decode_header_in( &p_sys->di, &p_sys->dc, &ds, &dpacket ) < 0 )
301 msg_Err( p_dec, "this bitstream does not contain Daala video data" );
302 ret = VLC_EGENERIC;
303 goto cleanup;
306 /* Set output properties */
307 if( !p_sys->b_packetizer )
309 if( p_sys->di.plane_info[0].xdec == 0 && p_sys->di.plane_info[0].ydec == 0 &&
310 p_sys->di.plane_info[1].xdec == 1 && p_sys->di.plane_info[1].ydec == 1 &&
311 p_sys->di.plane_info[2].xdec == 1 && p_sys->di.plane_info[2].ydec == 1 )
313 p_dec->fmt_out.i_codec = VLC_CODEC_I420;
315 else if( p_sys->di.plane_info[0].xdec == 0 && p_sys->di.plane_info[0].ydec == 0 &&
316 p_sys->di.plane_info[1].xdec == 0 && p_sys->di.plane_info[1].ydec == 0 &&
317 p_sys->di.plane_info[2].xdec == 0 && p_sys->di.plane_info[2].ydec == 0 )
319 p_dec->fmt_out.i_codec = VLC_CODEC_I444;
321 else
323 msg_Err( p_dec, "unknown chroma in daala sample" );
327 p_dec->fmt_out.video.i_width = p_sys->di.pic_width;
328 p_dec->fmt_out.video.i_height = p_sys->di.pic_height;
329 if( p_sys->di.pic_width && p_sys->di.pic_height )
331 p_dec->fmt_out.video.i_visible_width = p_sys->di.pic_width;
332 p_dec->fmt_out.video.i_visible_height = p_sys->di.pic_height;
335 if( p_sys->di.pixel_aspect_denominator && p_sys->di.pixel_aspect_numerator )
337 p_dec->fmt_out.video.i_sar_num = p_sys->di.pixel_aspect_numerator;
338 p_dec->fmt_out.video.i_sar_den = p_sys->di.pixel_aspect_denominator;
340 else
342 p_dec->fmt_out.video.i_sar_num = 1;
343 p_dec->fmt_out.video.i_sar_den = 1;
346 if( p_sys->di.timebase_numerator > 0 && p_sys->di.timebase_denominator > 0 )
348 p_dec->fmt_out.video.i_frame_rate = p_sys->di.timebase_numerator;
349 p_dec->fmt_out.video.i_frame_rate_base = p_sys->di.timebase_denominator;
352 msg_Dbg( p_dec, "%dx%d %.02f fps video, frame content ",
353 p_sys->di.pic_width, p_sys->di.pic_height,
354 (double)p_sys->di.timebase_numerator/p_sys->di.timebase_denominator );
356 /* The next packet in order is the comments header */
357 dpacket.b_o_s = 0;
358 dpacket.bytes = pi_size[1];
359 dpacket.packet = pp_data[1];
361 if( daala_decode_header_in( &p_sys->di, &p_sys->dc, &ds, &dpacket ) < 0 )
363 msg_Err( p_dec, "Daala comment header is corrupted" );
364 ret = VLC_EGENERIC;
365 goto cleanup;
368 ParseDaalaComments( p_dec );
370 /* The next packet in order is the setup header
371 * We need to watch out that this packet is not missing as a
372 * missing or corrupted header is fatal. */
373 dpacket.b_o_s = 0;
374 dpacket.bytes = pi_size[2];
375 dpacket.packet = pp_data[2];
376 if( daala_decode_header_in( &p_sys->di, &p_sys->dc, &ds, &dpacket ) < 0 )
378 msg_Err( p_dec, "Daala setup header is corrupted" );
379 ret = VLC_EGENERIC;
380 goto cleanup;
383 if( !p_sys->b_packetizer )
385 /* We have all the headers, initialize decoder */
386 if ( ( p_sys->dcx = daala_decode_create( &p_sys->di, ds ) ) == NULL )
388 msg_Err( p_dec, "Could not allocate Daala decoder" );
389 ret = VLC_EGENERIC;
390 goto cleanup;
393 else
395 void* p_extra = realloc( p_dec->fmt_out.p_extra,
396 p_dec->fmt_in.i_extra );
397 if( unlikely( p_extra == NULL ) )
399 ret = VLC_ENOMEM;
400 goto cleanup;
402 p_dec->fmt_out.p_extra = p_extra;
403 p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra;
404 memcpy( p_dec->fmt_out.p_extra,
405 p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra );
408 cleanup:
409 /* Clean up the decoder setup info... we're done with it */
410 daala_setup_free( ds );
412 return ret;
415 /*****************************************************************************
416 * ProcessPacket: processes a daala packet.
417 *****************************************************************************/
418 static void *ProcessPacket( decoder_t *p_dec, daala_packet *p_dpacket,
419 block_t *p_block )
421 decoder_sys_t *p_sys = p_dec->p_sys;
422 void *p_buf;
424 if( ( p_block->i_flags&(BLOCK_FLAG_CORRUPTED) ) != 0 )
426 /* Don't send the the first packet after a discontinuity to
427 * daala_decode, otherwise we get purple/green display artifacts
428 * appearing in the video output */
429 block_Release(p_block);
430 return NULL;
433 /* Date management */
434 if( p_block->i_pts > VLC_TS_INVALID && p_block->i_pts != p_sys->i_pts )
436 p_sys->i_pts = p_block->i_pts;
439 if( p_sys->b_packetizer )
441 /* Date management */
442 p_block->i_dts = p_block->i_pts = p_sys->i_pts;
444 p_block->i_length = p_sys->i_pts - p_block->i_pts;
446 p_buf = p_block;
448 else
450 p_buf = DecodePacket( p_dec, p_dpacket );
451 block_Release( p_block );
454 /* Date management */
455 p_sys->i_pts += ( CLOCK_FREQ * p_sys->di.timebase_denominator /
456 p_sys->di.timebase_numerator ); /* 1 frame per packet */
458 return p_buf;
461 /*****************************************************************************
462 * DecodePacket: decodes a Daala packet.
463 *****************************************************************************/
464 static picture_t *DecodePacket( decoder_t *p_dec, daala_packet *p_dpacket )
466 decoder_sys_t *p_sys = p_dec->p_sys;
467 picture_t *p_pic;
468 daala_image ycbcr;
470 if (daala_decode_packet_in( p_sys->dcx, p_dpacket ) < 0)
471 return NULL; /* bad packet */
473 if (!daala_decode_img_out( p_sys->dcx, &ycbcr ))
474 return NULL;
476 /* Check for keyframe */
477 if( daala_packet_iskeyframe( p_dpacket ) )
478 p_sys->b_decoded_first_keyframe = true;
480 /* Get a new picture */
481 if( decoder_UpdateVideoFormat( p_dec ) )
482 return NULL;
483 p_pic = decoder_NewPicture( p_dec );
484 if( !p_pic ) return NULL;
486 daala_CopyPicture( p_pic, &ycbcr );
488 p_pic->date = p_sys->i_pts;
490 return p_pic;
493 /*****************************************************************************
494 * ParseDaalaComments:
495 *****************************************************************************/
496 static void ParseDaalaComments( decoder_t *p_dec )
498 char *psz_name, *psz_value, *psz_comment;
499 /* Regarding the daala_comment structure: */
501 /* The metadata is stored as a series of (tag, value) pairs, in
502 length-encoded string vectors. The first occurrence of the '='
503 character delimits the tag and value. A particular tag may
504 occur more than once, and order is significant. The character
505 set encoding for the strings is always UTF-8, but the tag names
506 are limited to ASCII, and treated as case-insensitive. See the
507 Theora specification, Section 6.3.3 for details. */
509 /* In filling in this structure, daala_decode_header_in() will
510 null-terminate the user_comment strings for safety. However,
511 the bitstream format itself treats them as 8-bit clean vectors,
512 possibly containing null characters, and so the length array
513 should be treated as their authoritative length. */
514 for ( int i = 0; i < p_dec->p_sys->dc.comments; i++ )
516 int clen = p_dec->p_sys->dc.comment_lengths[i];
517 if ( clen <= 0 || clen >= INT_MAX ) { continue; }
518 psz_comment = malloc( clen + 1 );
519 if( !psz_comment )
520 break;
521 memcpy( (void*)psz_comment, (void*)p_dec->p_sys->dc.user_comments[i], clen + 1 );
522 psz_comment[clen] = '\0';
524 psz_name = psz_comment;
525 psz_value = strchr( psz_comment, '=' );
526 if( psz_value )
528 *psz_value = '\0';
529 psz_value++;
531 if( !p_dec->p_description )
532 p_dec->p_description = vlc_meta_New();
533 /* TODO: Since psz_value can contain NULLs see if there is an
534 * instance where we need to preserve the full length of this string */
535 if( p_dec->p_description )
536 vlc_meta_AddExtra( p_dec->p_description, psz_name, psz_value );
538 free( psz_comment );
542 /*****************************************************************************
543 * CloseDecoder: daala decoder destruction
544 *****************************************************************************/
545 static void CloseDecoder( vlc_object_t *p_this )
547 decoder_t *p_dec = (decoder_t *)p_this;
548 decoder_sys_t *p_sys = p_dec->p_sys;
550 daala_info_clear(&p_sys->di);
551 daala_comment_clear(&p_sys->dc);
552 daala_decode_free(p_sys->dcx);
553 free( p_sys );
556 /*****************************************************************************
557 * daala_CopyPicture: copy a picture from daala internal buffers to a
558 * picture_t structure.
559 *****************************************************************************/
560 static void daala_CopyPicture( picture_t *p_pic,
561 daala_image *ycbcr )
563 const int i_planes = p_pic->i_planes < 3 ? p_pic->i_planes : 3;
564 for( int i_plane = 0; i_plane < i_planes; i_plane++ )
566 const int i_total_lines = __MIN(p_pic->p[i_plane].i_lines,
567 ycbcr->height >> ycbcr->planes[i_plane].ydec);
568 uint8_t *p_dst = p_pic->p[i_plane].p_pixels;
569 uint8_t *p_src = ycbcr->planes[i_plane].data;
570 const int i_dst_stride = p_pic->p[i_plane].i_pitch;
571 const int i_src_stride = ycbcr->planes[i_plane].ystride;
572 for( int i_line = 0; i_line < i_total_lines; i_line++ )
574 memcpy( p_dst, p_src, i_src_stride );
575 p_src += i_src_stride;
576 p_dst += i_dst_stride;
581 #ifdef ENABLE_SOUT
582 struct encoder_sys_t
584 daala_info di; /* daala bitstream settings */
585 daala_comment dc; /* daala comment header */
586 daala_enc_ctx *dcx; /* daala context */
589 static int OpenEncoder( vlc_object_t *p_this )
591 encoder_t *p_enc = (encoder_t *)p_this;
592 encoder_sys_t *p_sys;
593 daala_packet header;
594 int status;
596 if( p_enc->fmt_out.i_codec != VLC_CODEC_DAALA &&
597 !p_enc->obj.force )
599 return VLC_EGENERIC;
602 /* Allocate the memory needed to store the encoder's structure */
603 p_sys = malloc( sizeof( encoder_sys_t ) );
604 if( !p_sys )
605 return VLC_ENOMEM;
606 p_enc->p_sys = p_sys;
608 p_enc->pf_encode_video = Encode;
609 p_enc->fmt_in.i_codec = VLC_CODEC_I420;
610 p_enc->fmt_out.i_codec = VLC_CODEC_DAALA;
612 config_ChainParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg );
614 char *psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX "chroma-fmt" );
615 uint32_t i_codec;
616 if( !psz_tmp ) {
617 free(p_sys);
618 return VLC_ENOMEM;
619 } else {
620 if( !strcmp( psz_tmp, "420" ) ) {
621 i_codec = VLC_CODEC_I420;
623 else if( !strcmp( psz_tmp, "444" ) ) {
624 i_codec = VLC_CODEC_I444;
626 else {
627 msg_Err( p_enc, "Invalid chroma format: %s", psz_tmp );
628 free( psz_tmp );
629 free( p_sys );
630 return VLC_EGENERIC;
632 free( psz_tmp );
633 p_enc->fmt_in.i_codec = i_codec;
634 /* update bits_per_pixel */
635 video_format_Setup(&p_enc->fmt_in.video, i_codec,
636 p_enc->fmt_in.video.i_width,
637 p_enc->fmt_in.video.i_height,
638 p_enc->fmt_in.video.i_visible_width,
639 p_enc->fmt_in.video.i_visible_height,
640 p_enc->fmt_in.video.i_sar_num,
641 p_enc->fmt_in.video.i_sar_den);
644 daala_info_init( &p_sys->di );
646 p_sys->di.pic_width = p_enc->fmt_in.video.i_visible_width;
647 p_sys->di.pic_height = p_enc->fmt_in.video.i_visible_height;
649 p_sys->di.nplanes = 3;
650 for (int i = 0; i < p_sys->di.nplanes; i++)
652 p_sys->di.plane_info[i].xdec = i > 0 && i_codec != VLC_CODEC_I444;
653 p_sys->di.plane_info[i].ydec = i_codec == VLC_CODEC_I420 ?
654 p_sys->di.plane_info[i].xdec : 0;
656 p_sys->di.frame_duration = 1;
658 if( !p_enc->fmt_in.video.i_frame_rate ||
659 !p_enc->fmt_in.video.i_frame_rate_base )
661 p_sys->di.timebase_numerator = 25;
662 p_sys->di.timebase_denominator = 1;
664 else
666 p_sys->di.timebase_numerator = p_enc->fmt_in.video.i_frame_rate;
667 p_sys->di.timebase_denominator = p_enc->fmt_in.video.i_frame_rate_base;
670 if( p_enc->fmt_in.video.i_sar_num > 0 && p_enc->fmt_in.video.i_sar_den > 0 )
672 unsigned i_dst_num, i_dst_den;
673 vlc_ureduce( &i_dst_num, &i_dst_den,
674 p_enc->fmt_in.video.i_sar_num,
675 p_enc->fmt_in.video.i_sar_den, 0 );
676 p_sys->di.pixel_aspect_numerator = i_dst_num;
677 p_sys->di.pixel_aspect_denominator = i_dst_den;
679 else
681 p_sys->di.pixel_aspect_numerator = 4;
682 p_sys->di.pixel_aspect_denominator = 3;
685 p_sys->di.keyframe_rate = var_GetInteger( p_enc, ENC_CFG_PREFIX "keyint" );
687 daala_enc_ctx *dcx;
688 p_sys->dcx = dcx = daala_encode_create( &p_sys->di );
689 if( !dcx )
691 free( p_sys );
692 return VLC_ENOMEM;
695 daala_comment_init( &p_sys->dc );
697 int i_quality = var_GetInteger( p_enc, ENC_CFG_PREFIX "quality" );
698 daala_encode_ctl( dcx, OD_SET_QUANT, &i_quality, sizeof(i_quality) );
700 /* Create and store headers */
701 while( ( status = daala_encode_flush_header( dcx, &p_sys->dc, &header ) ) )
703 if ( status < 0 )
705 CloseEncoder( p_this );
706 return VLC_EGENERIC;
708 if( xiph_AppendHeaders( &p_enc->fmt_out.i_extra,
709 &p_enc->fmt_out.p_extra, header.bytes,
710 header.packet ) )
712 p_enc->fmt_out.i_extra = 0;
713 p_enc->fmt_out.p_extra = NULL;
716 return VLC_SUCCESS;
719 static block_t *Encode( encoder_t *p_enc, picture_t *p_pict )
721 encoder_sys_t *p_sys = p_enc->p_sys;
722 daala_packet dpacket;
723 block_t *p_block;
724 daala_image img;
726 if( !p_pict ) return NULL;
728 const int i_width = p_sys->di.pic_width;
729 const int i_height = p_sys->di.pic_height;
731 /* Sanity check */
732 if( p_pict->p[0].i_pitch < i_width ||
733 p_pict->p[0].i_lines < i_height )
735 msg_Err( p_enc, "frame is smaller than encoding size"
736 "(%ix%i->%ix%i) -> dropping frame",
737 p_pict->p[0].i_pitch, p_pict->p[0].i_lines,
738 i_width, i_height );
739 return NULL;
742 /* Daala is a one-frame-in, one-frame-out system. Submit a frame
743 * for compression and pull out the packet. */
745 img.nplanes = p_sys->di.nplanes;
746 img.width = i_width;
747 img.height = i_height;
748 for( int i = 0; i < img.nplanes; i++ )
750 img.planes[i].data = p_pict->p[i].p_pixels;
751 img.planes[i].xdec = p_sys->di.plane_info[i].xdec;
752 img.planes[i].ydec = p_sys->di.plane_info[i].ydec;
753 img.planes[i].xstride = 1;
754 img.planes[i].ystride = p_pict->p[i].i_pitch;
755 img.planes[i].bitdepth = 8; /*FIXME: support higher bit depths*/
758 if( daala_encode_img_in( p_sys->dcx, &img, 0 ) < 0 )
760 msg_Warn( p_enc, "failed encoding a frame" );
761 return NULL;
764 daala_encode_packet_out( p_sys->dcx, 0, &dpacket );
766 /* Daala packet to block */
767 p_block = block_Alloc( dpacket.bytes );
768 memcpy( p_block->p_buffer, dpacket.packet, dpacket.bytes );
769 p_block->i_dts = p_block->i_pts = p_pict->date;
771 if( daala_packet_iskeyframe( &dpacket ) )
772 p_block->i_flags |= BLOCK_FLAG_TYPE_I;
774 return p_block;
777 static void CloseEncoder( vlc_object_t *p_this )
779 encoder_t *p_enc = (encoder_t *)p_this;
780 encoder_sys_t *p_sys = p_enc->p_sys;
782 daala_info_clear(&p_sys->di);
783 daala_comment_clear(&p_sys->dc);
784 daala_encode_free(p_sys->dcx);
785 free( p_sys );
787 #endif