[Libav-user] Not able to resample with libavfilter
amey jain
amey.jain7 at gmail.com
Tue Jun 20 07:18:36 EEST 2017
On Tue, Jun 20, 2017 at 2:11 AM, Paul B Mahol <onemda at gmail.com> wrote:
> On 6/19/17, amey jain <amey.jain7 at gmail.com> wrote:
>> Hi,
>> I want resampled output of 5512 Hz, mono channel, in float. I am using
>> aformat filter with these parameters and buffersrc sink. All things
>> are working fine except for the output frames collected from sink.
>> When I get sample_rate using frame->sample_rate, I get 48000 as
>> output. Also the value to nb_samples remains same. Can someone guide
>> me out here. Below is code I am using.
>>
>> //buffer src aformat initialized
>>
>> resample = avfilter_get_by_name("aformat");
>> resample_ctx = avfilter_graph_alloc_filter(filter_graph, resample,
>> "aformat");
>> av_get_channel_layout_string(ch_layout, sizeof(ch_layout),
>> 0,AV_CH_LAYOUT_MONO);
>> av_opt_set(resample_ctx, "channel_layout", ch_layout,
>> AV_OPT_SEARCH_CHILDREN);
>> av_opt_set(resample_ctx,
>> "sample_fmt",av_get_sample_fmt_name(AV_SAMPLE_FMT_FLT),
>> AV_OPT_SEARCH_CHILDREN);
>> av_opt_set_q(resample_ctx, "time_base", (AVRational){ 1, 5512
>> },AV_OPT_SEARCH_CHILDREN);
>> av_opt_set_int(resample_ctx, "sample_rate", 5512, AV_OPT_SEARCH_CHILDREN);
>> avfilter_init_str(resample_ctx, NULL);
>>
>> //buffer sink abuffersink initialized and all three linked together
>
> Mandatory code is missing. We can not guess it, please provide it or
> ask for help
> somewhere else.
Here is complete code.
static AVFormatContext *fmt_ctx = NULL;
static AVCodecContext *dec_ctx;
AVFilterContext *buffersink_ctx;
AVFilterContext *buffersrc_ctx;
AVFilterGraph *filter_graph;
int audio_stream_index = -1;
AVFilterGraph *graph;
AVFilterContext *src,*sink;
enum AVSampleFormat INPUT_SAMPLE_FMT = -1;
uint64_t INPUT_SAMPLERATE = 0;
uint64_t INPUT_CHANNEL_LAYOUT = 0;
//This function initialises input parameters
void init_input_parameters(AVFrame *frame,AVCodecContext *dec_ctx)
{
if(frame == NULL){
fprintf(stderr,"ERROR:Frame is NULL\n");
return;
}
if(dec_ctx == NULL){
fprintf(stderr,"ERROR:AVCodec context NULL\n");
return;
}
INPUT_CHANNEL_LAYOUT = frame->channel_layout;
INPUT_SAMPLERATE = frame->sample_rate;
INPUT_SAMPLE_FMT = dec_ctx->sample_fmt;
if(!INPUT_CHANNEL_LAYOUT || !INPUT_SAMPLERATE || (INPUT_SAMPLE_FMT == -1)){
fprintf(stderr,"ERROR:input parameters not set\n");
return;
}
}
//taken from ffmpeg-filter_audio.c
https://www.ffmpeg.org/doxygen/2.2/filter_audio_8c-example.html
int init_filter_graph(AVFilterGraph **graph, AVFilterContext **src,
AVFilterContext **sink)
{
AVFilterGraph *filter_graph;
AVFilterContext *abuffer_ctx;
AVFilter *abuffer;
AVFilterContext *resample_ctx;
AVFilter *resample;
AVFilterContext *abuffersink_ctx;
AVFilter *abuffersink;
uint8_t ch_layout[64];
int err;
char errstr[256];
/* Create a new filtergraph, which will contain all the filters. */
filter_graph = avfilter_graph_alloc();
if (!filter_graph) {
fprintf(stderr, "Unable to create filter graph.\n");
return AVERROR(ENOMEM);
}
/* Create the abuffer filter;
* it will be used for feeding the data into the graph. */
abuffer = avfilter_get_by_name("abuffer");
if (!abuffer) {
fprintf(stderr, "Could not find the abuffer filter.\n");
return AVERROR_FILTER_NOT_FOUND;
}
abuffer_ctx = avfilter_graph_alloc_filter(filter_graph, abuffer, "src");
if (!abuffer_ctx) {
fprintf(stderr, "Could not allocate the abuffer instance.\n");
return AVERROR(ENOMEM);
}
/* Set the filter options through the AVOptions API. */
av_get_channel_layout_string(ch_layout, sizeof(ch_layout), 0,
INPUT_CHANNEL_LAYOUT);
av_opt_set(abuffer_ctx, "channel_layout", ch_layout, AV_OPT_SEARCH_CHILDREN);
av_opt_set(abuffer_ctx, "sample_fmt",
av_get_sample_fmt_name(INPUT_SAMPLE_FMT), AV_OPT_SEARCH_CHILDREN);
av_opt_set_q(abuffer_ctx, "time_base", (AVRational){ 1,
INPUT_SAMPLERATE }, AV_OPT_SEARCH_CHILDREN);
av_opt_set_int(abuffer_ctx, "sample_rate", INPUT_SAMPLERATE,
AV_OPT_SEARCH_CHILDREN);
/* Now initialize the filter; we pass NULL options, since we have
already
* set all the options above. */
err = avfilter_init_str(abuffer_ctx, NULL);
if (err < 0) {
fprintf(stderr, "Could not initialize the abuffer filter.\n");
return err;
}
/* Create resampling filter. */
resample = avfilter_get_by_name("aformat");
if (!resample) {
fprintf(stderr, "Could not find the aformat filter.\n");
return AVERROR_FILTER_NOT_FOUND;
}
resample_ctx = avfilter_graph_alloc_filter(filter_graph, resample, "aformat");
if (!resample_ctx) {
fprintf(stderr, "Could not allocate the resample instance.\n");
return AVERROR(ENOMEM);
}
/* Set the filter options through the AVOptions API. */
av_get_channel_layout_string(ch_layout, sizeof(ch_layout), 0,
AV_CH_LAYOUT_MONO);
av_opt_set(resample_ctx, "channel_layout", ch_layout, AV_OPT_SEARCH_CHILDREN);
av_opt_set(resample_ctx, "sample_fmt",
av_get_sample_fmt_name(AV_SAMPLE_FMT_FLT), AV_OPT_SEARCH_CHILDREN);
av_opt_set_q(resample_ctx, "time_base", (AVRational){ 1, 5512 },
AV_OPT_SEARCH_CHILDREN);
av_opt_set_int(resample_ctx, "sample_rate", 5512, AV_OPT_SEARCH_CHILDREN);
avfilter_init_str(resample_ctx, NULL);
if (err < 0) {
fprintf(stderr, "Could not initialize the resampling filter.\n");
return err;
}
/* Finally create the abuffersink filter;
* it will be used to get the filtered data out of the graph. */
abuffersink = avfilter_get_by_name("abuffersink");
if (!abuffersink) {
fprintf(stderr, "Could not find the abuffersink filter.\n");
return AVERROR_FILTER_NOT_FOUND;
}
abuffersink_ctx = avfilter_graph_alloc_filter(filter_graph,
abuffersink, "sink");
if (!abuffersink_ctx) {
fprintf(stderr, "Could not allocate the abuffersink instance.\n");
return AVERROR(ENOMEM);
}
/* This filter takes no options. */
err = avfilter_init_str(abuffersink_ctx, NULL);
if (err < 0) {
fprintf(stderr, "Could not initialize the abuffersink instance.\n");
return err;
}
/* Connect the filters;
* in this simple case the filters just form a linear chain. */
err = avfilter_link(abuffer_ctx, 0, resample_ctx, 0);
if (err >= 0)
err = avfilter_link(resample_ctx, 0, abuffersink_ctx, 0);
else{
fprintf(stderr, "Error connecting filters buffer src and resample
%d error\n",err);
av_strerror(err, errstr, sizeof(errstr));
fprintf(stderr, "%s\n", errstr);
return err;
}
if (err < 0) {
fprintf(stderr, "Error connecting filters resample and buffersink
%d error\n",err);
return err;
}
/* Configure the graph. */
err = avfilter_graph_config(filter_graph, NULL);
if (err < 0) {
fprintf(stderr, "Error configuring the filter graph\n");
return err;
}
*graph = filter_graph;
*src = abuffer_ctx;
*sink = abuffersink_ctx;
return 0;
} //init_filter_graph
//function that uses filter_graph
void process_frame_by_pts(int64_t time_to_seek_ms)
{
int64_t num = fmt_ctx->streams[audio_stream_index]->time_base.num;
int64_t den = fmt_ctx->streams[audio_stream_index]->time_base.den;
int64_t duration;
int64_t start_pts = ((float)time_to_seek_ms/1000) * (float)den/num;
// converted to timebase of audio stream
int64_t end_pts = start_pts + ((float)(GRANUALITY/1000) * den/num);
int i = 0, count = 0,temp = 0,out_count = 0,in_count = 0;
uint8_t *OUTPUT_SAMPLES = NULL;
AVPacket pkt;
uint8_t *in;
int got_frame,ret;
AVFrame *frame = av_frame_alloc();
int size,len,buf_size;
uint64_t output_ch_layout = av_get_channel_layout("mono");
enum AVSampleFormat src_sample_fmt;
uint8_t *output_buffer = NULL;
int err;
if(end_pts > fmt_ctx->streams[audio_stream_index]->duration){
printf("Error: End PTS greater then duration of stream\n");
return;
}
while(1){ //read an audio frame for format specifications
ret = av_read_frame(fmt_ctx, &pkt);
if(ret < 0){
printf("Unable to read frame:%d \n",ret);
break;
}
if(pkt.stream_index == audio_stream_index){
got_frame = 0;
len = avcodec_decode_audio4(dec_ctx, frame, &got_frame, &pkt);
if(len < 0){
printf("Error while decoding\n");
}
else if(got_frame)
break;
}
}
/* Initialise filters */
init_input_parameters(frame, dec_ctx);
err = init_filter_graph(&graph, &src, &sink);
if(err != 0){
fprintf(stderr,"ERROR: Not able to initialize input parameters\n");
return err;
}
ret = av_seek_frame(fmt_ctx,audio_stream_index,start_pts,AVSEEK_FLAG_BACKWARD);
//get one frame before timing to cover all
if( ret < 0 ){
fprintf(stderr,"av_seek_frame failed with error code %d\n",ret);
return;
}
fprintf(stdout,"Start PTS: %lu End PTS: %lu\n",start_pts,end_pts);
do{ //outer do-while to read packets
ret = av_read_frame(fmt_ctx, &pkt);
if(ret < 0){
printf("Unable to read frame:%d \n",ret);
break;
}
if(pkt.stream_index == audio_stream_index){ // processing multiple
audio packets,if present
size = pkt.size;
while(size > 0){ // inner while to decode frames, if more than
one are present in a single packet
got_frame = 0;
len = avcodec_decode_audio4(dec_ctx, frame, &got_frame, &pkt);
if(len < 0){
printf("Error while decoding\n");
}
if(got_frame){
err = av_buffersrc_add_frame(src, frame);
if(err < 0) {
av_frame_unref(frame);
fprintf(stderr,"Error adding frame to source buffer\n");
return;
}
size = size - len;
}
}
}
}while(frame->pts < end_pts);
while((err = av_buffersink_get_frame(sink,frame) >= 0)){
fprintf(stdout,"frame->duration(PTS) %d frame->duration: %f with
sample rate as:%d number of samples
%d\n",frame->pkt_duration,((double)frame->pkt_duration/frame->sample_rate)
* 1000,frame->sample_rate,frame->nb_samples); //here is part when we
don't get 5512 as sampling rate
}
avfilter_graph_free(&graph);
av_frame_free(&frame);
return;
}
More information about the Libav-user
mailing list