On Mon, Mar 28, 2011 at 2:37 PM, Justin Ruggles
<[email protected]> wrote:
> 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.
>
Actually it turns out this code does not run at all for PCM codecs because of
if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
enc->frame_size <=1)
continue;
So I do need to fix that part.
Do we have any non-PCM *encoders* that support SAMPLE_FMT_U8. FWIW
they are broken already if they don't support
CODEC_CAP_SMALL_LAST_FRAME. Still it should be fairly trivial to add a
small generate silence function that works for any (sane) sample
format.
> 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?
>
Each silent frame generated is full size. The audio padding feature
(when turned on and active) does prevent the generation of a small
last frame if that's what you mean.
Regards,
Alex
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel