*/
uint8_t *p_buffer;
size_t i_buffer_out;
+ uint8_t *p_interleave_buf;
/*
* Video properties
#if (LIBAVCODEC_VERSION_MAJOR < 55)
"luma-elim-threshold", "chroma-elim-threshold",
#endif
- "aac-profile",
+ "aac-profile", "options",
NULL
};
p_sys->b_planar = false;
p_sys->p_buffer = NULL;
+ p_sys->p_interleave_buf = NULL;
p_sys->i_buffer_out = 0;
p_context = avcodec_alloc_context3(p_codec);
p_sys->p_context = p_context;
p_sys->p_context->codec_id = p_sys->p_codec->id;
+ p_context->thread_type = 0;
p_context->debug = var_InheritInteger( p_enc, "avcodec-debug" );
p_context->opaque = (void *)p_this;
p_context->thread_count = vlc_GetCPUCount();
int ret;
+ char *psz_opts = var_InheritString(p_enc, ENC_CFG_PREFIX "options");
+ AVDictionary *options = NULL;
+ if (psz_opts && *psz_opts)
+ options = vlc_av_get_options(psz_opts);
+ free(psz_opts);
+
vlc_avcodec_lock();
- ret = avcodec_open2( p_context, p_codec, NULL /* options */ );
+ ret = avcodec_open2( p_context, p_codec, options ? &options : NULL );
vlc_avcodec_unlock();
+
+ AVDictionaryEntry *t = NULL;
+ while ((t = av_dict_get(options, "", t, AV_DICT_IGNORE_SUFFIX))) {
+ msg_Err(p_enc, "Unknown option \"%s\"", t->key);
+ }
+
if( ret )
{
- if( p_enc->fmt_in.i_cat == AUDIO_ES &&
- (p_context->channels > 2 || i_codec_id == AV_CODEC_ID_MP2
- || i_codec_id == AV_CODEC_ID_MP3) )
+ if( p_enc->fmt_in.i_cat != AUDIO_ES ||
+ (p_context->channels <= 2 && i_codec_id != AV_CODEC_ID_MP2
+ && i_codec_id != AV_CODEC_ID_MP3) )
{
- if( p_context->channels > 2 )
- {
- p_context->channels = 2;
- p_enc->fmt_in.audio.i_channels = 2; // FIXME
- msg_Warn( p_enc, "stereo mode selected (codec limitation)" );
- }
+ msg_Err( p_enc, "cannot open encoder" );
+ dialog_Fatal( p_enc, _("Streaming / Transcoding failed"),
+ "%s", _("VLC could not open the encoder.") );
+ av_dict_free(&options);
+ goto error;
+ }
- if( i_codec_id == AV_CODEC_ID_MP2 || i_codec_id == AV_CODEC_ID_MP3 )
- {
- int i_frequency, i;
+ if( p_context->channels > 2 )
+ {
+ p_context->channels = 2;
+ p_enc->fmt_in.audio.i_channels = 2; // FIXME
+ msg_Warn( p_enc, "stereo mode selected (codec limitation)" );
+ }
- for ( i_frequency = 0; i_frequency < 6; i_frequency++ )
- {
- if ( p_enc->fmt_out.audio.i_rate
- == mpa_freq_tab[i_frequency] )
- break;
- }
- if ( i_frequency == 6 )
- {
- msg_Err( p_enc, "MPEG audio doesn't support frequency=%d",
- p_enc->fmt_out.audio.i_rate );
- free( p_sys );
- return VLC_EGENERIC;
- }
+ if( i_codec_id == AV_CODEC_ID_MP2 || i_codec_id == AV_CODEC_ID_MP3 )
+ {
+ int i_frequency, i;
+ es_format_t *fmt = &p_enc->fmt_out;
- for ( i = 1; i < 14; i++ )
- {
- if ( p_enc->fmt_out.i_bitrate / 1000
- <= mpa_bitrate_tab[i_frequency / 3][i] )
- break;
- }
- if ( p_enc->fmt_out.i_bitrate / 1000
- != mpa_bitrate_tab[i_frequency / 3][i] )
- {
- msg_Warn( p_enc,
- "MPEG audio doesn't support bitrate=%d, using %d",
- p_enc->fmt_out.i_bitrate,
- mpa_bitrate_tab[i_frequency / 3][i] * 1000 );
- p_enc->fmt_out.i_bitrate =
- mpa_bitrate_tab[i_frequency / 3][i] * 1000;
- p_context->bit_rate = p_enc->fmt_out.i_bitrate;
- }
+ for ( i_frequency = 0; i_frequency < 6; i_frequency++ )
+ if ( fmt->audio.i_rate == mpa_freq_tab[i_frequency] )
+ break;
+
+ if ( i_frequency == 6 )
+ {
+ msg_Err( p_enc, "MPEG audio doesn't support frequency=%d",
+ fmt->audio.i_rate );
+ av_dict_free(&options);
+ goto error;
}
- p_context->codec = NULL;
- vlc_avcodec_lock();
- ret = avcodec_open2( p_context, p_codec, NULL /* options */ );
- vlc_avcodec_unlock();
- if( ret )
+ for ( i = 1; i < 14; i++ )
+ if (fmt->i_bitrate/1000 <= mpa_bitrate_tab[i_frequency / 3][i])
+ break;
+
+ if (fmt->i_bitrate / 1000 != mpa_bitrate_tab[i_frequency / 3][i])
{
- msg_Err( p_enc, "cannot open encoder" );
- dialog_Fatal( p_enc,
- _("Streaming / Transcoding failed"),
- "%s", _("VLC could not open the encoder.") );
- free( p_sys );
- return VLC_EGENERIC;
+ msg_Warn( p_enc,
+ "MPEG audio doesn't support bitrate=%d, using %d",
+ fmt->i_bitrate,
+ mpa_bitrate_tab[i_frequency / 3][i] * 1000 );
+ fmt->i_bitrate = mpa_bitrate_tab[i_frequency / 3][i] * 1000;
+ p_context->bit_rate = fmt->i_bitrate;
}
}
- else
+
+ p_context->codec = NULL;
+ vlc_avcodec_lock();
+ ret = avcodec_open2( p_context, p_codec, options ? &options : NULL );
+ vlc_avcodec_unlock();
+ if( ret )
{
msg_Err( p_enc, "cannot open encoder" );
- dialog_Fatal( p_enc, _("Streaming / Transcoding failed"),
- "%s", _("VLC could not open the encoder.") );
- free( p_sys );
- return VLC_EGENERIC;
+ dialog_Fatal( p_enc,
+ _("Streaming / Transcoding failed"),
+ "%s", _("VLC could not open the encoder.") );
+ av_dict_free(&options);
+ goto error;
}
}
+ av_dict_free(&options);
+
if( i_codec_id == AV_CODEC_ID_FLAC )
{
p_enc->fmt_out.i_extra = 4 + 1 + 3 + p_context->extradata_size;
p_sys->b_variable = p_context->frame_size ? false : true;
p_sys->i_buffer_out = p_sys->i_frame_size * p_sys->i_sample_bytes * p_enc->fmt_in.audio.i_channels;
+
+ if( p_sys->b_planar )
+ {
+ p_sys->p_interleave_buf = malloc( p_sys->i_buffer_out );
+ if( unlikely( p_sys->p_interleave_buf == NULL ) )
+ goto error;
+ }
}
p_sys->frame = avcodec_alloc_frame();
error:
free( p_enc->fmt_out.p_extra );
free( p_sys->p_buffer );
+ free( p_sys->p_interleave_buf );
free( p_sys );
return VLC_ENOMEM;
}
{
encoder_sys_t *p_sys = p_enc->p_sys;
int i_out, i_plane, i_got_packet=1;
- AVPacket av_pkt;
/* Initialize the video output buffer the first time.
* This is done here instead of OpenEncoder() because we need the actual
block_t *p_block = block_Alloc( blocksize );
#if (LIBAVCODEC_VERSION_MAJOR >= 54)
+ AVPacket av_pkt;
/*We don't use av_pkt with major_version < 54, so no point init it*/
av_init_packet( &av_pkt );
av_pkt.data = p_block->p_buffer;
//How much we need to copy from new packet
const int leftover = leftover_samples * p_enc->fmt_in.audio.i_channels * p_sys->i_sample_bytes;
+#if LIBAVUTIL_VERSION_CHECK( 51,27,2,46,100 )
+ const int align = 0;
+#else
+ const int align = 1;
+#endif
+
AVPacket packet = {0};
avcodec_get_frame_defaults( p_sys->frame );
p_sys->frame->format = p_sys->p_context->sample_fmt;
if( likely( p_aout_buf ) )
{
p_aout_buf->i_nb_samples -= leftover_samples;
+ memcpy( p_sys->p_buffer+buffer_delay, p_aout_buf->p_buffer, leftover );
// We need to deinterleave from p_aout_buf to p_buffer the leftover bytes
if( p_sys->b_planar )
- aout_Deinterleave( p_sys->p_buffer+buffer_delay, p_aout_buf->p_buffer,
- leftover_samples, p_enc->fmt_in.audio.i_channels, p_enc->fmt_in.i_codec );
+ aout_Deinterleave( p_sys->p_interleave_buf, p_sys->p_buffer,
+ p_sys->i_frame_size, p_enc->fmt_in.audio.i_channels, p_enc->fmt_in.i_codec );
else
memcpy( p_sys->p_buffer + buffer_delay, p_aout_buf->p_buffer, leftover);
p_aout_buf->i_buffer -= leftover;
p_aout_buf->i_pts = date_Get( &p_sys->buffer_date );
}
+ if(unlikely( ( (leftover + buffer_delay) < p_sys->i_buffer_out ) &&
+ !(p_sys->p_codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME ))
+ )
+ {
+ msg_Dbg( p_enc, "No small last frame support, padding");
+ size_t padding_size = p_sys->i_buffer_out - (leftover+buffer_delay);
+ memset( p_sys->p_buffer + (leftover+buffer_delay), 0, padding_size );
+ buffer_delay += padding_size;
+ }
if( avcodec_fill_audio_frame( p_sys->frame, p_enc->fmt_in.audio.i_channels,
- p_sys->p_context->sample_fmt, p_sys->p_buffer,
+ p_sys->p_context->sample_fmt, p_sys->b_planar ? p_sys->p_interleave_buf : p_sys->p_buffer,
leftover + buffer_delay,
- 0) < 0 )
+ align) < 0 )
msg_Err( p_enc, "filling error on fillup" );
buffer_delay = 0;
( p_sys->b_variable && p_aout_buf->i_nb_samples ) )
{
AVPacket packet = {0};
+#if LIBAVUTIL_VERSION_CHECK( 51,27,2,46,100 )
+ const int align = 0;
+#else
+ const int align = 1;
+#endif
if( unlikely( p_aout_buf->i_pts > VLC_TS_INVALID &&
p_aout_buf->i_pts != date_Get( &p_sys->buffer_date ) ) )
p_sys->p_context->sample_fmt,
p_sys->b_planar ? p_sys->p_buffer : p_aout_buf->p_buffer,
__MIN(p_sys->i_buffer_out, p_aout_buf->i_buffer),
- 0) < 0 )
+ align) < 0 )
msg_Err( p_enc, "filling error on encode" );
p_aout_buf->p_buffer += (p_sys->frame->nb_samples * p_enc->fmt_in.audio.i_channels * p_sys->i_sample_bytes);
// that frame has more data than p_sys->i_frame_size most of the cases currently.
if( p_aout_buf->i_nb_samples > 0 )
{
- if( p_sys->b_planar )
- aout_Deinterleave( p_sys->p_buffer+buffer_delay, p_aout_buf->p_buffer,
- p_aout_buf->i_nb_samples, p_enc->fmt_in.audio.i_channels, p_enc->fmt_in.i_codec );
- else
- memcpy( p_sys->p_buffer + buffer_delay, p_aout_buf->p_buffer,
- p_aout_buf->i_nb_samples * p_sys->i_sample_bytes * p_enc->fmt_in.audio.i_channels);
- p_sys->i_samples_delay += p_aout_buf->i_nb_samples;
+ memcpy( p_sys->p_buffer + buffer_delay, p_aout_buf->p_buffer,
+ p_aout_buf->i_nb_samples * p_sys->i_sample_bytes * p_enc->fmt_in.audio.i_channels);
+ p_sys->i_samples_delay += p_aout_buf->i_nb_samples;
}
return p_chain;
av_free( p_sys->p_context );
+ free( p_sys->p_interleave_buf );
free( p_sys->p_buffer );
free( p_sys );