On 03/28/2011 05:27 PM, Alex Converse wrote: > On Mon, Mar 28, 2011 at 2:19 PM, Justin Ruggles > <[email protected]> wrote: >> On 03/28/2011 04:54 PM, Alex Converse wrote: >> >>> --- >>> doc/ffmpeg.texi | 2 ++ >>> ffmpeg.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- >>> 2 files changed, 47 insertions(+), 2 deletions(-) >>> >>> >>> >>> 0001-Add-an-apad-option-to-ffmpeg-to-pad-audio-to-video-l.patch >>> >>> >>> diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi >>> index 21c6f2c..2927017 100644 >>> --- a/doc/ffmpeg.texi >>> +++ b/doc/ffmpeg.texi >>> @@ -579,6 +579,8 @@ ffmpeg -i file.mpg -vcodec copy -acodec ac3 -ab 384k >>> test.mpg -acodec mp2 -ab 19 >>> @end example >>> @item -alang @var{code} >>> Set the ISO 639 language code (3 letters) of the current audio stream. >>> +@item -apad >>> +Pad audio to video length. >>> @end table >>> >>> @section Advanced Audio options: >>> diff --git a/ffmpeg.c b/ffmpeg.c >>> index 5e50db3..84a278e 100644 >>> --- a/ffmpeg.c >>> +++ b/ffmpeg.c >>> @@ -176,6 +176,7 @@ static int64_t channel_layout = 0; >>> #define QSCALE_NONE -99999 >>> static float audio_qscale = QSCALE_NONE; >>> static int audio_disable = 0; >>> +static int audio_pad = 0; >>> static int audio_channels = 1; >>> static char *audio_codec_name = NULL; >>> static unsigned int audio_codec_tag = 0; >>> @@ -297,6 +298,7 @@ typedef struct AVOutputStream { >>> int reformat_pair; >>> AVAudioConvert *reformat_ctx; >>> AVFifoBuffer *fifo; /* for compression: one audio fifo per codec */ >>> + >>> FILE *logfile; >>> } AVOutputStream; >>> >>> @@ -702,7 +704,8 @@ static void write_frame(AVFormatContext *s, AVPacket >>> *pkt, AVCodecContext *avctx >>> static void do_audio_out(AVFormatContext *s, >>> AVOutputStream *ost, >>> AVInputStream *ist, >>> - unsigned char *buf, int size) >>> + unsigned char *buf, int size, >>> + int skip_resample_reformat) >>> { >>> uint8_t *buftmp; >>> int64_t audio_out_size, audio_buf_size; >>> @@ -739,6 +742,7 @@ need_realloc: >>> ffmpeg_exit(1); >>> } >>> >>> + if (!skip_resample_reformat) { >>> if (enc->channels != dec->channels) >>> ost->audio_resample = 1; >>> >>> @@ -871,6 +875,10 @@ need_realloc: >>> buftmp = audio_buf; >>> size_out = len*osize; >>> } >>> + } else { >>> + buftmp = buf; >>> + size_out = size; >>> + } >>> >>> /* now encode as many frames as possible */ >>> if (enc->frame_size > 1) { >>> @@ -1603,7 +1611,7 @@ static int output_packet(AVInputStream *ist, int >>> ist_index, >>> av_assert0(ist->decoding_needed); >>> switch(ost->st->codec->codec_type) { >>> case AVMEDIA_TYPE_AUDIO: >>> - do_audio_out(os, ost, ist, decoded_data_buf, >>> decoded_data_size); >>> + do_audio_out(os, ost, ist, decoded_data_buf, >>> decoded_data_size, 0); >>> break; >>> case AVMEDIA_TYPE_VIDEO: >>> #if CONFIG_AVFILTER >>> @@ -1697,8 +1705,18 @@ static int output_packet(AVInputStream *ist, int >>> ist_index, >>> discard_packet: >>> if (pkt == NULL) { >>> /* EOF handling */ >>> + double vpts = 0.0; >>> + >>> + for(i=0;i<nb_ostreams;i++) { >>> + ost = ost_table[i]; >>> + if(ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { >>> + double opts = ost->st->pts.val * >>> av_q2d(ost->st->time_base); >>> + vpts = FFMAX(opts, vpts); >>> + } >>> + } >>> >>> for(i=0;i<nb_ostreams;i++) { >>> + int ost_pad_audio = audio_pad; >>> ost = ost_table[i]; >>> if (ost->source_index == ist_index) { >>> AVCodecContext *enc= ost->st->codec; >>> @@ -1713,13 +1731,37 @@ static int output_packet(AVInputStream *ist, int >>> ist_index, >>> for(;;) { >>> AVPacket pkt; >>> int fifo_bytes; >>> + double opts; >>> av_init_packet(&pkt); >>> pkt.stream_index= ost->index; >>> >>> switch(ost->st->codec->codec_type) { >>> case AVMEDIA_TYPE_AUDIO: >>> + opts = ost->st->pts.val * >>> av_q2d(ost->st->time_base); >>> fifo_bytes = av_fifo_size(ost->fifo); >>> ret = 0; >>> + >>> + if (ost_pad_audio && opts < vpts) { >>> + int osize = >>> av_get_bits_per_sample_fmt(enc->sample_fmt) >> 3; >>> + int frame_bytes = >>> enc->frame_size*osize*enc->channels; >>> + ost_pad_audio = 0; >>> + if (samples_size < frame_bytes) >>> + ffmpeg_exit(1); >>> + memset(samples, 0, frame_bytes); >>> + /* finish the current frame in the fifo, >>> then send whole frames */ >>> + if (fifo_bytes > 0) { >>> + do_audio_out(os, ost, ist, samples, >>> frame_bytes-fifo_bytes, 1); >>> + opts = ost->st->pts.val * >>> av_q2d(ost->st->time_base); >>> + } >>> + while (opts < vpts) { >>> + do_audio_out(os, ost, ist, samples, >>> frame_bytes, 1); >>> + opts = ost->st->pts.val * >>> av_q2d(ost->st->time_base); >>> + } >>> + fifo_bytes = av_fifo_size(ost->fifo); >>> + if (fifo_bytes != 0) >>> + ffmpeg_exit(1); >>> + } >>> + >>> /* encode any samples remaining in fifo */ >>> if (fifo_bytes > 0) { >>> int osize = >>> av_get_bits_per_sample_fmt(enc->sample_fmt) >> 3; >>> @@ -4233,6 +4275,7 @@ static const OptionDef options[] = { >>> { "vol", OPT_INT | HAS_ARG | OPT_AUDIO, {(void*)&audio_volume}, >>> "change audio volume (256=normal)" , "volume" }, // >>> { "newaudio", OPT_AUDIO | OPT_FUNC2, {(void*)opt_new_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" }, >>> + { "apad", OPT_BOOL | OPT_AUDIO, {(void*)&audio_pad}, "pad audio to >>> video length", "pad" }, >>> { "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 */ >> >> >> Based on how you're using skip_resample_reformat, it seems this patch >> doesn't work when changing sample format or sample rate when encoding, >> correct? >> >> -Justin > > The silence is generated in the output sample format domain to allow > appending silence one audio block at a time (based on the encoder's > frame size). So it should work with changing sample format and sample > rate.
I see. But it uses memset(0), so this wouldn't work with SAMPLE_FMT_U8. I'm also concerned with how it's flushing the fifo. Wouldn't that trigger detection of the last frame with encoders using CODEC_CAP_SMALL_LAST_FRAME? -Justin _______________________________________________ libav-devel mailing list [email protected] https://lists.libav.org/mailman/listinfo/libav-devel
