/*****************************************************************************
* theora.c: theora decoder module making use of libtheora.
*****************************************************************************
- * Copyright (C) 1999-2012 the VideoLAN team
+ * Copyright (C) 1999-2012 VLC authors and VideoLAN
* $Id$
*
* Authors: Gildas Bazin <gbazin@videolan.org>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
static void ParseTheoraComments( decoder_t * );
static void theora_CopyPicture( picture_t *, th_ycbcr_buffer );
+#ifdef ENABLE_SOUT
static int OpenEncoder( vlc_object_t *p_this );
static void CloseEncoder( vlc_object_t *p_this );
static block_t *Encode( encoder_t *p_enc, picture_t *p_pict );
+#endif
/*****************************************************************************
* Module descriptor
"Enforce a quality between 1 (low) and 10 (high), instead " \
"of specifying a particular bitrate. This will produce a VBR stream." )
+#define ENC_POSTPROCESS_TEXT N_("Post processing quality")
+
vlc_module_begin ()
set_category( CAT_INPUT )
set_subcategory( SUBCAT_INPUT_VCODEC )
set_capability( "decoder", 100 )
set_callbacks( OpenDecoder, CloseDecoder )
add_shortcut( "theora" )
+# define DEC_CFG_PREFIX "theora-"
+ add_integer( DEC_CFG_PREFIX "postproc", -1, ENC_POSTPROCESS_TEXT, NULL, true )
add_submodule ()
set_description( N_("Theora video packetizer") )
set_callbacks( OpenPacketizer, CloseDecoder )
add_shortcut( "theora" )
+#ifdef ENABLE_SOUT
add_submodule ()
set_description( N_("Theora video encoder") )
set_capability( "encoder", 150 )
# define ENC_CFG_PREFIX "sout-theora-"
add_integer( ENC_CFG_PREFIX "quality", 2, ENC_QUALITY_TEXT,
ENC_QUALITY_LONGTEXT, false )
+#endif
vlc_module_end ()
static const char *const ppsz_enc_options[] = {
{
if( ProcessHeaders( p_dec ) )
{
- block_Release( *pp_block );
+ block_Release( p_block );
return NULL;
}
p_sys->b_has_headers = true;
decoder_sys_t *p_sys = p_dec->p_sys;
ogg_packet oggpacket;
th_setup_info *ts = NULL; /* theora setup information */
+ int i_max_pp, i_pp;
unsigned pi_size[XIPH_MAX_HEADER_COUNT];
void *pp_data[XIPH_MAX_HEADER_COUNT];
p_dec->fmt_in.i_extra, p_dec->fmt_in.p_extra) )
return VLC_EGENERIC;
if( i_count < 3 )
- goto error;
+ return VLC_EGENERIC;
oggpacket.granulepos = -1;
oggpacket.e_o_s = 0;
msg_Err( p_dec, "Could not allocate Theora decoder" );
goto error;
}
+
+ i_pp = var_InheritInteger( p_dec, DEC_CFG_PREFIX "postproc" );
+ if ( i_pp >= 0 && !th_decode_ctl( p_sys->tcx,
+ TH_DECCTL_GET_PPLEVEL_MAX, &i_max_pp, sizeof(int) ) )
+ {
+ i_pp = __MIN( i_pp, i_max_pp );
+ if ( th_decode_ctl( p_sys->tcx, TH_DECCTL_SET_PPLEVEL,
+ &i_pp, sizeof(int) ) )
+ msg_Err( p_dec, "Failed to set post processing level to %d",
+ i_pp );
+ else
+ msg_Dbg( p_dec, "Set post processing level to %d / %d",
+ i_pp, i_max_pp );
+ }
+
}
else
{
p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra );
}
- for( unsigned i = 0; i < i_count; i++ )
- free( pp_data[i] );
/* Clean up the decoder setup info... we're done with it */
th_setup_free( ts );
return VLC_SUCCESS;
error:
- for( unsigned i = 0; i < i_count; i++ )
- free( pp_data[i] );
/* Clean up the decoder setup info... we're done with it */
th_setup_free( ts );
return VLC_EGENERIC;
/* Don't send the the first packet after a discontinuity to
* theora_decode, otherwise we get purple/green display artifacts
* appearing in the video output */
+ block_Release(p_block);
return NULL;
}
else
{
p_buf = DecodePacket( p_dec, p_oggpacket );
- if( p_block )
- block_Release( p_block );
+ block_Release( p_block );
}
/* Date management */
- p_sys->i_pts += ( INT64_C(1000000) * p_sys->ti.fps_denominator /
+ p_sys->i_pts += ( CLOCK_FREQ * p_sys->ti.fps_denominator /
p_sys->ti.fps_numerator ); /* 1 frame per packet */
return p_buf;
/* TODO: Implement _granpos (3rd parameter here) and add the
* call to TH_DECCTL_SET_GRANDPOS after seek */
- if (th_decode_packetin( p_sys->tcx, p_oggpacket, NULL )) /* 0 on success */
+ /* TODO: If the return is TH_DUPFRAME, we don't need to display a new
+ * frame, but we do need to keep displaying the previous one. */
+ if (th_decode_packetin( p_sys->tcx, p_oggpacket, NULL ) < 0)
return NULL; /* bad packet */
/* Check for keyframe */
i_line < __MIN(p_pic->p[i_plane].i_lines, ycbcr[i_plane].height);
i_line++ )
{
- vlc_memcpy( p_dst, p_src, ycbcr[i_plane].width );
+ memcpy( p_dst, p_src, ycbcr[i_plane].width );
p_src += i_src_stride;
p_dst += i_dst_stride;
}
}
}
+#ifdef ENABLE_SOUT
/*****************************************************************************
* encoder_sys_t : theora encoder descriptor
*****************************************************************************/
th_info_init( &p_sys->ti );
- p_sys->ti.frame_width = p_enc->fmt_in.video.i_width;
- p_sys->ti.frame_height = p_enc->fmt_in.video.i_height;
+ p_sys->ti.frame_width = p_enc->fmt_in.video.i_visible_width;
+ p_sys->ti.frame_height = p_enc->fmt_in.video.i_visible_height;
if( p_sys->ti.frame_width % 16 || p_sys->ti.frame_height % 16 )
{
p_sys->ti.frame_height = (p_sys->ti.frame_height + 15) >> 4 << 4;
msg_Dbg( p_enc, "padding video from %dx%d to %dx%d",
- p_enc->fmt_in.video.i_width, p_enc->fmt_in.video.i_height,
+ p_enc->fmt_in.video.i_visible_width, p_enc->fmt_in.video.i_visible_height,
p_sys->ti.frame_width, p_sys->ti.frame_height );
}
- p_sys->ti.pic_width = p_enc->fmt_in.video.i_width;
- p_sys->ti.pic_height = p_enc->fmt_in.video.i_height;
+ p_sys->ti.pic_width = p_enc->fmt_in.video.i_visible_width;
+ p_sys->ti.pic_height = p_enc->fmt_in.video.i_visible_height;
p_sys->ti.pic_x = 0 /*frame_x_offset*/;
p_sys->ti.pic_y = 0 /*frame_y_offset*/;
}
p_sys->ti.target_bitrate = p_enc->fmt_out.i_bitrate;
- p_sys->ti.quality = ((float)i_quality) * 6.3;
+ p_sys->ti.quality = ((float)i_quality) * 6.3f;
p_sys->tcx = th_encode_alloc( &p_sys->ti );
th_encode_packetout( p_sys->tcx, 0, &oggpacket );
/* Ogg packet to block */
- p_block = block_New( p_enc, oggpacket.bytes );
+ p_block = block_Alloc( oggpacket.bytes );
memcpy( p_block->p_buffer, oggpacket.packet, oggpacket.bytes );
p_block->i_dts = p_block->i_pts = p_pict->date;
p_sys->tcx = NULL;
free( p_sys );
}
+#endif