From: Gildas Bazin Date: Wed, 8 Oct 2003 21:01:07 +0000 (+0000) Subject: * include/vlc_codec.h: defines decoders/encoders related structures here. X-Git-Tag: 0.7.0~819 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=d44f9d26aec48a4af5e4eccca6fb1fc9bbc75c13;p=vlc * include/vlc_codec.h: defines decoders/encoders related structures here. * include/vlc_video.h: new video_frame_format_t structure which defines the properties of a video frame. * include/vlc/decoder.h: include vlc_codec.h * src/misc/objects.c: added VLC_OBJECT_PACKETIZER and VLC_OBJECT_ENCODER object types. * modules/stream_out/transcode.c, modules/codec/theora.c: experimental theora video encoder. * src/input/*: some cleanup. --- diff --git a/Makefile.am b/Makefile.am index c7f4ef79cc..923c3eb4e1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -91,6 +91,7 @@ HEADERS_include = \ include/video_output.h \ include/vlc_block.h \ include/vlc_block_helper.h \ + include/vlc_codec.h \ include/vlc_common.h \ include/vlc_config.h \ include/vlc_cpu.h \ diff --git a/include/audio_output.h b/include/audio_output.h index eaab48c8c5..2971b76cb2 100644 --- a/include/audio_output.h +++ b/include/audio_output.h @@ -2,7 +2,7 @@ * audio_output.h : audio output interface ***************************************************************************** * Copyright (C) 2002 VideoLAN - * $Id: audio_output.h,v 1.82 2003/08/14 11:47:32 gbazin Exp $ + * $Id: audio_output.h,v 1.83 2003/10/08 21:01:07 gbazin Exp $ * * Authors: Christophe Massiot * @@ -20,6 +20,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************/ +#ifndef _VLC_AUDIO_OUTPUT_H +#define _VLC_AUDIO_OUTPUT_H 1 /***************************************************************************** * audio_sample_format_t @@ -208,3 +210,4 @@ VLC_EXPORT( int, aout_Restart, ( aout_instance_t * p_aout ) ); VLC_EXPORT( int, aout_FindAndRestart, ( vlc_object_t *, const char *, vlc_value_t, vlc_value_t, void * ) ); VLC_EXPORT( int, aout_ChannelsRestart, ( vlc_object_t *, const char *, vlc_value_t, vlc_value_t, void * ) ); +#endif /* _VLC_AUDIO_OUTPUT_H */ diff --git a/include/input_ext-dec.h b/include/input_ext-dec.h index 12c8ceadb4..d81242cdb8 100644 --- a/include/input_ext-dec.h +++ b/include/input_ext-dec.h @@ -2,7 +2,7 @@ * input_ext-dec.h: structures exported to the VideoLAN decoders ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: input_ext-dec.h,v 1.80 2003/09/02 20:19:25 gbazin Exp $ + * $Id: input_ext-dec.h,v 1.81 2003/10/08 21:01:07 gbazin Exp $ * * Authors: Christophe Massiot * Michel Kaempf @@ -113,29 +113,6 @@ struct decoder_fifo_t decoder_t * p_dec; }; -/***************************************************************************** - * decoder_t - ***************************************************************************** - * The decoder descriptor. - *****************************************************************************/ -struct decoder_t -{ - VLC_COMMON_MEMBERS - - /* Module properties */ - module_t * p_module; - decoder_sys_t * p_sys; - int ( * pf_init ) ( decoder_t * ); - int ( * pf_decode )( decoder_t *, block_t * ); - int ( * pf_end ) ( decoder_t * ); - - /* Input properties */ - decoder_fifo_t * p_fifo; /* stores the PES stream data */ - - /* Tmp field for old decoder api */ - int ( * pf_run ) ( decoder_fifo_t * ); -}; - /***************************************************************************** * bit_fifo_t : bit fifo descriptor ***************************************************************************** diff --git a/include/vlc/decoder.h b/include/vlc/decoder.h index e6b98a684d..ced34d751b 100644 --- a/include/vlc/decoder.h +++ b/include/vlc/decoder.h @@ -2,7 +2,7 @@ * decoder.h: header for vlc decoders ***************************************************************************** * Copyright (C) 2002 VideoLAN - * $Id: decoder.h,v 1.2 2003/09/02 20:19:25 gbazin Exp $ + * $Id: decoder.h,v 1.3 2003/10/08 21:01:07 gbazin Exp $ * * 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 @@ -37,6 +37,9 @@ extern "C" { #include "vlc_block.h" #include "stream_control.h" #include "input_ext-dec.h" +#include "vlc_video.h" +#include "audio_output.h" +#include "vlc_codec.h" # ifdef __cplusplus } diff --git a/include/vlc_codec.h b/include/vlc_codec.h new file mode 100644 index 0000000000..5ab767cef3 --- /dev/null +++ b/include/vlc_codec.h @@ -0,0 +1,96 @@ +/***************************************************************************** + * vlc_codec.h: codec related structures + ***************************************************************************** + * Copyright (C) 1999-2003 VideoLAN + * $Id: vlc_codec.h,v 1.1 2003/10/08 21:01:07 gbazin Exp $ + * + * Authors: Gildas Bazin + * + * 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 + * (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. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + *****************************************************************************/ +#ifndef _VLC_CODEC_H +#define _VLC_CODEC_H 1 + +/** + * \file + * This file defines the structure and types used by decoders and encoders + */ + +/** + * \defgroup decoder Decoder + * + * The structure describing a decoder + * + * @{ + */ + +struct decoder_t +{ + VLC_COMMON_MEMBERS + + /* Module properties */ + module_t * p_module; + decoder_sys_t * p_sys; + int ( * pf_init ) ( decoder_t * ); + int ( * pf_decode )( decoder_t *, block_t * ); + int ( * pf_end ) ( decoder_t * ); + + /* Input properties */ + decoder_fifo_t * p_fifo; /* stores the PES stream data */ + + /* Tmp field for old decoder api */ + int ( * pf_run ) ( decoder_fifo_t * ); +}; + +/** + * @} + */ + +/** + * \defgroup decoder Encoder + * + * The structure describing a Encoder + * + * @{ + */ + +struct encoder_t +{ + VLC_COMMON_MEMBERS + + /* Module properties */ + module_t * p_module; + encoder_sys_t * p_sys; + + block_t * ( * pf_header )( encoder_t * ); + block_t * ( * pf_encode_video )( encoder_t *, picture_t * ); + block_t * ( * pf_encode_audio )( encoder_t *, aout_buffer_t * ); + + /* Properties of the input data fed to the encoder */ + union { + audio_sample_format_t audio; + video_frame_format_t video; + } format; + + /* Properties of the output of the encoder */ + vlc_fourcc_t i_fourcc; + int i_bitrate; +}; + +/** + * @} + */ + +#endif /* _VLC_CODEC_H */ diff --git a/include/vlc_keys.h b/include/vlc_keys.h index 5be5c83a98..6e8c6e5142 100644 --- a/include/vlc_keys.h +++ b/include/vlc_keys.h @@ -2,7 +2,7 @@ * hotkeys.h: keycode defines ***************************************************************************** * Copyright (C) 2003 VideoLAN - * $Id: vlc_keys.h,v 1.1 2003/08/14 19:25:55 sigmunau Exp $ + * $Id: vlc_keys.h,v 1.2 2003/10/08 21:01:07 gbazin Exp $ * * Authors: Sigmund Augdal * @@ -58,12 +58,15 @@ #define KEY_ASCII 0x0000007F #define KEY_UNSET 0 + typedef struct key_descriptor_s { char *psz_key_string; int i_key_code; } key_descriptor_t; + #define ADD_KEY(a) { a, *a } + static const struct key_descriptor_s modifiers[] = { { "Alt", KEY_MODIFIER_ALT }, diff --git a/include/vlc_objects.h b/include/vlc_objects.h index 7ebbb0ff28..116bda76a2 100644 --- a/include/vlc_objects.h +++ b/include/vlc_objects.h @@ -2,7 +2,7 @@ * vlc_objects.h: vlc_object_t definition. ***************************************************************************** * Copyright (C) 2002 VideoLAN - * $Id: vlc_objects.h,v 1.18 2003/09/18 17:54:02 zorglub Exp $ + * $Id: vlc_objects.h,v 1.19 2003/10/08 21:01:07 gbazin Exp $ * * Authors: Samuel Hocevar * @@ -46,6 +46,8 @@ #define VLC_OBJECT_AOUT (-10) #define VLC_OBJECT_SOUT (-11) #define VLC_OBJECT_HTTPD (-12) +#define VLC_OBJECT_PACKETIZER (-13) +#define VLC_OBJECT_ENCODER (-14) #define VLC_OBJECT_GENERIC (-666) diff --git a/include/vlc_video.h b/include/vlc_video.h index db1d818299..51b90fa685 100644 --- a/include/vlc_video.h +++ b/include/vlc_video.h @@ -4,7 +4,7 @@ * includes all common video types and constants. ***************************************************************************** * Copyright (C) 1999, 2000 VideoLAN - * $Id: vlc_video.h,v 1.3 2003/10/04 15:51:22 sigmunau Exp $ + * $Id: vlc_video.h,v 1.4 2003/10/08 21:01:07 gbazin Exp $ * * Authors: Vincent Seguin * @@ -22,6 +22,20 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************/ +#ifndef _VLC_VIDEO_H +#define _VLC_VIDEO_H 1 + +/** + * Description of a video frame + */ +typedef struct video_frame_format_t +{ + unsigned int i_width; /**< picture width */ + unsigned int i_height; /**< picture height */ + vlc_fourcc_t i_chroma; /**< picture chroma */ + unsigned int i_aspect; /**< aspect ratio */ + +} video_frame_format_t; /** * Description of a planar graphic field @@ -247,3 +261,5 @@ struct subpicture_t #define READY_SUBPICTURE 2 /* ready for display */ /**@}*/ + +#endif /* _VLC_VIDEO_H */ diff --git a/modules/codec/theora.c b/modules/codec/theora.c index 6849588379..baeb2cb1fa 100644 --- a/modules/codec/theora.c +++ b/modules/codec/theora.c @@ -2,7 +2,7 @@ * theora.c: theora decoder module making use of libtheora. ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: theora.c,v 1.8 2003/09/28 21:54:20 gbazin Exp $ + * $Id: theora.c,v 1.9 2003/10/08 21:01:07 gbazin Exp $ * * Authors: Gildas Bazin * @@ -90,9 +90,13 @@ static int DecodePacket ( decoder_t *, ogg_packet * ); static int SendPacket ( decoder_t *, ogg_packet * ); static void ParseTheoraComments( decoder_t * ); - static void theora_CopyPicture( decoder_t *, picture_t *, yuv_buffer * ); +static int OpenEncoder( vlc_object_t *p_this ); +static void CloseEncoder( vlc_object_t *p_this ); +static block_t *Headers( encoder_t *p_enc ); +static block_t *Encode( encoder_t *p_enc, picture_t *p_pict ); + /***************************************************************************** * Module descriptor *****************************************************************************/ @@ -107,6 +111,12 @@ vlc_module_begin(); set_capability( "packetizer", 100 ); set_callbacks( OpenPacketizer, NULL ); add_shortcut( "theora" ); + + add_submodule(); + set_description( _("Theora video encoder") ); + set_capability( "video encoder", 100 ); + set_callbacks( OpenEncoder, CloseEncoder ); + add_shortcut( "theora" ); vlc_module_end(); /***************************************************************************** @@ -515,3 +525,193 @@ static void theora_CopyPicture( decoder_t *p_dec, picture_t *p_pic, } } } + +/***************************************************************************** + * encoder_sys_t : theora encoder descriptor + *****************************************************************************/ +struct encoder_sys_t +{ + /* + * Input properties + */ + int i_headers; + + /* + * Theora properties + */ + theora_info ti; /* theora bitstream settings */ + theora_comment tc; /* theora comment header */ + theora_state td; /* theora bitstream user comments */ + + /* + * Packetizer output properties + */ + sout_packetizer_input_t *p_sout_input; + sout_format_t sout_format; + + /* + * Common properties + */ + mtime_t i_pts; +}; + +/***************************************************************************** + * OpenEncoder: probe the encoder and return score + *****************************************************************************/ +static int OpenEncoder( vlc_object_t *p_this ) +{ + encoder_t *p_enc = (encoder_t *)p_this; + encoder_sys_t *p_sys = p_enc->p_sys; + + if( p_enc->i_fourcc != VLC_FOURCC('t','h','e','o') ) + { + return VLC_EGENERIC; + } + + /* Allocate the memory needed to store the decoder's structure */ + if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL ) + { + msg_Err( p_enc, "out of memory" ); + return VLC_EGENERIC; + } + p_enc->p_sys = p_sys; + + p_enc->pf_header = Headers; + p_enc->pf_encode_video = Encode; + p_enc->format.video.i_chroma = VLC_FOURCC('I','4','2','0'); + +#define frame_x_offset 0 +#define frame_y_offset 0 +#define video_hzn 25 +#define video_hzd 1 +#define video_an 4 +#define video_ad 3 +#define video_q 5 + + theora_info_init( &p_sys->ti ); + + p_sys->ti.width = p_enc->format.video.i_width; + p_sys->ti.height = p_enc->format.video.i_height; + p_sys->ti.frame_width = p_enc->format.video.i_width; + p_sys->ti.frame_height = p_enc->format.video.i_height; + p_sys->ti.offset_x = frame_x_offset; + p_sys->ti.offset_y = frame_y_offset; + p_sys->ti.fps_numerator = video_hzn; + p_sys->ti.fps_denominator = video_hzd; + p_sys->ti.aspect_numerator = video_an; + p_sys->ti.aspect_denominator = video_ad; + p_sys->ti.colorspace = not_specified; + p_sys->ti.target_bitrate = p_enc->i_bitrate; + p_sys->ti.quality = video_q; + + p_sys->ti.dropframes_p = 0; + p_sys->ti.quick_p = 1; + p_sys->ti.keyframe_auto_p = 1; + p_sys->ti.keyframe_frequency = 64; + p_sys->ti.keyframe_frequency_force = 64; + p_sys->ti.keyframe_data_target_bitrate = p_enc->i_bitrate * 1.5; + p_sys->ti.keyframe_auto_threshold = 80; + p_sys->ti.keyframe_mindistance = 8; + p_sys->ti.noise_sensitivity = 1; + + theora_encode_init( &p_sys->td, &p_sys->ti ); + theora_info_clear( &p_sys->ti ); + + p_sys->i_headers = 0; + + return VLC_SUCCESS; +} + +/**************************************************************************** + * Encode: the whole thing + **************************************************************************** + * This function spits out ogg packets. + ****************************************************************************/ +static block_t *Headers( encoder_t *p_enc ) +{ + encoder_sys_t *p_sys = p_enc->p_sys; + ogg_packet oggpacket; + block_t *p_block; + + /* Create theora headers */ + switch( p_sys->i_headers ) + { + case 0: + theora_encode_header( &p_sys->td, &oggpacket ); + break; + case 1: + theora_comment_init( &p_sys->tc ); + theora_encode_comment( &p_sys->tc, &oggpacket ); + break; + case 2: + theora_encode_tables( &p_sys->td, &oggpacket ); + break; + default: + } + + p_sys->i_headers++; + if( p_sys->i_headers > 3 ) return NULL; + + /* Ogg packet to block */ + p_block = block_New( p_enc, oggpacket.bytes ); + p_block->p_buffer = oggpacket.packet; + p_block->i_buffer = oggpacket.bytes; + p_block->i_dts = oggpacket.granulepos; + + return p_block; +} + +/**************************************************************************** + * Encode: the whole thing + **************************************************************************** + * This function spits out ogg packets. + ****************************************************************************/ +static block_t *Encode( encoder_t *p_enc, picture_t *p_pict ) +{ + encoder_sys_t *p_sys = p_enc->p_sys; + ogg_packet oggpacket; + block_t *p_block; + yuv_buffer yuv; + int i_ret; + + /* Theora is a one-frame-in, one-frame-out system. Submit a frame + * for compression and pull out the packet. */ + + yuv.y_width = p_pict->p[0].i_visible_pitch; + yuv.y_height = p_pict->p[0].i_lines; + yuv.y_stride = p_pict->p[0].i_pitch; + + yuv.uv_width = p_pict->p[1].i_visible_pitch; + yuv.uv_height = p_pict->p[1].i_lines; + yuv.uv_stride = p_pict->p[1].i_pitch; + + yuv.y = p_pict->p[0].p_pixels; + yuv.u = p_pict->p[1].p_pixels; + yuv.v = p_pict->p[2].p_pixels; + + theora_encode_YUVin( &p_sys->td, &yuv ); + + theora_encode_packetout( &p_sys->td, 0, &oggpacket ); + + /* Ogg packet to block */ + p_block = block_New( p_enc, oggpacket.bytes ); + p_block->p_buffer = oggpacket.packet; + p_block->i_buffer = oggpacket.bytes; + p_block->i_dts = oggpacket.granulepos; + + return p_block; +} + +/***************************************************************************** + * CloseEncoder: theora encoder destruction + *****************************************************************************/ +static void CloseEncoder( vlc_object_t *p_this ) +{ + encoder_t *p_enc = (encoder_t *)p_this; + encoder_sys_t *p_sys = p_enc->p_sys; + + theora_info_clear( &p_sys->ti ); + theora_comment_clear( &p_sys->tc ); + + free( p_sys ); +} diff --git a/modules/stream_out/transcode.c b/modules/stream_out/transcode.c index 718d5de069..0afa0e1e3d 100644 --- a/modules/stream_out/transcode.c +++ b/modules/stream_out/transcode.c @@ -2,7 +2,7 @@ * transcode.c ***************************************************************************** * Copyright (C) 2001, 2002 VideoLAN - * $Id: transcode.c,v 1.34 2003/10/04 10:54:45 gbazin Exp $ + * $Id: transcode.c,v 1.35 2003/10/08 21:01:07 gbazin Exp $ * * Authors: Laurent Aimar * @@ -30,6 +30,8 @@ #include #include #include +#include +#include /* ffmpeg header */ #ifdef HAVE_FFMPEG_AVCODEC_H @@ -320,6 +322,9 @@ struct sout_stream_id_t /* id of the out stream */ void *id; + /* Encoder */ + encoder_t *p_encoder; + /* ffmpeg part */ AVCodec *ff_dec; AVCodecContext *ff_dec_c; @@ -373,6 +378,8 @@ static sout_stream_id_t * Add( sout_stream_t *p_stream, sout_format_t *p_fmt ) id = malloc( sizeof( sout_stream_id_t ) ); id->i_dts = 0; id->id = NULL; + id->p_encoder = NULL; + if( p_fmt->i_cat == AUDIO_ES && p_sys->i_acodec != 0 ) { msg_Dbg( p_stream, @@ -1215,20 +1222,78 @@ static int transcode_video_ffmpeg_new( sout_stream_t *p_stream, /* find encoder */ + id->ff_enc = NULL; i_ff_codec = get_ff_codec( id->f_dst.i_fourcc ); - if( i_ff_codec == 0 ) + if( i_ff_codec != 0 ) { - msg_Err( p_stream, "cannot find encoder" ); - return VLC_EGENERIC; + id->ff_enc = avcodec_find_encoder( i_ff_codec ); } - id->ff_enc = avcodec_find_encoder( i_ff_codec ); + /* Hack for external encoders */ if( !id->ff_enc ) + { + id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER ); + id->p_encoder->i_fourcc = id->f_dst.i_fourcc; + id->p_encoder->format.video.i_width = p_sys->i_width; + id->p_encoder->format.video.i_height = p_sys->i_height; + id->p_encoder->i_bitrate = p_sys->i_vbitrate; + + if( id->p_encoder->format.video.i_width <= 0 ) + { + id->p_encoder->format.video.i_width = id->f_dst.i_width = + id->ff_dec_c->width - p_sys->i_crop_left - + p_sys->i_crop_right; + } + if( id->p_encoder->format.video.i_height <= 0 ) + { + id->p_encoder->format.video.i_height = id->f_dst.i_height = + id->ff_dec_c->height - p_sys->i_crop_top - + p_sys->i_crop_bottom; + } + + id->p_encoder->p_module = + module_Need( id->p_encoder, "video encoder", NULL ); + + if( !id->p_encoder->p_module ) + { + free( id->p_encoder ); + id->p_encoder = NULL; + } + } + /* End hack for external encoders */ + + if( !id->ff_enc && !id->p_encoder ) { msg_Err( p_stream, "cannot find encoder" ); return VLC_EGENERIC; } + /* XXX open it only when we have the first frame */ + id->b_enc_inited = VLC_FALSE; + id->i_buffer_in = 0; + id->i_buffer_in_pos = 0; + id->p_buffer_in = NULL; + + id->i_buffer = 3*1024*1024; + id->i_buffer_pos = 0; + id->p_buffer = malloc( id->i_buffer ); + + id->i_buffer_out = 0; + id->i_buffer_out_pos = 0; + id->p_buffer_out = NULL; + + id->p_ff_pic = avcodec_alloc_frame(); + id->p_ff_pic_tmp0 = NULL; + id->p_ff_pic_tmp1 = NULL; + id->p_ff_pic_tmp2 = NULL; + id->p_vresample = NULL; + + p_sys->i_last_ref_pts = 0; + p_sys->i_buggy_pts_detect = 0; + + /* This is enough for external encoders */ + if( id->p_encoder->p_module ) return VLC_SUCCESS; + if( id->f_dst.i_fourcc == VLC_FOURCC( 'm','p','1','v' )|| id->f_dst.i_fourcc == VLC_FOURCC( 'm','p','2','v' ) ) { @@ -1282,28 +1347,6 @@ static int transcode_video_ffmpeg_new( sout_stream_t *p_stream, { id->ff_enc_c->pix_fmt = get_ff_chroma( id->f_dst.i_fourcc ); } - /* XXX open it only when we have the first frame */ - id->b_enc_inited = VLC_FALSE; - id->i_buffer_in = 0; - id->i_buffer_in_pos = 0; - id->p_buffer_in = NULL; - - id->i_buffer = 3*1024*1024; - id->i_buffer_pos = 0; - id->p_buffer = malloc( id->i_buffer ); - - id->i_buffer_out = 0; - id->i_buffer_out_pos = 0; - id->p_buffer_out = NULL; - - id->p_ff_pic = avcodec_alloc_frame(); - id->p_ff_pic_tmp0 = NULL; - id->p_ff_pic_tmp1 = NULL; - id->p_ff_pic_tmp2 = NULL; - id->p_vresample = NULL; - - p_sys->i_last_ref_pts = 0; - p_sys->i_buggy_pts_detect = 0; return VLC_SUCCESS; } @@ -1314,7 +1357,13 @@ static void transcode_video_ffmpeg_close ( sout_stream_t *p_stream, sout_stream_ { avcodec_close( id->ff_dec_c ); } - if( id->b_enc_inited ) + if( id->p_encoder ) + { + /* External encoding */ + module_Unneed( p_stream, id->p_encoder->p_module ); + vlc_object_destroy( id->p_encoder->p_module ); + } + else if( id->b_enc_inited ) { avcodec_close( id->ff_enc_c ); } @@ -1346,7 +1395,6 @@ static void transcode_video_ffmpeg_close ( sout_stream_t *p_stream, sout_stream_ free( id->ff_dec_c ); free( id->ff_enc_c ); - free( id->p_buffer ); } @@ -1412,10 +1460,50 @@ static int transcode_video_ffmpeg_process( sout_stream_t *p_stream, p_sys->i_output_pts = frame->pts; } - if( !id->b_enc_inited ) + if( !id->b_enc_inited && id->p_encoder ) { - /* XXX hack because of copy packetizer and mpeg4video that can failed - detecting size */ + block_t *p_block; + + /* XXX hack because of copy packetizer and mpeg4video that can fail + * detecting size */ +#if 0 + if( id->p_encoder->i_width <= 0 ) + { + id->p_encoder->i_width = id->f_dst.i_width = + id->ff_dec_c->width - p_sys->i_crop_left - + p_sys->i_crop_right; + } + if( id->p_encoder->i_height <= 0 ) + { + id->p_encoder->i_height = id->f_dst.i_height = + id->ff_dec_c->height - p_sys->i_crop_top - + p_sys->i_crop_bottom; + } +#endif + + id->p_encoder->i_bitrate = p_sys->i_vbitrate; + + if( !( id->id = p_stream->p_sys->p_out->pf_add( p_stream->p_sys->p_out, &id->f_dst ) ) ) + { + msg_Err( p_stream, "cannot add this stream" ); + id->b_transcode = VLC_FALSE; + return VLC_EGENERIC; + } + + while( (p_block = id->p_encoder->pf_header( id->p_encoder )) ) + { + sout_buffer_t *p_out; + p_out = sout_BufferNew( p_stream->p_sout, p_block->i_buffer ); + memcpy( p_out->p_buffer, p_block->p_buffer, p_block->i_buffer); + sout_BufferChain( out, p_out ); + } + + id->b_enc_inited = VLC_TRUE; + } + else if( !id->b_enc_inited ) + { + /* XXX hack because of copy packetizer and mpeg4video that can fail + * detecting size */ if( id->ff_enc_c->width <= 0 ) { id->ff_enc_c->width = @@ -1479,6 +1567,7 @@ static int transcode_video_ffmpeg_process( sout_stream_t *p_stream, } /* convert pix format */ + if( !id->p_encoder ) if( id->ff_dec_c->pix_fmt != id->ff_enc_c->pix_fmt ) { if( id->p_ff_pic_tmp1 == NULL ) @@ -1504,6 +1593,7 @@ static int transcode_video_ffmpeg_process( sout_stream_t *p_stream, } /* convert size and crop */ + if( !id->p_encoder ) if( id->ff_dec_c->width != id->ff_enc_c->width || id->ff_dec_c->height != id->ff_enc_c->height || p_sys->i_crop_top > 0 || p_sys->i_crop_bottom > 0 || @@ -1552,6 +1642,37 @@ static int transcode_video_ffmpeg_process( sout_stream_t *p_stream, id->ff_dec_c->frame_rate_base / (2 * id->ff_dec_c->frame_rate); } + if( id->p_encoder ) + { + /* External encoding */ + block_t *p_block; + picture_t pic; + int i_plane; + + vout_InitPicture( VLC_OBJECT(p_stream), &pic, + id->ff_dec_c->width, id->ff_dec_c->height, + VLC_FOURCC('I','4','2','0') ); + + for( i_plane = 0; i_plane < pic.i_planes; i_plane++ ) + { + pic.p[i_plane].p_pixels = frame->data[i_plane]; + pic.p[i_plane].i_pitch = frame->linesize[i_plane]; + } + + pic.date = frame->pts; + + p_block = id->p_encoder->pf_encode_video( id->p_encoder, &pic ); + if( p_block ) + { + sout_buffer_t *p_out; + p_out = sout_BufferNew( p_stream->p_sout, p_block->i_buffer ); + memcpy( p_out->p_buffer, p_block->p_buffer, p_block->i_buffer); + sout_BufferChain( out, p_out ); + } + + return VLC_SUCCESS; + } + /* Let ffmpeg select the frame type */ frame->pict_type = 0; diff --git a/src/input/demux.c b/src/input/demux.c index c0bdccb0b6..c272ff5bb1 100644 --- a/src/input/demux.c +++ b/src/input/demux.c @@ -2,7 +2,7 @@ * demux.c ***************************************************************************** * Copyright (C) 1999-2003 VideoLAN - * $Id: demux.c,v 1.3 2003/09/13 17:42:16 fenrir Exp $ + * $Id: demux.c,v 1.4 2003/10/08 21:01:07 gbazin Exp $ * * Authors: Laurent Aimar * @@ -27,7 +27,7 @@ #include "ninput.h" -int demux_vaControl( input_thread_t *p_input, int i_query, va_list args ) +int demux_vaControl( input_thread_t *p_input, int i_query, va_list args ) { if( p_input->pf_demux_control ) { @@ -36,7 +36,7 @@ int demux_vaControl( input_thread_t *p_input, int i_query, va_list args ) return VLC_EGENERIC; } -int demux_Control ( input_thread_t *p_input, int i_query, ... ) +int demux_Control( input_thread_t *p_input, int i_query, ... ) { va_list args; int i_result; @@ -50,7 +50,8 @@ int demux_Control ( input_thread_t *p_input, int i_query, ... ) static void SeekOffset( input_thread_t *p_input, int64_t i_pos ); -int demux_vaControlDefault( input_thread_t *p_input, int i_query, va_list args ) +int demux_vaControlDefault( input_thread_t *p_input, int i_query, + va_list args ) { int i_ret; double f, *pf; @@ -75,9 +76,11 @@ int demux_vaControlDefault( input_thread_t *p_input, int i_query, va_list args case DEMUX_SET_POSITION: f = (double)va_arg( args, double ); - if( p_input->stream.b_seekable && p_input->pf_seek != NULL && f >= 0.0 && f <= 1.0 ) + if( p_input->stream.b_seekable && p_input->pf_seek != NULL && + f >= 0.0 && f <= 1.0 ) { - SeekOffset( p_input, (int64_t)(f * (double)p_input->stream.p_selected_area->i_size) ); + SeekOffset( p_input, (int64_t)(f * + (double)p_input->stream.p_selected_area->i_size) ); i_ret = VLC_SUCCESS; } else @@ -105,7 +108,8 @@ int demux_vaControlDefault( input_thread_t *p_input, int i_query, va_list args case DEMUX_SET_TIME: i64 = (int64_t)va_arg( args, int64_t ); if( p_input->stream.i_mux_rate > 0 && - p_input->stream.b_seekable && p_input->pf_seek != NULL && i64 >= 0 ) + p_input->stream.b_seekable && + p_input->pf_seek != NULL && i64 >= 0 ) { SeekOffset( p_input, i64 * 50 * (int64_t)p_input->stream.i_mux_rate / @@ -147,7 +151,6 @@ int demux_vaControlDefault( input_thread_t *p_input, int i_query, va_list args return i_ret; } - static void SeekOffset( input_thread_t *p_input, int64_t i_pos ) { /* Reinitialize buffer manager. */ diff --git a/src/input/input.c b/src/input/input.c index 4cca86d883..77f47b9243 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -4,7 +4,7 @@ * decoders. ***************************************************************************** * Copyright (C) 1998-2002 VideoLAN - * $Id: input.c,v 1.245 2003/09/30 16:09:58 hartman Exp $ + * $Id: input.c,v 1.246 2003/10/08 21:01:07 gbazin Exp $ * * Authors: Christophe Massiot * @@ -1204,14 +1204,14 @@ static int EsOutControl( es_out_t *out, int i_query, va_list args ) * Callbacks (position, time, state, rate ) *****************************************************************************/ static int PositionCallback( vlc_object_t *p_this, char const *psz_cmd, - vlc_value_t oldval, vlc_value_t newval, void *p_data ) + vlc_value_t oldval, vlc_value_t newval, + void *p_data ) { input_thread_t *p_input = (input_thread_t *)p_this; int64_t i_offset; - msg_Warn( p_input, "cmd=%s old=%f new=%f", - psz_cmd, - oldval.f_float, newval.f_float ); + msg_Dbg( p_input, "cmd=%s old=%f new=%f", psz_cmd, + oldval.f_float, newval.f_float ); vlc_mutex_lock( &p_input->stream.stream_lock ); i_offset = (int64_t)( newval.f_float * @@ -1233,16 +1233,15 @@ static int PositionCallback( vlc_object_t *p_this, char const *psz_cmd, return VLC_SUCCESS; } -static int TimeCallback ( vlc_object_t *p_this, char const *psz_cmd, - vlc_value_t oldval, vlc_value_t newval, void *p_data ) +static int TimeCallback( vlc_object_t *p_this, char const *psz_cmd, + vlc_value_t oldval, vlc_value_t newval, void *p_data ) { input_thread_t *p_input = (input_thread_t *)p_this; int64_t i_offset; /* FIXME TODO FIXME */ - msg_Warn( p_input, "cmd=%s old=%lld new=%lld", - psz_cmd, - oldval.i_time, newval.i_time ); + msg_Dbg( p_input, "cmd=%s old=%lld new=%lld", psz_cmd, + oldval.i_time, newval.i_time ); vlc_mutex_lock( &p_input->stream.stream_lock ); @@ -1264,12 +1263,14 @@ static int TimeCallback ( vlc_object_t *p_this, char const *psz_cmd, return VLC_SUCCESS; } -static int StateCallback ( vlc_object_t *p_this, char const *psz_cmd, - vlc_value_t oldval, vlc_value_t newval, void *p_data ) +static int StateCallback( vlc_object_t *p_this, char const *psz_cmd, + vlc_value_t oldval, vlc_value_t newval, + void *p_data ) { input_thread_t *p_input = (input_thread_t *)p_this; - msg_Warn( p_input, "cmd=%s old=%d new=%d", - psz_cmd, oldval.i_int, newval.i_int ); + + msg_Dbg( p_input, "cmd=%s old=%d new=%d", + psz_cmd, oldval.i_int, newval.i_int ); switch( newval.i_int ) { @@ -1288,8 +1289,8 @@ static int StateCallback ( vlc_object_t *p_this, char const *psz_cmd, } } -static int RateCallback ( vlc_object_t *p_this, char const *psz_cmd, - vlc_value_t oldval, vlc_value_t newval, void *p_data ) +static int RateCallback( vlc_object_t *p_this, char const *psz_cmd, + vlc_value_t oldval, vlc_value_t newval, void *p_data ) { input_thread_t *p_input = (input_thread_t *)p_this; @@ -1303,8 +1304,8 @@ static int RateCallback ( vlc_object_t *p_this, char const *psz_cmd, } else { - msg_Warn( p_input, "cmd=%s old=%d new=%d", - psz_cmd, oldval.i_int, newval.i_int ); + msg_Dbg( p_input, "cmd=%s old=%d new=%d", + psz_cmd, oldval.i_int, newval.i_int ); input_SetRate( p_input, newval.i_int ); } return VLC_SUCCESS; diff --git a/src/input/input_dec.c b/src/input/input_dec.c index 6385d35b04..aa419077cf 100644 --- a/src/input/input_dec.c +++ b/src/input/input_dec.c @@ -2,7 +2,7 @@ * input_dec.c: Functions for the management of decoders ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: input_dec.c,v 1.63 2003/10/06 15:22:53 gbazin Exp $ + * $Id: input_dec.c,v 1.64 2003/10/08 21:01:07 gbazin Exp $ * * Authors: Christophe Massiot * @@ -28,10 +28,8 @@ #include /* memcpy(), memset() */ #include +#include -#include "vlc_block.h" -#include "stream_control.h" -#include "input_ext-dec.h" #include "input_ext-intf.h" #include "input_ext-plugins.h" diff --git a/src/input/stream.c b/src/input/stream.c index 3fe25fe7b3..37fd291642 100644 --- a/src/input/stream.c +++ b/src/input/stream.c @@ -2,7 +2,7 @@ * stream.c ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: stream.c,v 1.5 2003/09/08 00:36:26 fenrir Exp $ + * $Id: stream.c,v 1.6 2003/10/08 21:01:07 gbazin Exp $ * * Authors: Laurent Aimar * @@ -48,7 +48,7 @@ struct stream_t /** * Create a "stream_t *" from an "input_thread_t *". */ -stream_t *stream_OpenInput( input_thread_t *p_input ) +stream_t *stream_OpenInput( input_thread_t *p_input ) { stream_t *s; @@ -64,15 +64,16 @@ stream_t *stream_OpenInput( input_thread_t *p_input ) /** * Destroy a previously created "stream_t *" instance. */ -void stream_Release( stream_t *s ) +void stream_Release( stream_t *s ) { vlc_object_destroy( s ); } /** - * Similar to #stream_Control(), but takes a va_list and not variable arguments. + * Similar to #stream_Control(), but takes a va_list and not variable + * arguments. */ -int stream_vaControl( stream_t *s, int i_query, va_list args ) +int stream_vaControl( stream_t *s, int i_query, va_list args ) { vlc_bool_t *p_b; int64_t *p_i64, i64; @@ -99,7 +100,8 @@ int stream_vaControl( stream_t *s, int i_query, va_list args ) p_b = (vlc_bool_t*) va_arg( args, vlc_bool_t * ); vlc_mutex_lock( &s->p_input->stream.stream_lock ); - *p_b = s->p_input->stream.b_seekable && s->p_input->stream.i_method == INPUT_METHOD_FILE; + *p_b = s->p_input->stream.b_seekable && + s->p_input->stream.i_method == INPUT_METHOD_FILE; vlc_mutex_unlock( &s->p_input->stream.stream_lock ); return VLC_SUCCESS; @@ -142,8 +144,8 @@ int stream_vaControl( stream_t *s, int i_query, va_list args ) if( i64 - s->p_input->stream.p_selected_area->i_tell > 0 ) { - data_packet_t *p_data; - int i_skip = i64 - s->p_input->stream.p_selected_area->i_tell; + data_packet_t *p_data; + int i_skip = i64 - s->p_input->stream.p_selected_area->i_tell; if( i_skip > 1000 ) { @@ -155,7 +157,7 @@ int stream_vaControl( stream_t *s, int i_query, va_list args ) int i_read; i_read = input_SplitBuffer( s->p_input, &p_data, - __MIN( (int)s->p_input->i_bufsize, i_skip ) ); + __MIN( (int)s->p_input->i_bufsize, i_skip ) ); if( i_read < 0 ) { return VLC_EGENERIC; @@ -183,7 +185,7 @@ int stream_vaControl( stream_t *s, int i_query, va_list args ) * possible "i_query" value and format arguments. Return VLC_SUCCESS * if ... succeed ;) and VLC_EGENERIC if failed or unimplemented */ -int stream_Control( stream_t *s, int i_query, ... ) +int stream_Control( stream_t *s, int i_query, ... ) { va_list args; int i_result; @@ -201,7 +203,7 @@ int stream_Control( stream_t *s, int i_query, ... ) * value is the real numbers of bytes read/skip. If this value is less * than i_read that means that it's the end of the stream. */ -int stream_Read( stream_t *s, void *p_data, int i_data ) +int stream_Read( stream_t *s, void *p_data, int i_data ) { uint8_t *p = (uint8_t*)p_data; data_packet_t *p_packet; @@ -227,7 +229,7 @@ int stream_Read( stream_t *s, void *p_data, int i_data ) int i_count; i_count = input_SplitBuffer( s->p_input, &p_packet, - __MIN( i_data, (int)s->p_input->i_bufsize ) ); + __MIN( i_data, (int)s->p_input->i_bufsize ) ); if( i_count <= 0 ) { return i_read; @@ -258,7 +260,7 @@ int stream_Read( stream_t *s, void *p_data, int i_data ) * the end of the stream (but only when you have i_peek >= * p_input->i_bufsize) */ -int stream_Peek( stream_t *s, uint8_t **pp_peek, int i_data ) +int stream_Peek( stream_t *s, uint8_t **pp_peek, int i_data ) { return input_Peek( s->p_input, pp_peek, i_data ); } @@ -269,7 +271,7 @@ int stream_Peek( stream_t *s, uint8_t **pp_peek, int i_data ) * you need to fill i_dts, i_pts, ... ) If only less than "i_size" * bytes are available NULL is returned. */ -pes_packet_t *stream_PesPacket( stream_t *s, int i_data ) +pes_packet_t *stream_PesPacket( stream_t *s, int i_data ) { pes_packet_t *p_pes; data_packet_t *p_packet; @@ -283,8 +285,7 @@ pes_packet_t *stream_PesPacket( stream_t *s, int i_data ) if( i_data <= 0 ) { p_pes->p_first = - p_pes->p_last = - input_NewPacket( s->p_input->p_method_data, 0 ); + p_pes->p_last = input_NewPacket( s->p_input->p_method_data, 0 ); p_pes->i_nb_data = 1; return p_pes; } @@ -294,7 +295,7 @@ pes_packet_t *stream_PesPacket( stream_t *s, int i_data ) int i_read; i_read = input_SplitBuffer( s->p_input, &p_packet, - __MIN( i_data, (int)s->p_input->i_bufsize ) ); + __MIN( i_data, (int)s->p_input->i_bufsize ) ); if( i_read <= 0 ) { /* should occur only with EOF and max allocation reached @@ -315,7 +316,7 @@ pes_packet_t *stream_PesPacket( stream_t *s, int i_data ) p_pes->p_last = p_packet; p_pes->i_nb_data++; p_pes->i_pes_size += i_read; - i_data -= i_read; + i_data -= i_read; } return p_pes; @@ -363,7 +364,8 @@ data_packet_t *stream_DataPacket( stream_t *s, int i_size, vlc_bool_t b_force ) memcpy( p_pk->p_payload_start, p_old->p_payload_start, i_read ); input_DeletePacket( s->p_input->p_method_data, p_old ); - if( stream_Read( s, &p_pk->p_payload_start[i_read], i_missing ) < i_missing ) + if( stream_Read( s, &p_pk->p_payload_start[i_read], i_missing ) + < i_missing ) { input_DeletePacket( s->p_input->p_method_data, p_pk ); return NULL; @@ -372,6 +374,3 @@ data_packet_t *stream_DataPacket( stream_t *s, int i_size, vlc_bool_t b_force ) return p_pk; } - - - diff --git a/src/misc/block.c b/src/misc/block.c index cd686c49a6..39776591d2 100644 --- a/src/misc/block.c +++ b/src/misc/block.c @@ -2,7 +2,7 @@ * block.c: Data blocks management functions ***************************************************************************** * Copyright (C) 2003 VideoLAN - * $Id: block.c,v 1.2 2003/09/02 20:19:26 gbazin Exp $ + * $Id: block.c,v 1.3 2003/10/08 21:01:07 gbazin Exp $ * * Authors: Laurent Aimar * @@ -181,7 +181,7 @@ static block_t *BlockRealloc( block_t *p_block, int i_prebody, int i_body ) * Standard block management * *****************************************************************************/ -/* to be used by other block managment */ +/* to be used by other block management */ block_t *block_NewEmpty( void ) { block_t *p_block; @@ -322,9 +322,8 @@ block_t *block_ChainGather( block_t *p_list ) return g; } - /***************************************************************************** - * block_fifo_t managment + * block_fifo_t management *****************************************************************************/ block_fifo_t *__block_FifoNew( vlc_object_t *p_obj ) { diff --git a/src/misc/messages.c b/src/misc/messages.c index 8d01dea5c9..515e51d78e 100644 --- a/src/misc/messages.c +++ b/src/misc/messages.c @@ -4,7 +4,7 @@ * modules, especially intf modules. See config.h for output configuration. ***************************************************************************** * Copyright (C) 1998-2002 VideoLAN - * $Id: messages.c,v 1.34 2003/06/24 13:33:49 sam Exp $ + * $Id: messages.c,v 1.35 2003/10/08 21:01:07 gbazin Exp $ * * Authors: Vincent Seguin * Samuel Hocevar @@ -467,6 +467,8 @@ static void PrintMsg ( vlc_object_t * p_this, msg_item_t * p_item ) case VLC_OBJECT_ITEM: psz_object = "item"; break; case VLC_OBJECT_INPUT: psz_object = "input"; break; case VLC_OBJECT_DECODER: psz_object = "decoder"; break; + case VLC_OBJECT_PACKETIZER: psz_object = "packetizer"; break; + case VLC_OBJECT_ENCODER: psz_object = "encoder"; break; case VLC_OBJECT_VOUT: psz_object = "video output"; break; case VLC_OBJECT_AOUT: psz_object = "audio output"; break; case VLC_OBJECT_SOUT: psz_object = "stream output"; break; diff --git a/src/misc/objects.c b/src/misc/objects.c index d4617bc435..6ba26c6cad 100644 --- a/src/misc/objects.c +++ b/src/misc/objects.c @@ -2,7 +2,7 @@ * objects.c: vlc_object_t handling ***************************************************************************** * Copyright (C) 2002 VideoLAN - * $Id: objects.c,v 1.40 2003/09/19 15:33:58 fenrir Exp $ + * $Id: objects.c,v 1.41 2003/10/08 21:01:07 gbazin Exp $ * * Authors: Samuel Hocevar * @@ -49,6 +49,7 @@ #include "vlc_playlist.h" #include "vlc_interface.h" +#include "vlc_codec.h" #include "httpd.h" /***************************************************************************** @@ -130,6 +131,14 @@ void * __vlc_object_create( vlc_object_t *p_this, int i_type ) i_size = sizeof(decoder_fifo_t); psz_type = "decoder"; break; + case VLC_OBJECT_PACKETIZER: + i_size = sizeof(decoder_t); + psz_type = "packetizer"; + break; + case VLC_OBJECT_ENCODER: + i_size = sizeof(encoder_t); + psz_type = "encoder"; + break; case VLC_OBJECT_VOUT: i_size = sizeof(vout_thread_t); psz_type = "video output";