contrib: cargo: use cargo/vendored-openssl if needed
[vlc.git] / modules / codec / aom.c
blob20ec11c75c923648e2d407af273143b8447a54d9
1 /*****************************************************************************
2 * aom.c: libaom encoder and decoder (AV1) module
3 *****************************************************************************
4 * Copyright (C) 2016 VLC authors and VideoLAN
6 * Authors: Tristan Matthews <tmatth@videolan.org>
7 * Based on vpx.c by: Rafaël Carré <funman@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>
35 #include <aom/aom_decoder.h>
36 #include <aom/aomdx.h>
38 #ifdef ENABLE_SOUT
39 # include <aom/aom_encoder.h>
40 # include <aom/aomcx.h>
41 # include <aom/aom_image.h>
42 # define SOUT_CFG_PREFIX "sout-aom-"
43 #endif
45 #include "../packetizer/iso_color_tables.h"
47 /****************************************************************************
48 * Local prototypes
49 ****************************************************************************/
50 static int OpenDecoder(vlc_object_t *);
51 static void CloseDecoder(vlc_object_t *);
52 #ifdef ENABLE_SOUT
53 static int OpenEncoder(vlc_object_t *);
54 static void CloseEncoder(vlc_object_t *);
55 static block_t *Encode(encoder_t *p_enc, picture_t *p_pict);
57 static const int pi_enc_bitdepth_values_list[] =
58 { 8, 10, 12 };
59 static const char *const ppsz_enc_bitdepth_text [] =
60 { N_("8 bpp"), N_("10 bpp"), N_("12 bpp") };
61 #endif
63 /*****************************************************************************
64 * Module descriptor
65 *****************************************************************************/
67 vlc_module_begin ()
68 set_shortname("aom")
69 set_description(N_("AOM video decoder"))
70 set_capability("video decoder", 100)
71 set_callbacks(OpenDecoder, CloseDecoder)
72 set_category(CAT_INPUT)
73 set_subcategory(SUBCAT_INPUT_VCODEC)
74 #ifdef ENABLE_SOUT
75 add_submodule()
76 set_shortname("aom")
77 set_capability("encoder", 101)
78 set_description(N_("AOM video encoder"))
79 set_callbacks(OpenEncoder, CloseEncoder)
80 add_integer( SOUT_CFG_PREFIX "profile", 0, "Profile", NULL, true )
81 change_integer_range( 0, 3 )
82 add_integer( SOUT_CFG_PREFIX "bitdepth", 8, "Bit Depth", NULL, true )
83 change_integer_list( pi_enc_bitdepth_values_list, ppsz_enc_bitdepth_text )
84 add_integer( SOUT_CFG_PREFIX "tile-rows", 0, "Tile Rows (in log2 units)", NULL, true )
85 change_integer_range( 0, 6 ) /* 1 << 6 == MAX_TILE_ROWS */
86 add_integer( SOUT_CFG_PREFIX "tile-columns", 0, "Tile Columns (in log2 units)", NULL, true )
87 change_integer_range( 0, 6 ) /* 1 << 6 == MAX_TILE_COLS */
88 add_integer( SOUT_CFG_PREFIX "cpu-used", 1, "Speed setting", NULL, true )
89 change_integer_range( 0, 8 ) /* good: 0-5, realtime: 6-8 */
90 add_integer( SOUT_CFG_PREFIX "lag-in-frames", 16, "Maximum number of lookahead frames", NULL, true )
91 change_integer_range(0, 70 /* MAX_LAG_BUFFERS + MAX_LAP_BUFFERS */ )
92 add_integer( SOUT_CFG_PREFIX "usage", 0, "Usage (0: good, 1: realtime)", NULL, true )
93 change_integer_range( 0, 1 )
94 add_integer( SOUT_CFG_PREFIX "rc-end-usage", 1, "Usage (0: VBR, 1: CBR, 2: CQ, 3: Q)", NULL, true )
95 change_integer_range( 0, 4 )
96 #ifdef AOM_CTRL_AV1E_SET_ROW_MT
97 add_bool( SOUT_CFG_PREFIX "row-mt", false, "Row Multithreading", NULL, true )
98 #endif
99 #endif
100 vlc_module_end ()
102 static void aom_err_msg(vlc_object_t *this, aom_codec_ctx_t *ctx,
103 const char *msg)
105 const char *error = aom_codec_error(ctx);
106 const char *detail = aom_codec_error_detail(ctx);
107 if (!detail)
108 detail = "no specific information";
109 msg_Err(this, msg, error, detail);
112 #define AOM_ERR(this, ctx, msg) aom_err_msg(VLC_OBJECT(this), ctx, msg ": %s (%s)")
113 #define AOM_MAX_FRAMES_DEPTH 64
115 /*****************************************************************************
116 * decoder_sys_t: libaom decoder descriptor
117 *****************************************************************************/
118 struct frame_priv_s
120 vlc_tick_t pts;
123 typedef struct
125 aom_codec_ctx_t ctx;
126 struct frame_priv_s frame_priv[AOM_MAX_FRAMES_DEPTH];
127 unsigned i_next_frame_priv;
128 } decoder_sys_t;
130 static const struct
132 vlc_fourcc_t i_chroma;
133 enum aom_img_fmt i_chroma_id;
134 uint8_t i_bitdepth;
135 uint8_t i_needs_hack;
137 } chroma_table[] =
139 { VLC_CODEC_I420, AOM_IMG_FMT_I420, 8, 0 },
140 { VLC_CODEC_I422, AOM_IMG_FMT_I422, 8, 0 },
141 { VLC_CODEC_I444, AOM_IMG_FMT_I444, 8, 0 },
143 { VLC_CODEC_YV12, AOM_IMG_FMT_YV12, 8, 0 },
145 { VLC_CODEC_GBR_PLANAR, AOM_IMG_FMT_I444, 8, 1 },
146 { VLC_CODEC_GBR_PLANAR_10L, AOM_IMG_FMT_I44416, 10, 1 },
148 { VLC_CODEC_I420_10L, AOM_IMG_FMT_I42016, 10, 0 },
149 { VLC_CODEC_I422_10L, AOM_IMG_FMT_I42216, 10, 0 },
150 { VLC_CODEC_I444_10L, AOM_IMG_FMT_I44416, 10, 0 },
152 { VLC_CODEC_I420_12L, AOM_IMG_FMT_I42016, 12, 0 },
153 { VLC_CODEC_I422_12L, AOM_IMG_FMT_I42216, 12, 0 },
154 { VLC_CODEC_I444_12L, AOM_IMG_FMT_I44416, 12, 0 },
156 { VLC_CODEC_I444_16L, AOM_IMG_FMT_I44416, 16, 0 },
159 static vlc_fourcc_t FindVlcChroma( struct aom_image *img )
161 uint8_t hack = (img->fmt & AOM_IMG_FMT_I444) && (img->tc == AOM_CICP_TC_SRGB);
163 for( unsigned int i = 0; i < ARRAY_SIZE(chroma_table); i++ )
164 if( chroma_table[i].i_chroma_id == img->fmt &&
165 chroma_table[i].i_bitdepth == img->bit_depth &&
166 chroma_table[i].i_needs_hack == hack )
167 return chroma_table[i].i_chroma;
169 return 0;
172 static void CopyPicture(const struct aom_image *img, picture_t *pic)
174 for (int plane = 0; plane < pic->i_planes; plane++ ) {
175 plane_t src_plane = pic->p[plane];
176 src_plane.p_pixels = img->planes[plane];
177 src_plane.i_pitch = img->stride[plane];
178 plane_CopyPixels(&pic->p[plane], &src_plane);
182 static int PushFrame(decoder_t *dec, block_t *block)
184 decoder_sys_t *p_sys = dec->p_sys;
185 aom_codec_ctx_t *ctx = &p_sys->ctx;
186 const uint8_t *p_buffer;
187 size_t i_buffer;
189 /* Associate packet PTS with decoded frame */
190 uintptr_t priv_index = p_sys->i_next_frame_priv++ % AOM_MAX_FRAMES_DEPTH;
192 if(likely(block))
194 p_buffer = block->p_buffer;
195 i_buffer = block->i_buffer;
196 p_sys->frame_priv[priv_index].pts = (block->i_pts != VLC_TICK_INVALID) ? block->i_pts : block->i_dts;
198 else
200 p_buffer = NULL;
201 i_buffer = 0;
204 aom_codec_err_t err;
205 err = aom_codec_decode(ctx, p_buffer, i_buffer, (void*)priv_index);
207 if(block)
208 block_Release(block);
210 if (err != AOM_CODEC_OK) {
211 AOM_ERR(dec, ctx, "Failed to decode frame");
212 if (err == AOM_CODEC_UNSUP_BITSTREAM)
213 return VLCDEC_ECRITICAL;
215 return VLCDEC_SUCCESS;
218 static void OutputFrame(decoder_t *dec, const struct aom_image *img)
220 video_format_t *v = &dec->fmt_out.video;
222 if (img->d_w != v->i_visible_width || img->d_h != v->i_visible_height)
224 v->i_visible_width = dec->fmt_out.video.i_width = img->d_w;
225 v->i_visible_height = dec->fmt_out.video.i_height = img->d_h;
228 if( !dec->fmt_out.video.i_sar_num || !dec->fmt_out.video.i_sar_den )
230 dec->fmt_out.video.i_sar_num = 1;
231 dec->fmt_out.video.i_sar_den = 1;
234 if(dec->fmt_in.video.primaries == COLOR_PRIMARIES_UNDEF)
236 v->primaries = iso_23001_8_cp_to_vlc_primaries(img->cp);
237 v->transfer = iso_23001_8_tc_to_vlc_xfer(img->tc);
238 v->space = iso_23001_8_mc_to_vlc_coeffs(img->mc);
239 v->color_range = img->range == AOM_CR_FULL_RANGE ? COLOR_RANGE_FULL : COLOR_RANGE_LIMITED;
242 dec->fmt_out.video.projection_mode = dec->fmt_in.video.projection_mode;
243 dec->fmt_out.video.multiview_mode = dec->fmt_in.video.multiview_mode;
244 dec->fmt_out.video.pose = dec->fmt_in.video.pose;
246 if (decoder_UpdateVideoFormat(dec) == 0)
248 picture_t *pic = decoder_NewPicture(dec);
249 if (pic)
251 decoder_sys_t *p_sys = dec->p_sys;
252 CopyPicture(img, pic);
254 /* fetches back the PTS */
256 pic->b_progressive = true; /* codec does not support interlacing */
257 pic->date = p_sys->frame_priv[(uintptr_t)img->user_priv].pts;
259 decoder_QueueVideo(dec, pic);
264 static int PopFrames(decoder_t *dec,
265 void(*pf_output)(decoder_t *, const struct aom_image *))
267 decoder_sys_t *p_sys = dec->p_sys;
268 aom_codec_ctx_t *ctx = &p_sys->ctx;
270 for(const void *iter = NULL;; )
272 struct aom_image *img = aom_codec_get_frame(ctx, &iter);
273 if (!img)
274 break;
276 dec->fmt_out.i_codec = FindVlcChroma(img);
277 if (dec->fmt_out.i_codec == 0) {
278 msg_Err(dec, "Unsupported output colorspace %d", img->fmt);
279 continue;
282 pf_output(dec, img);
285 return VLCDEC_SUCCESS;
288 /****************************************************************************
289 * Flush: clears decoder between seeks
290 ****************************************************************************/
291 static void DropFrame(decoder_t *dec, const struct aom_image *img)
293 VLC_UNUSED(dec);
294 VLC_UNUSED(img);
295 /* do nothing for now */
298 static void FlushDecoder(decoder_t *dec)
300 decoder_sys_t *p_sys = dec->p_sys;
301 aom_codec_ctx_t *ctx = &p_sys->ctx;
303 if(PushFrame(dec, NULL) != VLCDEC_SUCCESS)
304 AOM_ERR(dec, ctx, "Failed to flush decoder");
305 else
306 PopFrames(dec, DropFrame);
309 /****************************************************************************
310 * Decode: the whole thing
311 ****************************************************************************/
312 static int Decode(decoder_t *dec, block_t *block)
314 if (block && block->i_flags & (BLOCK_FLAG_CORRUPTED))
316 block_Release(block);
317 return VLCDEC_SUCCESS;
320 int i_ret = PushFrame(dec, block);
322 PopFrames(dec, OutputFrame);
324 return i_ret;
327 /*****************************************************************************
328 * OpenDecoder: probe the decoder
329 *****************************************************************************/
330 static int OpenDecoder(vlc_object_t *p_this)
332 decoder_t *dec = (decoder_t *)p_this;
333 const aom_codec_iface_t *iface;
334 int av_version;
336 if (dec->fmt_in.i_codec != VLC_CODEC_AV1)
337 return VLC_EGENERIC;
339 iface = &aom_codec_av1_dx_algo;
340 av_version = 1;
342 decoder_sys_t *sys = malloc(sizeof(*sys));
343 if (!sys)
344 return VLC_ENOMEM;
345 dec->p_sys = sys;
347 sys->i_next_frame_priv = 0;
349 struct aom_codec_dec_cfg deccfg = {
350 .threads = __MIN(vlc_GetCPUCount(), 16),
351 .allow_lowbitdepth = 1
354 msg_Dbg(p_this, "AV%d: using libaom version %s (build options %s)",
355 av_version, aom_codec_version_str(), aom_codec_build_config());
357 if (aom_codec_dec_init(&sys->ctx, iface, &deccfg, 0) != AOM_CODEC_OK) {
358 AOM_ERR(p_this, &sys->ctx, "Failed to initialize decoder");
359 free(sys);
360 return VLC_EGENERIC;;
363 dec->pf_decode = Decode;
364 dec->pf_flush = FlushDecoder;
366 dec->fmt_out.video.i_width = dec->fmt_in.video.i_width;
367 dec->fmt_out.video.i_height = dec->fmt_in.video.i_height;
368 dec->fmt_out.i_codec = VLC_CODEC_I420;
370 if (dec->fmt_in.video.i_sar_num > 0 && dec->fmt_in.video.i_sar_den > 0) {
371 dec->fmt_out.video.i_sar_num = dec->fmt_in.video.i_sar_num;
372 dec->fmt_out.video.i_sar_den = dec->fmt_in.video.i_sar_den;
374 dec->fmt_out.video.primaries = dec->fmt_in.video.primaries;
375 dec->fmt_out.video.transfer = dec->fmt_in.video.transfer;
376 dec->fmt_out.video.space = dec->fmt_in.video.space;
377 dec->fmt_out.video.color_range = dec->fmt_in.video.color_range;
379 return VLC_SUCCESS;
382 static void destroy_context(vlc_object_t *p_this, aom_codec_ctx_t *context)
384 if (aom_codec_destroy(context))
385 AOM_ERR(p_this, context, "Failed to destroy codec context");
388 /*****************************************************************************
389 * CloseDecoder: decoder destruction
390 *****************************************************************************/
391 static void CloseDecoder(vlc_object_t *p_this)
393 decoder_t *dec = (decoder_t *)p_this;
394 decoder_sys_t *sys = dec->p_sys;
396 /* Flush decoder */
397 FlushDecoder(dec);
399 destroy_context(p_this, &sys->ctx);
401 free(sys);
404 #ifdef ENABLE_SOUT
406 #ifndef AOM_USAGE_REALTIME
407 # define AOM_USAGE_REALTIME 1
408 #endif
410 /*****************************************************************************
411 * encoder_sys_t: libaom encoder descriptor
412 *****************************************************************************/
413 typedef struct
415 struct aom_codec_ctx ctx;
416 } encoder_sys_t;
418 /*****************************************************************************
419 * OpenEncoder: probe the encoder
420 *****************************************************************************/
421 static int OpenEncoder(vlc_object_t *p_this)
423 encoder_t *p_enc = (encoder_t *)p_this;
424 encoder_sys_t *p_sys;
426 if (p_enc->fmt_out.i_codec != VLC_CODEC_AV1)
427 return VLC_EGENERIC;
429 /* Allocate the memory needed to store the encoder's structure */
430 p_sys = malloc(sizeof(*p_sys));
431 if (p_sys == NULL)
432 return VLC_ENOMEM;
434 p_enc->p_sys = p_sys;
436 const struct aom_codec_iface *iface = &aom_codec_av1_cx_algo;
438 struct aom_codec_enc_cfg enccfg = { 0 };
439 aom_codec_enc_config_default(iface, &enccfg, 0);
440 /* TODO: implement 2-pass */
441 enccfg.g_pass = AOM_RC_ONE_PASS;
442 enccfg.g_timebase.num = p_enc->fmt_in.video.i_frame_rate_base;
443 enccfg.g_timebase.den = p_enc->fmt_in.video.i_frame_rate;
444 enccfg.g_threads = __MIN(vlc_GetCPUCount(), 4);
445 enccfg.g_w = p_enc->fmt_in.video.i_visible_width;
446 enccfg.g_h = p_enc->fmt_in.video.i_visible_height;
447 enccfg.rc_end_usage = var_InheritInteger( p_enc, SOUT_CFG_PREFIX "rc-end-usage" );
448 enccfg.g_usage = var_InheritInteger( p_enc, SOUT_CFG_PREFIX "usage" );
449 /* we have no pcr on sout, hence this defaulting to 16 */
450 enccfg.g_lag_in_frames = var_InheritInteger( p_enc, SOUT_CFG_PREFIX "lag-in-frames" );
451 if( enccfg.g_usage == AOM_USAGE_REALTIME && enccfg.g_lag_in_frames != 0 )
453 msg_Warn( p_enc, "Non-zero lag in frames is not supported for realtime, forcing 0" );
454 enccfg.g_lag_in_frames = 0;
457 int enc_flags;
458 int i_profile = var_InheritInteger( p_enc, SOUT_CFG_PREFIX "profile" );
459 int i_bit_depth = var_InheritInteger( p_enc, SOUT_CFG_PREFIX "bitdepth" );
460 int i_tile_rows = var_InheritInteger( p_enc, SOUT_CFG_PREFIX "tile-rows" );
461 int i_tile_columns = var_InheritInteger( p_enc, SOUT_CFG_PREFIX "tile-columns" );
462 #ifdef AOM_CTRL_AV1E_SET_ROW_MT
463 bool b_row_mt = var_GetBool( p_enc, SOUT_CFG_PREFIX "row-mt" );
464 #endif
466 /* TODO: implement higher profiles, bit depths and other pixformats. */
467 switch( i_profile )
469 case 0:
470 /* Main Profile: 8 and 10-bit 4:2:0. */
471 enccfg.g_profile = 0;
472 switch( i_bit_depth )
474 case 10:
475 p_enc->fmt_in.i_codec = VLC_CODEC_I420_10L;
476 enc_flags = AOM_CODEC_USE_HIGHBITDEPTH;
477 break;
478 case 8:
479 p_enc->fmt_in.i_codec = VLC_CODEC_I420;
480 enc_flags = 0;
481 break;
482 default:
483 msg_Err( p_enc, "%d bit is unsupported for profile %d", i_bit_depth, i_profile );
484 free( p_sys );
485 return VLC_EGENERIC;
487 enccfg.g_bit_depth = i_bit_depth;
488 break;
490 case 1:
491 /* High Profile: 8 and 10-bit 4:4:4 */
492 /* fallthrough */
493 case 2:
494 /* Professional Profile: 8, 10 and 12-bit for 4:2:2, otherwise 12-bit. */
495 /* fallthrough */
496 default:
497 msg_Err( p_enc, "Unsupported profile %d", i_profile );
498 free( p_sys );
499 return VLC_EGENERIC;
502 msg_Dbg(p_this, "AV1: using libaom version %s (build options %s)",
503 aom_codec_version_str(), aom_codec_build_config());
505 struct aom_codec_ctx *ctx = &p_sys->ctx;
506 if (aom_codec_enc_init(ctx, iface, &enccfg, enc_flags) != AOM_CODEC_OK)
508 AOM_ERR(p_this, ctx, "Failed to initialize encoder");
509 free(p_sys);
510 return VLC_EGENERIC;
513 if (i_tile_rows >= 0 &&
514 aom_codec_control(ctx, AV1E_SET_TILE_ROWS, i_tile_rows))
516 AOM_ERR(p_this, ctx, "Failed to set tile rows");
517 destroy_context(p_this, ctx);
518 free(p_sys);
519 return VLC_EGENERIC;
522 if (i_tile_columns >= 0 &&
523 aom_codec_control(ctx, AV1E_SET_TILE_COLUMNS, i_tile_columns))
525 AOM_ERR(p_this, ctx, "Failed to set tile columns");
526 destroy_context(p_this, ctx);
527 free(p_sys);
528 return VLC_EGENERIC;
531 #ifdef AOM_CTRL_AV1E_SET_ROW_MT
532 if (b_row_mt &&
533 aom_codec_control(ctx, AV1E_SET_ROW_MT, b_row_mt))
535 AOM_ERR(p_this, ctx, "Failed to set row-multithreading");
536 destroy_context(p_this, ctx);
537 free(p_sys);
538 return VLC_EGENERIC;
540 #endif
542 int i_cpu_used = var_InheritInteger( p_enc, SOUT_CFG_PREFIX "cpu-used" );
543 if (aom_codec_control(ctx, AOME_SET_CPUUSED, i_cpu_used))
545 AOM_ERR(p_this, ctx, "Failed to set cpu-used");
546 destroy_context(p_this, ctx);
547 free(p_sys);
548 return VLC_EGENERIC;
551 p_enc->pf_encode_video = Encode;
553 return VLC_SUCCESS;
556 /****************************************************************************
557 * Encode: the whole thing
558 ****************************************************************************/
559 static block_t *Encode(encoder_t *p_enc, picture_t *p_pict)
561 encoder_sys_t *p_sys = p_enc->p_sys;
562 struct aom_codec_ctx *ctx = &p_sys->ctx;
564 if (!p_pict) return NULL;
566 aom_image_t img = { 0 };
567 unsigned i_w = p_enc->fmt_in.video.i_visible_width;
568 unsigned i_h = p_enc->fmt_in.video.i_visible_height;
569 const aom_img_fmt_t img_fmt = p_enc->fmt_in.i_codec == VLC_CODEC_I420_10L ?
570 AOM_IMG_FMT_I42016 : AOM_IMG_FMT_I420;
572 /* Create and initialize the aom_image */
573 if (!aom_img_wrap(&img, img_fmt, i_w, i_h, 32, p_pict->p[0].p_pixels))
575 AOM_ERR(p_enc, ctx, "Failed to wrap image");
576 return NULL;
579 /* Correct chroma plane offsets. */
580 for (int plane = 1; plane < p_pict->i_planes; plane++) {
581 img.planes[plane] = p_pict->p[plane].p_pixels;
582 img.stride[plane] = p_pict->p[plane].i_pitch;
585 aom_codec_err_t res = aom_codec_encode(ctx, &img, US_FROM_VLC_TICK(p_pict->date), 1, 0);
586 if (res != AOM_CODEC_OK) {
587 AOM_ERR(p_enc, ctx, "Failed to encode frame");
588 aom_img_free(&img);
589 return NULL;
592 const aom_codec_cx_pkt_t *pkt = NULL;
593 aom_codec_iter_t iter = NULL;
594 block_t *p_out = NULL;
595 while ((pkt = aom_codec_get_cx_data(ctx, &iter)) != NULL)
597 if (pkt->kind == AOM_CODEC_CX_FRAME_PKT)
599 int keyframe = pkt->data.frame.flags & AOM_FRAME_IS_KEY;
600 block_t *p_block = block_Alloc(pkt->data.frame.sz);
601 if (unlikely(p_block == NULL)) {
602 block_ChainRelease(p_out);
603 p_out = NULL;
604 break;
607 /* FIXME: do this in-place */
608 memcpy(p_block->p_buffer, pkt->data.frame.buf, pkt->data.frame.sz);
609 p_block->i_dts = p_block->i_pts = VLC_TICK_FROM_US(pkt->data.frame.pts);
610 if (keyframe)
611 p_block->i_flags |= BLOCK_FLAG_TYPE_I;
612 block_ChainAppend(&p_out, p_block);
615 aom_img_free(&img);
616 return p_out;
619 /*****************************************************************************
620 * CloseEncoder: encoder destruction
621 *****************************************************************************/
622 static void CloseEncoder(vlc_object_t *p_this)
624 encoder_t *p_enc = (encoder_t *)p_this;
625 encoder_sys_t *p_sys = p_enc->p_sys;
626 destroy_context(p_this, &p_sys->ctx);
627 free(p_sys);
630 #endif /* ENABLE_SOUT */