AVFormatContext *ic = (AVFormatContext*)pv->title->opaque_priv;
pv->context = avcodec_alloc_context3(codec);
avcodec_copy_context( pv->context, ic->streams[w->audio->id]->codec);
- hb_ff_set_sample_fmt( pv->context, codec );
+ hb_ff_set_sample_fmt( pv->context, codec, AV_SAMPLE_FMT_FLT );
}
else
{
pv->parser = av_parser_init( w->codec_param );
pv->context = avcodec_alloc_context3(codec);
- hb_ff_set_sample_fmt( pv->context, codec );
+ hb_ff_set_sample_fmt( pv->context, codec, AV_SAMPLE_FMT_FLT );
}
if ( hb_avcodec_open( pv->context, codec, NULL, 0 ) )
{
AVCodecParserContext *parser = av_parser_init( codec->id );
AVCodecContext *context = avcodec_alloc_context3(codec);
- hb_ff_set_sample_fmt( context, codec );
+ hb_ff_set_sample_fmt( context, codec, AV_SAMPLE_FMT_FLT );
if ( hb_avcodec_open( context, codec, NULL, 0 ) )
{
return -1;
context->compression_level = audio->config.out.compression_level;
}
- // Try to set format to float; fall back to whatever is supported.
- hb_ff_set_sample_fmt(context, codec);
+ // set the sample_fmt to something practical
+ if (audio->config.out.codec == HB_ACODEC_FFFLAC)
+ {
+ hb_ff_set_sample_fmt(context, codec, AV_SAMPLE_FMT_S16);
+ }
+ else
+ {
+ hb_ff_set_sample_fmt(context, codec, AV_SAMPLE_FMT_FLT);
+ }
if (hb_avcodec_open(context, codec, &av_opts, 0))
{
return hb_layout;
}
-// Set sample format to AV_SAMPLE_FMT_FLT if supported.
-// If it is not supported, we will have to translate using
-// av_audio_convert.
-void hb_ff_set_sample_fmt(AVCodecContext *context, AVCodec *codec)
+/*
+ * Set sample format to the request format if supported by the codec.
+ * The planar/packed variant of the requested format is the next best thing.
+ */
+void hb_ff_set_sample_fmt(AVCodecContext *context, AVCodec *codec,
+ enum AVSampleFormat request_sample_fmt)
{
- if ( codec && codec->sample_fmts )
+ if (context != NULL && codec != NULL &&
+ codec->type == AVMEDIA_TYPE_AUDIO && codec->sample_fmts != NULL)
{
- if ( codec->type != AVMEDIA_TYPE_AUDIO )
- return; // Not audio
-
const enum AVSampleFormat *fmt;
+ enum AVSampleFormat next_best_fmt;
+
+ next_best_fmt = (av_sample_fmt_is_planar(request_sample_fmt) ?
+ av_get_packed_sample_fmt(request_sample_fmt) :
+ av_get_planar_sample_fmt(request_sample_fmt));
- for ( fmt = codec->sample_fmts; *fmt != -1; fmt++ )
+ context->request_sample_fmt = AV_SAMPLE_FMT_NONE;
+
+ for (fmt = codec->sample_fmts; *fmt != AV_SAMPLE_FMT_NONE; fmt++)
{
- if ( *fmt == AV_SAMPLE_FMT_FLT )
+ if (*fmt == request_sample_fmt)
{
- context->request_sample_fmt = AV_SAMPLE_FMT_FLT;
- context->sample_fmt = AV_SAMPLE_FMT_FLT;
+ context->request_sample_fmt = request_sample_fmt;
break;
}
+ else if (*fmt == next_best_fmt)
+ {
+ context->request_sample_fmt = next_best_fmt;
+ }
}
- if ( *fmt == -1 )
- context->sample_fmt = codec->sample_fmts[0];
+ /*
+ * When encoding and AVCodec.sample_fmts exists, avcodec_open2()
+ * will error out if AVCodecContext.sample_fmt isn't set.
+ */
+ if (context->request_sample_fmt == AV_SAMPLE_FMT_NONE)
+ {
+ context->request_sample_fmt = codec->sample_fmts[0];
+ }
+ context->sample_fmt = context->request_sample_fmt;
}
}
uint64_t hb_ff_layout_xlat(uint64_t ff_channel_layout, int nchannels);
uint64_t hb_ff_mixdown_xlat(int hb_mixdown, int *downmix_mode);
-void hb_ff_set_sample_fmt(AVCodecContext *context, AVCodec *codec);
+void hb_ff_set_sample_fmt(AVCodecContext *, AVCodec *, enum AVSampleFormat);
struct SwsContext*
hb_sws_get_context(int srcW, int srcH, enum PixelFormat srcFormat,
} break;
}
- c = avcodec_alloc_context3( codec );
-
+ c = avcodec_alloc_context3(codec);
c->bit_rate = w->audio->config.in.bitrate;
c->sample_rate = w->audio->config.in.samplerate;
- c->channels = av_get_channel_layout_nb_channels(w->audio->config.in.channel_layout);
- hb_ff_set_sample_fmt( c, codec );
+ c->channels =
+ av_get_channel_layout_nb_channels(w->audio->config.in.channel_layout);
+ hb_ff_set_sample_fmt(c, codec, AV_SAMPLE_FMT_FLT);
if (w->audio->config.in.channel_layout == AV_CH_LAYOUT_STEREO_DOWNMIX)
{