Advertisement
vinvinod

Audio Transcoding using FFmpeg - error

Dec 7th, 2013
282
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 19.55 KB | None | 0 0
  1.         /*
  2.          * File:   main.cpp
  3.          * Author: vinod
  4.          * Compile with "g++ -std=c++11 -o audiotranscode main.cpp -lavformat -lavcodec -lavutil -lavfilter"
  5.          *
  6.          */
  7.  
  8.  
  9.         #if !defined PRId64 || PRI_MACROS_BROKEN
  10.         #undef PRId64
  11.         #define PRId64 "lld"
  12.         #endif
  13.  
  14.         #define __STDC_FORMAT_MACROS
  15.  
  16.         #ifdef   __cplusplus
  17.         extern "C" {
  18.         #endif
  19.  
  20.         #include <stdio.h>
  21.         #include <stdlib.h>
  22.         #include <sys/types.h>
  23.         #include <stdint.h>
  24.         #include <libavutil/imgutils.h>
  25.         #include <libavutil/samplefmt.h>
  26.         #include <libavutil/frame.h>
  27.         #include <libavutil/timestamp.h>
  28.         #include <libavformat/avformat.h>
  29.         #include <libavfilter/avfilter.h>
  30.         #include <libavfilter/buffersrc.h>
  31.         #include <libavfilter/buffersink.h>
  32.         #include <libswscale/swscale.h>
  33.         #include <libavutil/opt.h>
  34.  
  35.         #ifdef   __cplusplus
  36.         }
  37.         #endif
  38.  
  39.         #include <iostream>
  40.         using namespace std;
  41.  
  42.         int select_stream, got_frame, got_packet;
  43.  
  44.         AVFormatContext *in_fmt_ctx = NULL, *out_fmt_ctx = NULL;
  45.         AVCodec *dec_codec = NULL, * enc_codec = NULL;
  46.         AVStream *audio_st = NULL;
  47.         AVCodecContext *enc_ctx = NULL, *dec_ctx = NULL;
  48.  
  49.         AVFrame *pFrame = NULL, * pFrameFiltered = NULL;
  50.  
  51.         AVFilterGraph *filter_graph = NULL;
  52.         AVFilterContext *buffersrc_ctx = NULL;
  53.         AVFilterContext *buffersink_ctx = NULL;
  54.  
  55.         AVPacket packet;
  56.  
  57.         string inFileName = "/home/vinod/vinod/Media/univac.webm";
  58.         string outFileName = "audio_extracted.m4a";
  59.  
  60.         int target_bit_rate = 128000,
  61.             sample_rate = 22050,
  62.             channels = 1;
  63.         AVSampleFormat sample_fmt = AV_SAMPLE_FMT_S16;
  64.         string filter_description = "aresample=22050,aformat=sample_fmts=s16:channel_layouts=mono";
  65.  
  66.         int log_averror(int errcode)
  67.         {
  68.                 char *errbuf = (char *) calloc(AV_ERROR_MAX_STRING_SIZE, sizeof(char));
  69.                 av_strerror(errcode, errbuf, AV_ERROR_MAX_STRING_SIZE);
  70.                 std::cout << "Error - " << errbuf << std::endl;
  71.                 delete [] errbuf;
  72.                 return -1;
  73.         }
  74.  
  75.         /**
  76.          * Initialize conversion filter */
  77.         int initialize_audio_filter()
  78.         {
  79.                 char args[512];
  80.                 int ret;
  81.                 AVFilter *buffersrc = avfilter_get_by_name("abuffer");
  82.                 AVFilter *buffersink = avfilter_get_by_name("abuffersink");
  83.                 AVFilterInOut *outputs = avfilter_inout_alloc();
  84.                 AVFilterInOut *inputs = avfilter_inout_alloc();
  85.                 filter_graph = avfilter_graph_alloc();
  86.                 const enum AVSampleFormat out_sample_fmts[] = {sample_fmt, AV_SAMPLE_FMT_NONE};
  87.                 const int64_t out_channel_layouts[] = {av_get_default_channel_layout(out_fmt_ctx -> streams[0] -> codec -> channels), -1};
  88.                 const int out_sample_rates[] = {out_fmt_ctx -> streams[0] -> codec -> sample_rate, -1};
  89.  
  90.                 if (!dec_ctx->channel_layout)
  91.                         dec_ctx->channel_layout = av_get_default_channel_layout(dec_ctx->channels);
  92.  
  93.                 snprintf(args, sizeof(args), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%" PRIx64,
  94.                          in_fmt_ctx -> streams[select_stream] -> time_base.num, in_fmt_ctx -> streams[select_stream] -> time_base.den,
  95.                          dec_ctx->sample_rate,
  96.                          av_get_sample_fmt_name(dec_ctx->sample_fmt),
  97.                          dec_ctx->channel_layout);
  98.                 ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", args, NULL, filter_graph);
  99.  
  100.                 if (ret < 0) {
  101.                         av_log(NULL, AV_LOG_ERROR, "Cannot create buffer source\n");
  102.                         return -1;
  103.                 }
  104.  
  105.                 ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out", NULL, NULL, filter_graph);
  106.  
  107.                 if (ret < 0) {
  108.                         av_log(NULL, AV_LOG_ERROR, "Cannot create buffer sink\n");
  109.                         return ret;
  110.                 }
  111.  
  112.                 ret = av_opt_set_int_list(buffersink_ctx, "sample_fmts", out_sample_fmts, -1,
  113.                                           AV_OPT_SEARCH_CHILDREN);
  114.  
  115.                 if (ret < 0) {
  116.                         av_log(NULL, AV_LOG_ERROR, "Cannot set output sample format\n");
  117.                         return ret;
  118.                 }
  119.  
  120.                 ret = av_opt_set_int_list(buffersink_ctx, "channel_layouts", out_channel_layouts, -1,
  121.                                           AV_OPT_SEARCH_CHILDREN);
  122.  
  123.                 if (ret < 0) {
  124.                         av_log(NULL, AV_LOG_ERROR, "Cannot set output channel layout\n");
  125.                         return ret;
  126.                 }
  127.  
  128.                 ret = av_opt_set_int_list(buffersink_ctx, "sample_rates", out_sample_rates, -1,
  129.                                           AV_OPT_SEARCH_CHILDREN);
  130.  
  131.                 if (ret < 0) {
  132.                         av_log(NULL, AV_LOG_ERROR, "Cannot set output sample rate\n");
  133.                         return ret;
  134.                 }
  135.  
  136.                 /* Endpoints for the filter graph. */
  137.                 outputs -> name = av_strdup("in");
  138.                 outputs -> filter_ctx = buffersrc_ctx;
  139.                 outputs -> pad_idx = 0;
  140.                 outputs -> next = NULL;
  141.                 /* Endpoints for the filter graph. */
  142.                 inputs -> name = av_strdup("out");
  143.                 inputs -> filter_ctx = buffersink_ctx;
  144.                 inputs -> pad_idx = 0;
  145.                 inputs -> next = NULL;
  146.                 string filter_desc = filter_description;
  147.  
  148.                 if ((ret = avfilter_graph_parse_ptr(filter_graph, filter_desc.c_str(), &inputs, &outputs, NULL)) < 0) {
  149.                         log_averror(ret);
  150.                         exit(1);
  151.                 }
  152.  
  153.                 if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0) {
  154.                         log_averror(ret);
  155.                         exit(1);
  156.                 }
  157.  
  158.                 /* Print summary of the sink buffer
  159.                  * Note: args buffer is reused to store channel layout string */
  160.                 AVFilterLink *outlink = buffersink_ctx->inputs[0];
  161.                 av_get_channel_layout_string(args, sizeof(args), -1, outlink->channel_layout);
  162.                 av_log(NULL, AV_LOG_INFO, "Output: srate:%dHz fmt:%s chlayout:%s\n",
  163.                        (int) outlink->sample_rate,
  164.                        (char *) av_x_if_null(av_get_sample_fmt_name((AVSampleFormat) outlink->format), "?"),
  165.                        args);
  166.                 return 0;
  167.         }
  168.  
  169.         /*
  170.          *
  171.          */
  172.         int main(int argc, char **argv)
  173.         {
  174.                 int ret;
  175.                 cout << "Hello World" << endl;
  176.                 printf("abcd");
  177.                 avcodec_register_all();
  178.                 av_register_all();
  179.                 avfilter_register_all();
  180.  
  181.                 /* open input file, and allocate format context */
  182.                 if (avformat_open_input(&in_fmt_ctx, inFileName.c_str(), NULL, NULL) < 0) {
  183.                         std::cout << "error opening input file - " << inFileName << std::endl;
  184.                         return -1;
  185.                 }
  186.  
  187.                 /* retrieve stream information */
  188.                 if (avformat_find_stream_info(in_fmt_ctx, NULL) < 0) {
  189.                         std::cerr << "Could not find stream information in the input file " << inFileName << std::endl;
  190.                 }
  191.  
  192.                 /* Dump format details */
  193.                 printf("\n ---------------------------------------------------------------------- \n");
  194.                 av_dump_format(in_fmt_ctx, 0, inFileName.c_str(), 0);
  195.                 printf("\n ---------------------------------------------------------------------- \n");
  196.                 /* Choose a audio stream */
  197.                 select_stream = av_find_best_stream(in_fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, &dec_codec, 0);
  198.  
  199.                 if (select_stream == AVERROR_STREAM_NOT_FOUND) {
  200.                         std::cerr << "No audio stream found" << std::endl;
  201.                         return -1;
  202.                 }
  203.  
  204.                 if (select_stream == AVERROR_DECODER_NOT_FOUND) {
  205.                         std::cerr << "No suitable decoder found" << std::endl;
  206.                         return -1;
  207.                 }
  208.  
  209.                 dec_ctx = in_fmt_ctx -> streams[ select_stream] -> codec;
  210.                 av_opt_set_int(dec_ctx, "refcounted_frames", 1, 0);
  211.  
  212.                 /* init the audio decoder */
  213.                 if ((ret = avcodec_open2(dec_ctx, dec_codec, NULL)) < 0) {
  214.                         av_log(NULL, AV_LOG_ERROR, "Cannot open audio decoder\n");
  215.                         return ret;
  216.                 }
  217.  
  218.                 /* allocate output context */
  219.                 ret = avformat_alloc_output_context2(&out_fmt_ctx, NULL, NULL,
  220.                                                      outFileName.c_str());
  221.  
  222.                 if (ret < 0) {
  223.                         std::cerr << "Could not create output context for the file " << outFileName << std::endl;
  224.                         return -1;
  225.                 }
  226.  
  227.                 /* find the encoder */
  228.                 enum AVCodecID codec_id = out_fmt_ctx -> oformat -> audio_codec;
  229.                 enc_codec = avcodec_find_encoder(codec_id);
  230.  
  231.                 if (!(enc_codec)) {
  232.                         std::cerr << "Could not find encoder for - " << avcodec_get_name(codec_id) << std::endl;
  233.                         return -1;
  234.                 }
  235.  
  236.                 /* add a new stream */
  237.                 audio_st = avformat_new_stream(out_fmt_ctx, enc_codec);
  238.  
  239.                 if (!audio_st) {
  240.                         std::cerr << "Could not add audio stream - " << std::endl;
  241.                 }
  242.  
  243.                 /* Initialise audio codec */
  244.                 audio_st -> id = out_fmt_ctx -> nb_streams - 1;
  245.                 enc_ctx = audio_st -> codec;
  246.                 enc_ctx -> codec_id = codec_id;
  247.                 enc_ctx -> codec_type = AVMEDIA_TYPE_AUDIO;
  248.                 enc_ctx -> bit_rate = target_bit_rate;
  249.                 enc_ctx -> sample_rate = sample_rate;
  250.                 enc_ctx -> sample_fmt = sample_fmt;
  251.                 enc_ctx -> channels = channels;
  252.                 enc_ctx -> channel_layout = av_get_default_channel_layout(enc_ctx -> channels);
  253.  
  254.                 /* Some formats want stream headers to be separate. */
  255.                 if (out_fmt_ctx -> oformat -> flags & AVFMT_GLOBALHEADER) {
  256.                         enc_ctx -> flags |= CODEC_FLAG_GLOBAL_HEADER;
  257.                 }
  258.  
  259.                 ret = avcodec_open2(out_fmt_ctx -> streams[0] -> codec, enc_codec, NULL);
  260.  
  261.                 if (ret < 0) {
  262.                         std::cerr << "Could not create codec context for the file " << outFileName << std::endl;
  263.                         return -1;
  264.                 }
  265.  
  266.                 /* Initialize filter */
  267.                 initialize_audio_filter();
  268.  
  269.                 if (!(out_fmt_ctx -> oformat -> flags & AVFMT_NOFILE)) {
  270.                         int ret = avio_open(& out_fmt_ctx -> pb, outFileName.c_str(),
  271.                                             AVIO_FLAG_WRITE);
  272.  
  273.                         if (ret < 0) {
  274.                                 log_averror(ret);
  275.                                 return -1;
  276.                         }
  277.                 }
  278.  
  279.                 /* Write header */
  280.                 if (avformat_write_header(out_fmt_ctx, NULL) < 0) {
  281.                         if (ret < 0) {
  282.                                 log_averror(ret);
  283.                                 return -1;
  284.                         }
  285.                 }
  286.  
  287.                 /* Allocate frame */
  288.                 pFrame = av_frame_alloc();
  289.  
  290.                 if (!pFrame) {
  291.                         std::cerr << "Could not allocate frame\n";
  292.                         return -1;
  293.                 }
  294.  
  295.                 pFrameFiltered = av_frame_alloc();
  296.  
  297.                 if (!pFrameFiltered) {
  298.                         std::cerr << "Could not allocate frame\n";
  299.                         return -1;
  300.                 }
  301.  
  302.                 av_init_packet(&packet);
  303.                 packet.data = NULL;
  304.                 packet.size = 0;
  305.  
  306.                 /* Read packet from the stream */
  307.                 while (av_read_frame(in_fmt_ctx, &packet) >= 0) {
  308.                         if (packet.stream_index == select_stream) {
  309.                                 avcodec_get_frame_defaults(pFrame);
  310.                                 ret = avcodec_decode_audio4(dec_ctx, pFrame, &got_frame, &packet);
  311.  
  312.                                 if (ret < 0) {
  313.                                         log_averror(ret);
  314.                                         return ret;
  315.                                 }
  316.  
  317.                                 printf("Decoded packet pts : %ld ", packet.pts);
  318.                                 printf("Frame Best Effor pts : %ld \n", pFrame->best_effort_timestamp);
  319.                                 /* Set frame pts */
  320.                                 pFrame -> pts = av_frame_get_best_effort_timestamp(pFrame);
  321.  
  322.                                 if (got_frame) {
  323.                                         /* push the decoded frame into the filtergraph */
  324.                                         ret = av_buffersrc_add_frame_flags(buffersrc_ctx, pFrame, AV_BUFFERSRC_FLAG_KEEP_REF);
  325.  
  326.                                         if (ret < 0) {
  327.                                                 log_averror(ret);
  328.                                                 return ret;
  329.                                         }
  330.  
  331.                                         /* pull filtered frames from the filtergraph */
  332.                                         while (1) {
  333.                                                 ret = av_buffersink_get_frame(buffersink_ctx, pFrameFiltered);
  334.  
  335.                                                 if ((ret == AVERROR(EAGAIN)) || (ret == AVERROR_EOF)) {
  336.                                                         break;
  337.                                                 }
  338.  
  339.                                                 if (ret < 0) {
  340.                                                         printf("Error while getting filtered frames from filtergraph\n");
  341.                                                         log_averror(ret);
  342.                                                         return -1;
  343.                                                 }
  344.  
  345.                                                 /* Initialize the packets */
  346.                                                 AVPacket encodedPacket = {0};
  347.                                                 av_init_packet(&encodedPacket);
  348.                                                 ret = avcodec_encode_audio2(out_fmt_ctx -> streams[0] -> codec, &encodedPacket, pFrameFiltered, &got_packet);
  349.  
  350.                                                 if (!ret && got_packet && encodedPacket.size) {
  351.                                                         /* Set correct pts and dts */
  352.                                                         if (encodedPacket.pts != AV_NOPTS_VALUE) {
  353.                                                                 encodedPacket.pts = av_rescale_q(encodedPacket.pts, buffersink_ctx -> inputs[0] -> time_base,
  354.                                                                                                  out_fmt_ctx -> streams[0] -> time_base);
  355.                                                         }
  356.  
  357.                                                         if (encodedPacket.dts != AV_NOPTS_VALUE) {
  358.                                                                 encodedPacket.dts = av_rescale_q(encodedPacket.dts, buffersink_ctx -> inputs[0] -> time_base,
  359.                                                                                                  out_fmt_ctx -> streams[0] -> time_base);
  360.                                                         }
  361.  
  362.                                                         printf("Encoded packet pts %ld\n", encodedPacket.pts);
  363.                                                         /* Write the compressed frame to the media file. */
  364.                                                         ret = av_interleaved_write_frame(out_fmt_ctx, &encodedPacket);
  365.  
  366.                                                         if (ret < 0) {
  367.                                                                 log_averror(ret);
  368.                                                                 return -1;
  369.                                                         }
  370.                                                 } else if (ret < 0) {
  371.                                                         log_averror(ret);
  372.                                                         return -1;
  373.                                                 }
  374.  
  375.                                                 av_frame_unref(pFrameFiltered);
  376.                                         }
  377.  
  378.                                         av_frame_unref(pFrame);
  379.                                 }
  380.                         }
  381.                 }
  382.  
  383.                 /* Flush delayed frames from encoder*/
  384.                 while (got_packet) {
  385.                         AVPacket encodedPacket = {0};
  386.                         av_init_packet(&encodedPacket);
  387.                         ret = avcodec_encode_audio2(out_fmt_ctx -> streams[0] -> codec, &encodedPacket, NULL, &got_packet);
  388.  
  389.                         if (!ret && got_packet && encodedPacket.size) {
  390.                                 /* Set correct pts and dts */
  391.                                 if (encodedPacket.pts != AV_NOPTS_VALUE) {
  392.                                         encodedPacket.pts = av_rescale_q(encodedPacket.pts, buffersink_ctx -> inputs[0] -> time_base,
  393.                                                                          out_fmt_ctx -> streams[0] -> time_base);
  394.                                 }
  395.  
  396.                                 if (encodedPacket.dts != AV_NOPTS_VALUE) {
  397.                                         encodedPacket.dts = av_rescale_q(encodedPacket.dts, buffersink_ctx -> inputs[0] -> time_base,
  398.                                                                          out_fmt_ctx -> streams[0] -> time_base);
  399.                                 }
  400.  
  401.                                 printf("Encoded packet pts %ld\n", encodedPacket.pts);
  402.                                 /* Write the compressed frame to the media file. */
  403.                                 ret = av_interleaved_write_frame(out_fmt_ctx, &encodedPacket);
  404.  
  405.                                 if (ret < 0) {
  406.                                         log_averror(ret);
  407.                                         return -1;
  408.                                 }
  409.                         } else if (ret < 0) {
  410.                                 log_averror(ret);
  411.                                 return -1;
  412.                         }
  413.                 }
  414.  
  415.                 /* Write Trailer */
  416.                 av_write_trailer(out_fmt_ctx);
  417.                 avfilter_graph_free(&filter_graph);
  418.  
  419.                 if (dec_ctx)
  420.                         avcodec_close(dec_ctx);
  421.  
  422.                 avformat_close_input(&in_fmt_ctx);
  423.                 av_frame_free(&pFrame);
  424.                 av_frame_free(&pFrameFiltered);
  425.  
  426.                 if (!(out_fmt_ctx -> oformat -> flags & AVFMT_NOFILE))
  427.                         avio_close(out_fmt_ctx -> pb);
  428.  
  429.                 avformat_free_context(out_fmt_ctx);
  430.                 return 0;
  431.         }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement