Jim Rhodes
Jim Rhodes

Reputation: 5095

ffmpeg audio encoder frame size

I need to convert audio data from AV_CODEC_ID_PCM_S16LE to AV_CODEC_ID_PCM_ALAW and I am using this code as an example. The example code does essentially this (error checking omitted for brevity):

const AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_MP2);
AVCodecContext* c = avcodec_alloc_context3(codec);
c->bit_rate       = 64000;
c->sample_fmt     = AV_SAMPLE_FMT_S16;
c->sample_rate    = select_sample_rate(codec);
c->channel_layout = select_channel_layout(codec);
c->channels       = av_get_channel_layout_nb_channels(c->channel_layout);
avcodec_open2(c, codec, NULL);
AVFrame* frame = av_frame_alloc();
frame->nb_samples     = c->frame_size;
frame->format         = c->sample_fmt;
frame->channel_layout = c->channel_layout;

The example code subsequently uses c->frame_size in a for loop.

My code is similar to the above with the following differences:

const AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_PCM_ALAW);
c->sample_rate    = 8000;
c->channel_layout = AV_CH_LAYOUT_MONO;
c->channels       = 1;

After calling avcodec_open2, c->frame_size is zero. The example code never sets the frame size so I assume that it expects either avcodec_alloc_context3 or avcodec_open2 to set it. Is this a correct assumption? Is the setting of the frame size based on the codec being used? If I have to set the frame size explicitly, is there a recommended size?

EDIT:

Based on @the-kamilz answer it appears that the example code is not robust. The example assumes that c->frame_size will be set but that appears to be dependent on the codec. In my case, codec->capabilities was in fact set to AV_CODEC_CAP_VARIABLE_FRAME_SIZE. So I modified my code to check c->frame_size and use it only if it is not zero. If it is zero, I just picked an arbitrary one second worth of data for frame->nb_samples.

Upvotes: 4

Views: 3844

Answers (2)

oli21270
oli21270

Reputation: 21

you don't control the frame size explicitly, it is set by the encoder depending on the codecs provided at initialization (opening) time

once avcodec_open2() is successful, you can retrieve the frame's buffer size with av_samples_get_buffer_size()

Upvotes: 0

the kamilz
the kamilz

Reputation: 1988

In the FFmpeg documentation it is mentioned as:

int AVCodecContext::frame_size

Number of samples per channel in an audio frame.

encoding: set by libavcodec in avcodec_open2(). Each submitted frame except the last must contain exactly frame_size samples per channel.
May be 0 when the codec has AV_CODEC_CAP_VARIABLE_FRAME_SIZE set, then the frame size is not restricted.
decoding: may be set by some decoders to indicate constant frame size

Hope that helps.

Upvotes: 2

Related Questions