[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