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 /*****************************************************************************
26 *****************************************************************************/
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>
40 #include <daala/daalaenc.h>
45 /*****************************************************************************
46 * decoder_sys_t : daala decoder descriptor
47 *****************************************************************************/
61 daala_info di
; /* daala bitstream settings */
62 daala_comment dc
; /* daala comment information */
63 daala_dec_ctx
*dcx
; /* daala decoder context */
68 bool b_decoded_first_keyframe
;
76 /*****************************************************************************
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
* );
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
[] = {
101 static const char *const enc_chromafmt_list_text
[] = {
106 /*****************************************************************************
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." )
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" )
125 set_description( N_("Daala video packetizer") )
126 set_capability( "packetizer", 100 )
127 set_callbacks( OpenPacketizer
, CloseDecoder
)
128 add_shortcut( "daala" )
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
)
152 static const char *const ppsz_enc_options
[] = {
153 "quality", "keyint", "chroma-fmt", NULL
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
)
170 /* Allocate the memory needed to store the decoder's structure */
171 p_sys
= malloc(sizeof(*p_sys
));
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;
182 /* Set output properties */
183 p_dec
->fmt_out
.i_codec
= VLC_CODEC_I420
;
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
);
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
;
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
;
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
);
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
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
);
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 */
266 block_t
*p_block
= *pp_block
; *pp_block
= NULL
;
267 if( p_block
== 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
];
285 if( xiph_SplitHeaders( pi_size
, pp_data
, &i_count
,
286 p_dec
->fmt_in
.i_extra
, p_dec
->fmt_in
.p_extra
) )
291 dpacket
.granulepos
= -1;
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" );
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
;
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
;
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 */
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" );
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. */
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" );
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" );
395 void* p_extra
= realloc( p_dec
->fmt_out
.p_extra
,
396 p_dec
->fmt_in
.i_extra
);
397 if( unlikely( p_extra
== NULL
) )
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
);
409 /* Clean up the decoder setup info... we're done with it */
410 daala_setup_free( ds
);
415 /*****************************************************************************
416 * ProcessPacket: processes a daala packet.
417 *****************************************************************************/
418 static void *ProcessPacket( decoder_t
*p_dec
, daala_packet
*p_dpacket
,
421 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
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
);
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
;
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 */
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
;
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
))
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
) )
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
;
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 );
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
, '=' );
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
);
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
);
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
,
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
;
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
;
596 if( p_enc
->fmt_out
.i_codec
!= VLC_CODEC_DAALA
&&
602 /* Allocate the memory needed to store the encoder's structure */
603 p_sys
= malloc( sizeof( encoder_sys_t
) );
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" );
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
;
627 msg_Err( p_enc
, "Invalid chroma format: %s", 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;
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
;
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" );
688 p_sys
->dcx
= dcx
= daala_encode_create( &p_sys
->di
);
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
) ) )
705 CloseEncoder( p_this
);
708 if( xiph_AppendHeaders( &p_enc
->fmt_out
.i_extra
,
709 &p_enc
->fmt_out
.p_extra
, header
.bytes
,
712 p_enc
->fmt_out
.i_extra
= 0;
713 p_enc
->fmt_out
.p_extra
= NULL
;
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
;
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
;
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
,
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
;
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" );
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
;
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
);