Advertisement
mnguyen

extract audio from media file

Aug 12th, 2014
246
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.75 KB | None | 0 0
  1. /*
  2.  * Copyright (c) 2010 Nicolas George
  3.  * Copyright (c) 2011 Stefano Sabatini
  4.  * Copyright (c) 2012 Clรฉment Bล“sch
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a copy
  7.  * of this software and associated documentation files (the "Software"), to deal
  8.  * in the Software without restriction, including without limitation the rights
  9.  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10.  * copies of the Software, and to permit persons to whom the Software is
  11.  * furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included in
  14.  * all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22.  * THE SOFTWARE.
  23.  */
  24. /**
  25.  * @file
  26.  * API example for audio decoding and filtering
  27.  * @example filtering_audio.c
  28.  */
  29.  
  30.  
  31. #include "MediaExtractionTools.h"
  32. #include <iostream>
  33. #include <hlcam-common.h>
  34.  
  35. #ifdef __cplusplus
  36. extern "C" {
  37. #endif
  38. #include <unistd.h>
  39. #include <libavcodec/avcodec.h>
  40. #include <libavformat/avformat.h>
  41. #include <libavfilter/avfiltergraph.h>
  42. #include <libavfilter/avcodec.h>
  43. #include <libavfilter/buffersink.h>
  44. #include <libavfilter/buffersrc.h>
  45. #include <libavutil/opt.h>
  46. #include <libavutil/frame.h>
  47.  
  48.  
  49. #ifndef M_PI
  50. #define M_PI 3.1415926535897931
  51. #endif
  52.  
  53. static const char *filter_descr = "aresample=8000,aformat=sample_fmts=s16:channel_layouts=mono";
  54. static const char *player       = "ffplay -f s16le -ar 8000 -ac 1 -";
  55. static AVFormatContext *fmt_ctx;
  56. static AVCodecContext *dec_ctx;
  57.  
  58. AVFilterContext *buffersink_ctx;
  59. AVFilterContext *buffersrc_ctx;
  60. AVFilterGraph *filter_graph;
  61. static int audio_stream_index = -1;
  62.  
  63. static int open_input_file(const char *filename)
  64. {
  65.     int ret;
  66.     AVCodec *dec;
  67.     if ((ret = avformat_open_input(&fmt_ctx, filename, NULL, NULL)) < 0) {
  68.         av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n");
  69.         return ret;
  70.     }
  71.     if ((ret = avformat_find_stream_info(fmt_ctx, NULL)) < 0) {
  72.         av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n");
  73.         return ret;
  74.     }
  75.     /* select the audio stream */
  76.     ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, &dec, 0);
  77.     if (ret < 0) {
  78.         av_log(NULL, AV_LOG_ERROR, "Cannot find a audio stream in the input file\n");
  79.         return ret;
  80.     }
  81.     audio_stream_index = ret;
  82.     dec_ctx = fmt_ctx->streams[audio_stream_index]->codec;
  83.     av_opt_set_int(dec_ctx, "refcounted_frames", 1, 0);
  84.     /* init the audio decoder */
  85.     if ((ret = avcodec_open2(dec_ctx, dec, NULL)) < 0) {
  86.         av_log(NULL, AV_LOG_ERROR, "Cannot open audio decoder\n");
  87.         return ret;
  88.     }
  89.     return 0;
  90. }
  91.  
  92.  
  93. static int init_filters(const char *filters_descr)
  94. {
  95.     char args[512];
  96.     int ret = 0;
  97.     AVFilter *abuffersrc  = avfilter_get_by_name("abuffer");
  98.     AVFilter *abuffersink = avfilter_get_by_name("abuffersink");
  99.     AVFilterInOut *outputs = avfilter_inout_alloc();
  100.     AVFilterInOut *inputs  = avfilter_inout_alloc();
  101.     static const enum AVSampleFormat out_sample_fmts[] = { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE };
  102.  
  103.     static const int64_t out_channel_layouts[] = { AV_CH_LAYOUT_MONO, AV_SAMPLE_FMT_NONE };
  104.     static const int out_sample_rates[] = { 8000, -1 };
  105.     const AVFilterLink *outlink;
  106.     AVRational time_base = fmt_ctx->streams[audio_stream_index]->time_base;
  107.     filter_graph = avfilter_graph_alloc();
  108.     if (!outputs || !inputs || !filter_graph) {
  109.         ret = AVERROR(ENOMEM);
  110.         goto end;
  111.     }
  112.     /* buffer audio source: the decoded frames from the decoder will be inserted here. */
  113.     if (!dec_ctx->channel_layout)
  114.         dec_ctx->channel_layout = av_get_default_channel_layout(dec_ctx->channels);
  115.         snprintf(args, sizeof(args),
  116.             "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%llx", // substituted 11x for PRIx64 macro
  117.              time_base.num, time_base.den, dec_ctx->sample_rate,
  118.              av_get_sample_fmt_name(dec_ctx->sample_fmt), dec_ctx->channel_layout);
  119.     ret = avfilter_graph_create_filter(&buffersrc_ctx, abuffersrc, "in",
  120.                                        args, NULL, filter_graph);
  121.     if (ret < 0) {
  122.         av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer source\n");
  123.         goto end;
  124.     }
  125.     /* buffer audio sink: to terminate the filter chain. */
  126.     ret = avfilter_graph_create_filter(&buffersink_ctx, abuffersink, "out",
  127.                                        NULL, NULL, filter_graph);
  128.     if (ret < 0) {
  129.         av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer sink\n");
  130.         goto end;
  131.     }
  132.     ret = av_opt_set_int_list(buffersink_ctx, "sample_fmts", out_sample_fmts, -1,
  133.                               AV_OPT_SEARCH_CHILDREN);
  134.     if (ret < 0) {
  135.         av_log(NULL, AV_LOG_ERROR, "Cannot set output sample format\n");
  136.         goto end;
  137.     }
  138.     ret = av_opt_set_int_list(buffersink_ctx, "channel_layouts", out_channel_layouts, -1,
  139.                               AV_OPT_SEARCH_CHILDREN);
  140.     if (ret < 0) {
  141.         av_log(NULL, AV_LOG_ERROR, "Cannot set output channel layout\n");
  142.         goto end;
  143.     }
  144.     ret = av_opt_set_int_list(buffersink_ctx, "sample_rates", out_sample_rates, -1,
  145.                               AV_OPT_SEARCH_CHILDREN);
  146.     if (ret < 0) {
  147.         av_log(NULL, AV_LOG_ERROR, "Cannot set output sample rate\n");
  148.         goto end;
  149.     }
  150.     /* Endpoints for the filter graph. */
  151.     outputs->name       = av_strdup("in");
  152.     outputs->filter_ctx = buffersrc_ctx;
  153.     outputs->pad_idx    = 0;
  154.     outputs->next       = NULL;
  155.     inputs->name       = av_strdup("out");
  156.     inputs->filter_ctx = buffersink_ctx;
  157.     inputs->pad_idx    = 0;
  158.     inputs->next       = NULL;
  159.     if ((ret = avfilter_graph_parse_ptr(filter_graph, filters_descr,
  160.                                         &inputs, &outputs, NULL)) < 0)
  161.         goto end;
  162.     if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0)
  163.         goto end;
  164.     /* Print summary of the sink buffer
  165.      * Note: args buffer is reused to store channel layout string */
  166.     outlink = buffersink_ctx->inputs[0];
  167.     av_get_channel_layout_string(args, sizeof(args), -1, outlink->channel_layout);
  168.     av_log(NULL, AV_LOG_INFO, "Output: srate:%dHz fmt:%s chlayout:%s\n",
  169.            (int)outlink->sample_rate,
  170.            (char *)av_x_if_null(av_get_sample_fmt_name((AVSampleFormat)outlink->format), "?"),
  171.            args);
  172. end:
  173.     avfilter_inout_free(&inputs);
  174.     avfilter_inout_free(&outputs);
  175.  
  176.     return ret;
  177. }
  178.  
  179.  
  180. static void print_frame(const AVFrame *frame, FILE* dst)
  181. {
  182.     const int n = frame->nb_samples * av_get_channel_layout_nb_channels(av_frame_get_channel_layout(frame));
  183.     const uint16_t *p     = (uint16_t*)frame->data[0];
  184.     const uint16_t *p_end = p + n;
  185.     while (p < p_end) {
  186.         fputc(*p    & 0xff, dst);
  187.         fputc(*p>>8 & 0xff, dst);
  188.         p++;
  189.     }
  190.     fflush(dst);
  191. }
  192.  
  193. int extractAudioFromVideo(const char* inputVideoFilename) {
  194.     int ret;
  195.     FILE* audioOutputStream;
  196.     AVPacket packet0, packet;
  197.     AVFrame *frame = av_frame_alloc();
  198.     AVFrame *filt_frame = av_frame_alloc();
  199.     int got_frame;
  200.  
  201.     if (!frame || !filt_frame) {
  202.         ELOG("Could not allocate frame");
  203.         return 1;
  204.     }
  205.  
  206.     DLOG("Registering all codecs for processing");
  207.     av_register_all();
  208.     avfilter_register_all();
  209.     DLOG("Opening %s for audio extraction", inputVideoFilename);
  210.  
  211.     ret = open_input_file(inputVideoFilename);
  212.     if (ret == 0)
  213.         ret = init_filters(filter_descr);
  214.  
  215.     std::string wavFilename(inputVideoFilename);
  216.     wavFilename = wavFilename + ".wav";
  217.  
  218.     DLOG("Wriitng wav file to %s", wavFilename.c_str());
  219.     audioOutputStream = fopen(wavFilename.c_str(), "w");
  220.  
  221.     if (audioOutputStream == NULL)
  222.     {
  223.         DLOG("Failed to create audio file from video %s", wavFilename.c_str());
  224.         ret = 100;
  225.     }
  226.    
  227.     if (ret == 0) {
  228.         /* read all packets */
  229.         packet0.data = NULL;
  230.         packet.data = NULL;
  231.         while (1) {
  232.             if (!packet0.data) {
  233.                 if ((ret = av_read_frame(fmt_ctx, &packet)) < 0)
  234.                     break;
  235.                 packet0 = packet;
  236.             }
  237.             if (packet.stream_index == audio_stream_index) {
  238.                 got_frame = 0;
  239.                 ret = avcodec_decode_audio4(dec_ctx, frame, &got_frame, &packet);
  240.                 if (ret < 0) {
  241.                     ELOG("Error decoding audio: [%d]", ret);
  242.                     continue;
  243.                 }
  244.                 packet.size -= ret;
  245.                 packet.data += ret;
  246.                 if (got_frame) {
  247.                     /* push the audio data from decoded frame into the filtergraph */
  248.                     if (av_buffersrc_add_frame_flags(buffersrc_ctx, frame, 0) < 0) {
  249.                         ELOG("Error while feeding the audio filtergraph: [%d]", ret);
  250. //                        av_log(NULL, AV_LOG_ERROR, "Error while feeding the audio filtergraph\n");
  251.                         break;
  252.                     }
  253.                     /* pull filtered audio from the filtergraph */
  254.                     while (1) {
  255.                         ret = av_buffersink_get_frame(buffersink_ctx, filt_frame);
  256.                         if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
  257.                             break;
  258.                         if (ret < 0)
  259.                             goto end;
  260.  
  261.                         print_frame(filt_frame, audioOutputStream);
  262.                         av_frame_unref(filt_frame);
  263.                     }
  264.                 }
  265.                 if (packet.size <= 0)
  266.                     av_free_packet(&packet0);
  267.             } else {
  268.                 /* discard non-wanted packets */
  269.                 av_free_packet(&packet0);
  270.             }
  271.         }
  272.     }
  273. end:
  274.     avfilter_graph_free(&filter_graph);
  275.     avcodec_close(dec_ctx);
  276.     avformat_close_input(&fmt_ctx);
  277.     av_frame_free(&frame);
  278.     av_frame_free(&filt_frame);
  279.     if (ret < 0 && ret != AVERROR_EOF) {
  280. //        fprintf(stderr, "Error occurred: %s\n", av_err2str(ret));
  281.         ret = 1;
  282.     }
  283.  
  284.     return ret;
  285. }
  286.  
  287. int main(int argc, char **argv)
  288. {
  289.  
  290.     if (argc != 2) {
  291.         fprintf(stderr, "Usage: %s file | %s\n", argv[0], player);
  292.         return 1;
  293.     }
  294.  
  295.     return extractAudioFromVideo(argv[1]);
  296.  
  297. }
  298.  
  299.  
  300. #ifdef __cplusplus
  301. }
  302. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement