summaryrefslogtreecommitdiff
path: root/ffmpeg.c
diff options
context:
space:
mode:
authorPeter Ross <pross@xvid.org>2008-08-03 00:37:07 +0000
committerPeter Ross <pross@xvid.org>2008-08-03 00:37:07 +0000
commita79db0f7c47701d46ec864b6b2dfeea03160a106 (patch)
tree47c73c6a0669e747b7aa8ef49ddb49b93d3391e3 /ffmpeg.c
parent2879c75ff32bc31dabc565d623776e21c39584c4 (diff)
Add sample format converter to FFmpeg (adds -sample_fmt option)
Originally committed as revision 14512 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'ffmpeg.c')
-rw-r--r--ffmpeg.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/ffmpeg.c b/ffmpeg.c
index ee9a4883b2..91485ae5b6 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -257,6 +257,8 @@ typedef struct AVOutputStream {
/* audio only */
int audio_resample;
ReSampleContext *resample; /* for audio resampling */
+ int reformat_pair;
+ AVAudioConvert *reformat_ctx;
AVFifoBuffer fifo; /* for compression: one audio fifo per codec */
FILE *logfile;
} AVOutputStream;
@@ -513,6 +515,7 @@ static void do_audio_out(AVFormatContext *s,
uint8_t *buftmp;
static uint8_t *audio_buf = NULL;
static uint8_t *audio_out = NULL;
+ static uint8_t *audio_out2 = NULL;
const int audio_out_size= 4*MAX_AUDIO_PACKET_SIZE;
int size_out, frame_bytes, ret;
@@ -541,6 +544,26 @@ static void do_audio_out(AVFormatContext *s,
}
}
+#define MAKE_SFMT_PAIR(a,b) ((a)+SAMPLE_FMT_NB*(b))
+ if (dec->sample_fmt!=enc->sample_fmt &&
+ MAKE_SFMT_PAIR(enc->sample_fmt,dec->sample_fmt)!=ost->reformat_pair) {
+ if (!audio_out2)
+ audio_out2 = av_malloc(audio_out_size);
+ if (!audio_out2)
+ av_exit(1);
+ if (ost->reformat_ctx)
+ av_audio_convert_free(ost->reformat_ctx);
+ ost->reformat_ctx = av_audio_convert_alloc(enc->sample_fmt, 1,
+ dec->sample_fmt, 1, NULL, 0);
+ if (!ost->reformat_ctx) {
+ fprintf(stderr, "Cannot convert %s sample format to %s sample format\n",
+ avcodec_get_sample_fmt_name(dec->sample_fmt),
+ avcodec_get_sample_fmt_name(enc->sample_fmt));
+ av_exit(1);
+ }
+ ost->reformat_pair=MAKE_SFMT_PAIR(enc->sample_fmt,dec->sample_fmt);
+ }
+
if(audio_sync_method){
double delta = get_sync_ipts(ost) * enc->sample_rate - ost->sync_opts
- av_fifo_size(&ost->fifo)/(ost->st->codec->channels * 2);
@@ -599,6 +622,22 @@ static void do_audio_out(AVFormatContext *s,
size_out = size;
}
+ if (dec->sample_fmt!=enc->sample_fmt) {
+ const void *ibuf[6]= {buftmp};
+ void *obuf[6]= {audio_out2};
+ int istride[6]= {av_get_bits_per_sample_format(dec->sample_fmt)/8};
+ int ostride[6]= {av_get_bits_per_sample_format(enc->sample_fmt)/8};
+ int len= size_out/istride[0];
+ if (av_audio_convert(ost->reformat_ctx, obuf, ostride, ibuf, istride, len)<0) {
+ printf("av_audio_convert() failed\n");
+ return;
+ }
+ buftmp = audio_out2;
+ /* FIXME: existing code assume that size_out equals framesize*channels*2
+ remove this legacy cruft */
+ size_out = len*2;
+ }
+
/* now encode as many frames as possible */
if (enc->frame_size > 1) {
/* output resampled raw samples */
@@ -1726,6 +1765,7 @@ static int av_encode(AVFormatContext **output_files,
case CODEC_TYPE_AUDIO:
if (av_fifo_init(&ost->fifo, 1024))
goto fail;
+ ost->reformat_pair = MAKE_SFMT_PAIR(SAMPLE_FMT_NONE,SAMPLE_FMT_NONE);
ost->audio_resample = codec->sample_rate != icodec->sample_rate || audio_sync_method > 1;
icodec->request_channels = codec->channels;
ist->decoding_needed = 1;
@@ -2162,6 +2202,8 @@ static int av_encode(AVFormatContext **output_files,
sws_freeContext(ost->img_resample_ctx);
if (ost->resample)
audio_resample_close(ost->resample);
+ if (ost->reformat_ctx)
+ av_audio_convert_free(ost->reformat_ctx);
av_free(ost);
}
}
@@ -2763,6 +2805,7 @@ static void opt_input_file(const char *filename)
ap->width = frame_width + frame_padleft + frame_padright;
ap->height = frame_height + frame_padtop + frame_padbottom;
ap->pix_fmt = frame_pix_fmt;
+ // ap->sample_fmt = audio_sample_fmt; //FIXME:not implemented in libavformat
ap->channel = video_channel;
ap->standard = video_standard;
ap->video_codec_id = find_codec_or_die(video_codec_name, CODEC_TYPE_VIDEO, 0);
@@ -2827,6 +2870,7 @@ static void opt_input_file(const char *filename)
//fprintf(stderr, "\nInput Audio channels: %d", enc->channels);
audio_channels = enc->channels;
audio_sample_rate = enc->sample_rate;
+ audio_sample_fmt = enc->sample_fmt;
if(audio_disable)
ic->streams[i]->discard= AVDISCARD_ALL;
break;
@@ -3109,6 +3153,7 @@ static void new_audio_stream(AVFormatContext *oc)
st->stream_copy = 1;
audio_enc->channels = audio_channels;
} else {
+ AVCodec *codec;
codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, CODEC_TYPE_AUDIO);
set_context_opts(audio_enc, avctx_opts[CODEC_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM);
@@ -3116,6 +3161,7 @@ static void new_audio_stream(AVFormatContext *oc)
if (audio_codec_name)
codec_id = find_codec_or_die(audio_codec_name, CODEC_TYPE_AUDIO, 1);
audio_enc->codec_id = codec_id;
+ codec = avcodec_find_encoder(codec_id);
if (audio_qscale > QSCALE_NONE) {
audio_enc->flags |= CODEC_FLAG_QSCALE;
@@ -3123,6 +3169,17 @@ static void new_audio_stream(AVFormatContext *oc)
}
audio_enc->thread_count = thread_count;
audio_enc->channels = audio_channels;
+ audio_enc->sample_fmt = audio_sample_fmt;
+
+ if(codec && codec->sample_fmts){
+ const enum SampleFormat *p= codec->sample_fmts;
+ for(; *p!=-1; p++){
+ if(*p == audio_enc->sample_fmt)
+ break;
+ }
+ if(*p == -1)
+ audio_enc->sample_fmt = codec->sample_fmts[0];
+ }
}
audio_enc->sample_rate = audio_sample_rate;
audio_enc->time_base= (AVRational){1, audio_sample_rate};
@@ -3793,6 +3850,7 @@ static const OptionDef options[] = {
{ "vol", OPT_INT | HAS_ARG | OPT_AUDIO, {(void*)&audio_volume}, "change audio volume (256=normal)" , "volume" }, //
{ "newaudio", OPT_AUDIO, {(void*)opt_new_audio_stream}, "add a new audio stream to the current output stream" },
{ "alang", HAS_ARG | OPT_STRING | OPT_AUDIO, {(void *)&audio_language}, "set the ISO 639 language code (3 letters) of the current audio stream" , "code" },
+ { "sample_fmt", HAS_ARG | OPT_EXPERT | OPT_AUDIO, {(void*)opt_audio_sample_fmt}, "set sample format, 'list' as argument shows all the sample formats supported", "format" },
/* subtitle options */
{ "sn", OPT_BOOL | OPT_SUBTITLE, {(void*)&subtitle_disable}, "disable subtitle" },