You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
233 lines
6.2 KiB
233 lines
6.2 KiB
#include <vlc_configuration.h>
|
|
#include <vlc_picture_fifo.h>
|
|
#include <vlc_filter.h>
|
|
#include <vlc_codec.h>
|
|
#include "encoder/encoder.h"
|
|
#include "pcr_helper.h"
|
|
|
|
/*100ms is around the limit where people are noticing lipsync issues*/
|
|
#define MASTER_SYNC_MAX_DRIFT VLC_TICK_FROM_MS(100)
|
|
|
|
typedef struct
|
|
{
|
|
char *psz_filters;
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
char *psz_deinterlace;
|
|
config_chain_t *p_deinterlace_cfg;
|
|
char *psz_spu_sources;
|
|
bool b_reorient;
|
|
} video;
|
|
};
|
|
} sout_filters_config_t;
|
|
|
|
static inline
|
|
void sout_filters_config_init( sout_filters_config_t *p_cfg )
|
|
{
|
|
memset( p_cfg, 0, sizeof(*p_cfg) );
|
|
}
|
|
|
|
static inline
|
|
void sout_filters_config_clean( sout_filters_config_t *p_cfg )
|
|
{
|
|
free( p_cfg->psz_filters );
|
|
if( p_cfg->video.psz_deinterlace )
|
|
{
|
|
free( p_cfg->video.psz_deinterlace );
|
|
config_ChainDestroy( p_cfg->video.p_deinterlace_cfg );
|
|
}
|
|
free( p_cfg->video.psz_spu_sources );
|
|
}
|
|
|
|
typedef struct sout_stream_id_sys_t sout_stream_id_sys_t;
|
|
|
|
typedef struct
|
|
{
|
|
bool b_soverlay;
|
|
|
|
/* Audio */
|
|
transcode_encoder_config_t aenc_cfg;
|
|
sout_filters_config_t afilters_cfg;
|
|
|
|
/* Video */
|
|
transcode_encoder_config_t venc_cfg;
|
|
sout_filters_config_t vfilters_cfg;
|
|
|
|
/* SPU */
|
|
transcode_encoder_config_t senc_cfg;
|
|
|
|
/* Shared between streams */
|
|
vlc_mutex_t lock;
|
|
/* Sync */
|
|
bool b_master_sync;
|
|
sout_stream_id_sys_t *id_master_sync;
|
|
/* Spu's video */
|
|
sout_stream_id_sys_t *id_video;
|
|
|
|
bool pcr_forwarding_enabled;
|
|
vlc_pcr_sync_t *pcr_sync;
|
|
bool first_pcr_sent;
|
|
bool pcr_sync_has_input;
|
|
unsigned int transcoded_stream_nb;
|
|
} sout_stream_sys_t;
|
|
|
|
struct aout_filters;
|
|
|
|
struct sout_stream_id_sys_t
|
|
{
|
|
bool b_transcode;
|
|
bool b_error;
|
|
|
|
/* id of the out stream */
|
|
void *downstream_id;
|
|
void *(*pf_transcode_downstream_add)( sout_stream_t *,
|
|
const es_format_t *orig,
|
|
const es_format_t *current );
|
|
|
|
vlc_fifo_t *output_fifo;
|
|
|
|
/* Decoder */
|
|
decoder_t *p_decoder;
|
|
|
|
struct
|
|
{
|
|
vlc_mutex_t lock;
|
|
union
|
|
{
|
|
vlc_picture_chain_t pic;
|
|
struct {
|
|
subpicture_t *first;
|
|
subpicture_t **last;
|
|
} spu;
|
|
struct {
|
|
block_t *first;
|
|
block_t **last;
|
|
} audio;
|
|
};
|
|
} fifo;
|
|
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
int (*pf_drift_validate)(void *cbdata, vlc_tick_t);
|
|
};
|
|
struct
|
|
{
|
|
void (*pf_send_subpicture)(void *cbdata, subpicture_t *);
|
|
int (*pf_get_output_dimensions)(void *cbdata, unsigned *, unsigned *);
|
|
vlc_tick_t (*pf_get_master_drift)(void *cbdata);
|
|
};
|
|
};
|
|
void *callback_data;
|
|
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
filter_chain_t *p_f_chain; /**< deinterlace & fps video filters */
|
|
filter_chain_t *p_uf_chain; /**< User-specified video filters */
|
|
filter_chain_t *p_final_conv_static; /**< converter to adapt filtered pics to the encoder */
|
|
vlc_blender_t *p_spu_blender;
|
|
spu_t *p_spu;
|
|
vlc_decoder_device *dec_dev;
|
|
vlc_video_context *enc_vctx_in;
|
|
};
|
|
struct
|
|
{
|
|
struct aout_filters *p_af_chain; /**< Audio filters */
|
|
audio_format_t fmt_input_audio;
|
|
};
|
|
};
|
|
|
|
/* only rw from pf_*_format_update() */
|
|
es_format_t decoder_out;
|
|
|
|
const sout_filters_config_t *p_filterscfg;
|
|
|
|
/* Encoder */
|
|
const transcode_encoder_config_t *p_enccfg;
|
|
transcode_encoder_t *encoder;
|
|
|
|
/* Sync */
|
|
date_t next_input_pts; /**< Incoming calculated PTS */
|
|
vlc_tick_t i_drift; /** how much buffer is ahead of calculated PTS */
|
|
|
|
transcode_track_pcr_helper_t *pcr_helper;
|
|
};
|
|
|
|
struct decoder_owner
|
|
{
|
|
decoder_t dec;
|
|
es_format_t fmt_in;
|
|
sout_stream_t *p_stream;
|
|
sout_stream_id_sys_t *id;
|
|
};
|
|
|
|
static inline struct decoder_owner *dec_get_owner( decoder_t *p_dec )
|
|
{
|
|
return container_of( p_dec, struct decoder_owner, dec );
|
|
}
|
|
|
|
static inline void dec_Delete( decoder_t *p_dec )
|
|
{
|
|
if( p_dec == NULL )
|
|
return;
|
|
|
|
struct decoder_owner *p_owner = dec_get_owner( p_dec );
|
|
es_format_Clean( &p_owner->fmt_in );
|
|
decoder_Destroy( p_dec );
|
|
}
|
|
|
|
static inline void es_format_SetMeta( es_format_t *p_dst, const es_format_t *p_src )
|
|
{
|
|
p_dst->i_group = p_src->i_group;
|
|
p_dst->i_id = p_src->i_id;
|
|
if( p_src->psz_language )
|
|
{
|
|
free( p_dst->psz_language );
|
|
p_dst->psz_language = strdup( p_src->psz_language );
|
|
}
|
|
if( p_src->psz_description )
|
|
{
|
|
free( p_dst->psz_description );
|
|
p_dst->psz_description = strdup( p_src->psz_description );
|
|
}
|
|
}
|
|
|
|
static inline void transcode_remove_filters( filter_chain_t **pp )
|
|
{
|
|
if( *pp )
|
|
{
|
|
filter_chain_Delete( *pp );
|
|
*pp = NULL;
|
|
}
|
|
}
|
|
|
|
/* SPU */
|
|
|
|
void transcode_spu_clean ( sout_stream_t *, sout_stream_id_sys_t * );
|
|
int transcode_spu_process( sout_stream_t *, sout_stream_id_sys_t *,
|
|
block_t *, block_t ** );
|
|
int transcode_spu_init ( sout_stream_t *, const es_format_t *, sout_stream_id_sys_t *);
|
|
|
|
/* AUDIO */
|
|
|
|
void transcode_audio_clean ( sout_stream_t *, sout_stream_id_sys_t * );
|
|
int transcode_audio_process( sout_stream_t *, sout_stream_id_sys_t *,
|
|
block_t *, block_t ** );
|
|
int transcode_audio_init ( sout_stream_t *, const es_format_t *,
|
|
sout_stream_id_sys_t *);
|
|
|
|
/* VIDEO */
|
|
|
|
void transcode_video_clean ( sout_stream_id_sys_t * );
|
|
int transcode_video_process( sout_stream_t *, sout_stream_id_sys_t *,
|
|
block_t *, block_t ** );
|
|
int transcode_video_get_output_dimensions( sout_stream_id_sys_t *,
|
|
unsigned *w, unsigned *h );
|
|
void transcode_video_push_spu( sout_stream_t *, sout_stream_id_sys_t *, subpicture_t * );
|
|
int transcode_video_init ( sout_stream_t *, const es_format_t *,
|
|
sout_stream_id_sys_t *);
|
|
|