}
}
-static int use_float_audio_buffer(int codec_id)
+static int request_float_audio_buffer(int codec_id)
{
+ /* If any of these codecs, we prefer the float sample format (if supported) */
return codec_id == CODEC_ID_AAC || codec_id == CODEC_ID_AC3 || codec_id == CODEC_ID_VORBIS;
}
c->bit_rate = ffmpeg_audio_bitrate * 1000;
c->sample_fmt = AV_SAMPLE_FMT_S16;
c->channels = rd->ffcodecdata.audio_channels;
- if (use_float_audio_buffer(codec_id)) {
+
+ if (request_float_audio_buffer(codec_id)) {
+ /* mainly for AAC codec which is experimental */
c->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
c->sample_fmt = AV_SAMPLE_FMT_FLT;
}
+
codec = avcodec_find_encoder(c->codec_id);
if (!codec) {
//XXX error("Couldn't find a valid audio codec");
return NULL;
}
+ if (codec->sample_fmts) {
+ /* check if the prefered sample format for this codec is supported.
+ * this is because, depending on the version of libav, and with the whole ffmpeg/libav fork situation,
+ * you have various implementations around. float samples in particular are not always supported.
+ */
+ const enum AVSampleFormat *p = codec->sample_fmts;
+ for (; *p!=-1; p++) {
+ if (*p == st->codec->sample_fmt)
+ break;
+ }
+ if (*p == -1) {
+ /* sample format incompatible with codec. Defaulting to a format known to work */
+ st->codec->sample_fmt = codec->sample_fmts[0];
+ }
+ }
+
+ if (c->sample_fmt == AV_SAMPLE_FMT_FLTP) {
+ BLI_strncpy(error, "Requested audio codec requires planar float sample format, which is not supported yet", error_size);
+ return NULL;
+ }
+
+ if (codec->supported_samplerates) {
+ const int *p = codec->supported_samplerates;
+ int best = 0;
+ int best_dist = INT_MAX;
+ for (; *p; p++){
+ int dist = abs(st->codec->sample_rate - *p);
+ if (dist < best_dist){
+ best_dist = dist;
+ best = *p;
+ }
+ }
+ /* best is the closest supported sample rate (same as selected if best_dist == 0) */
+ st->codec->sample_rate = best;
+ }
+
set_ffmpeg_properties(rd, c, "audio");
if (avcodec_open2(c, codec, NULL) < 0) {
audio_output_buffer = (uint8_t *) av_malloc(audio_outbuf_size);
- if (use_float_audio_buffer(codec_id)) {
+ if (c->sample_fmt == AV_SAMPLE_FMT_FLT) {
audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(float));
}
else {
AVCodecContext *c = audio_stream->codec;
AUD_DeviceSpecs specs;
specs.channels = c->channels;
- if (use_float_audio_buffer(c->codec_id)) {
+ if (c->sample_fmt == AV_SAMPLE_FMT_FLT) {
specs.format = AUD_FORMAT_FLOAT32;
}
else {