Advertisement
Guest User

Untitled

a guest
Aug 2nd, 2017
31
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.28 KB | None | 0 0
  1.  
  2. #include <algorithm>
  3. #include <iterator>
  4. #include <stdlib.h>
  5. #include <process.h>
  6.  
  7. extern "C"
  8. {
  9. #include "libavcodec/avcodec.h"
  10. #include "libavdevice/avdevice.h"
  11. #include "libavfilter/avfilter.h"
  12. #include "libavformat/avformat.h"
  13. #include "libavutil/avutil.h"
  14. #include "libavutil/imgutils.h"
  15. #include "libswscale/swscale.h"
  16. #include "libswresample/swresample.h"
  17.  
  18.     AVCodecID aud_codec_id = AV_CODEC_ID_OPUS;
  19.     AVSampleFormat sample_fmt = AV_SAMPLE_FMT_FLT;
  20.  
  21.     AVCodec *aud_codec = NULL;
  22.     AVCodecContext *aud_codec_context = NULL;
  23.     AVFormatContext *outctx;
  24.     AVStream *audio_st;
  25.     AVFrame *aud_frame;
  26.     SwrContext *audio_swr_ctx;
  27.     uint8_t **dst_data = NULL;
  28.     AVRational conv_time_base;
  29.  
  30.     int aud_frame_counter;
  31.     int dst_nb_samples, src_nb_samples, max_dst_nb_samples;;
  32.     int src_rate, dst_rate;
  33.     int dst_nb_channels;
  34.     int dst_linesize;
  35.  
  36.     int initialize(int sample_rate, int per_frame_audio_samples, int audio_bitrate, const char *filename)
  37.     {
  38.         int ret;
  39.  
  40.         avcodec_register_all();
  41.         av_register_all();
  42.  
  43.         ret = avformat_alloc_output_context2(&outctx, NULL, "webm", filename);
  44.  
  45.         if (ret < 0)
  46.             return ret;
  47.  
  48.         aud_codec = avcodec_find_encoder(aud_codec_id);
  49.         avcodec_register(aud_codec);
  50.  
  51.         if (!aud_codec)
  52.             return -1;
  53.  
  54.         // Setup Audio Stream
  55.  
  56.         aud_codec_context = avcodec_alloc_context3(aud_codec);
  57.         if (!aud_codec_context)
  58.             return -1;
  59.  
  60.         /* select other audio parameters supported by the encoder */
  61.         aud_codec_context->bit_rate = audio_bitrate;
  62.         aud_codec_context->sample_rate = sample_rate;
  63.         aud_codec_context->sample_fmt = sample_fmt;
  64.         aud_codec_context->channel_layout = AV_CH_LAYOUT_STEREO;
  65.         aud_codec_context->channels = av_get_channel_layout_nb_channels(aud_codec_context->channel_layout);
  66.  
  67.         aud_codec_context->codec = aud_codec;
  68.         aud_codec_context->codec_id = aud_codec_id;
  69.  
  70.  
  71.         AVRational time_base;
  72.         time_base.num = per_frame_audio_samples;
  73.         time_base.den = aud_codec_context->sample_rate;
  74.         aud_codec_context->time_base = time_base;
  75.  
  76.         ret = avcodec_open2(aud_codec_context, aud_codec, NULL);
  77.  
  78.         if (ret < 0)
  79.             return ret;
  80.  
  81.         outctx->audio_codec = aud_codec;
  82.         outctx->audio_codec_id = aud_codec_id;
  83.  
  84.         audio_st = avformat_new_stream(outctx, aud_codec);
  85.  
  86.         avcodec_parameters_from_context(audio_st->codecpar, aud_codec_context);
  87.  
  88.         conv_time_base.num = aud_codec_context->frame_size;
  89.         conv_time_base.den = aud_codec_context->sample_rate;
  90.  
  91.         // Setup audio frame
  92.         aud_frame = av_frame_alloc();
  93.         aud_frame->nb_samples = aud_codec_context->frame_size;
  94.         aud_frame->format = aud_codec_context->sample_fmt;
  95.         aud_frame->channel_layout = aud_codec_context->channel_layout;
  96.         aud_frame->sample_rate = aud_codec_context->sample_rate;
  97.  
  98.         int buffer_size;
  99.         if (aud_codec_context->frame_size == 0)
  100.         {
  101.             buffer_size = per_frame_audio_samples * 2 * 4;
  102.             aud_frame->nb_samples = per_frame_audio_samples;
  103.         }
  104.         else
  105.         {
  106.             buffer_size = av_samples_get_buffer_size(NULL, aud_codec_context->channels, aud_codec_context->frame_size,
  107.                 aud_codec_context->sample_fmt, 0);
  108.         }
  109.  
  110.         if (av_sample_fmt_is_planar(sample_fmt))
  111.             ret = av_frame_get_buffer(aud_frame, buffer_size / 2);
  112.         else
  113.             ret = av_frame_get_buffer(aud_frame, buffer_size);
  114.  
  115.         if (!aud_frame || ret < 0)
  116.             return ret;
  117.  
  118.         // Setup audio resampler
  119.  
  120.         audio_swr_ctx = swr_alloc();
  121.         if (!audio_swr_ctx)
  122.             return -1;
  123.  
  124.         /* set options */
  125.         av_opt_set_int(audio_swr_ctx, "in_channel_layout", aud_codec_context->channel_layout, 0);
  126.         av_opt_set_int(audio_swr_ctx, "in_sample_rate", sample_rate, 0);
  127.         av_opt_set_int(audio_swr_ctx, "in_frame_size", per_frame_audio_samples, 0);
  128.         av_opt_set_sample_fmt(audio_swr_ctx, "in_sample_fmt", AV_SAMPLE_FMT_FLT, 0);
  129.  
  130.         av_opt_set_int(audio_swr_ctx, "out_channel_layout", aud_codec_context->channel_layout, 0);
  131.         av_opt_set_int(audio_swr_ctx, "out_sample_rate", aud_codec_context->sample_rate, 0);
  132.         av_opt_set_int(audio_swr_ctx, "out_frame_size", aud_codec_context->frame_size, 0);
  133.         av_opt_set_sample_fmt(audio_swr_ctx, "out_sample_fmt", aud_codec_context->sample_fmt, 0);
  134.  
  135.         /* initialize the resampling context */
  136.         if ((ret = swr_init(audio_swr_ctx)) < 0)
  137.         {
  138.             return ret;
  139.         }
  140.  
  141.         dst_rate = aud_codec_context->sample_rate;
  142.         src_rate = sample_rate;
  143.  
  144.         src_nb_samples = per_frame_audio_samples;
  145.         dst_nb_samples = aud_codec_context->frame_size;
  146.  
  147.         max_dst_nb_samples = av_rescale_rnd(src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);
  148.  
  149.         dst_nb_channels = av_get_channel_layout_nb_channels(aud_codec_context->channel_layout);
  150.  
  151.         ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, dst_nb_channels, dst_nb_samples, sample_fmt, 0);
  152.  
  153.         aud_frame_counter = 0;
  154.  
  155.         if (ret < 0)
  156.             return ret;
  157.  
  158.         av_dump_format(outctx, 0, filename, 1);
  159.  
  160.         if (!(outctx->oformat->flags & AVFMT_NOFILE))
  161.         {
  162.             ret = avio_open(&outctx->pb, filename, AVIO_FLAG_WRITE);
  163.             if (ret < 0)
  164.             {
  165.                 return ret;
  166.             }
  167.         }
  168.  
  169.         ret = avformat_write_header(outctx, NULL);
  170.         if (ret < 0)
  171.             return ret;
  172.  
  173.         return 0;
  174.     }
  175.  
  176.     int process_encode_loop(AVFormatContext *local_outctx, AVCodecContext *codec_context, AVStream *stream, AVRational time_base, bool flush)
  177.     {
  178.         int ret;
  179.  
  180.         AVPacket pkt;
  181.         av_init_packet(&pkt);
  182.         pkt.data = NULL;
  183.         pkt.size = 0;
  184.  
  185.         while (true)
  186.         {
  187.             ret = avcodec_receive_packet(codec_context, &pkt);
  188.             if (!ret)
  189.             {
  190.                 pkt.stream_index = stream->index;
  191.                 av_packet_rescale_ts(&pkt, time_base, stream->time_base);
  192.                 av_interleaved_write_frame(local_outctx, &pkt);
  193.  
  194.                 av_packet_unref(&pkt);
  195.             }
  196.  
  197.             if (ret == AVERROR(EAGAIN))
  198.                 break;
  199.             else if (ret == AVERROR_EOF)
  200.                 break;
  201.             else if (ret < 0)
  202.                 return ret;
  203.             else if (flush == false)
  204.                 break;
  205.         }
  206.  
  207.         return 0;
  208.     }
  209.  
  210.     int write_audio_frame(float_t *aud_sample)
  211.     {
  212.         int ret;
  213.         if (dst_nb_samples > max_dst_nb_samples)
  214.         {
  215.             av_free(&aud_frame->data[0]);
  216.             ret = av_samples_alloc(aud_frame->data, &dst_linesize, dst_nb_channels, dst_nb_samples, sample_fmt, 1);
  217.             if (ret < 0)
  218.                 return ret;
  219.  
  220.             max_dst_nb_samples = dst_nb_samples;
  221.         }
  222.  
  223.         ret = swr_convert(audio_swr_ctx, dst_data, dst_nb_samples, (const uint8_t **)&aud_sample, src_nb_samples);
  224.         if (ret < 0)
  225.         {
  226.             return ret;
  227.         }
  228.  
  229.         aud_frame->data[0] = (uint8_t*)dst_data[0];
  230.         aud_frame->extended_data[0] = (uint8_t*)dst_data[0];
  231.  
  232.         aud_frame->pts = aud_frame_counter++;
  233.  
  234.         ret = avcodec_send_frame(aud_codec_context, aud_frame);
  235.  
  236.         ret = process_encode_loop(outctx, aud_codec_context, audio_st, conv_time_base, false);
  237.  
  238.         if (ret < 0)
  239.             return ret;
  240.  
  241.         return 0;
  242.     }
  243.  
  244.     int finish_audio_encoding()
  245.     {
  246.         int ret = avcodec_send_frame(aud_codec_context, NULL);
  247.         if (ret < 0)
  248.             return ret;
  249.  
  250.         ret = process_encode_loop(outctx, aud_codec_context, audio_st, conv_time_base, true);
  251.         if (ret < 0)
  252.             return ret;
  253.  
  254.         av_write_trailer(outctx);
  255.  
  256.         return ret;
  257.     }
  258.  
  259.     void cleanup()
  260.     {
  261.         if (aud_frame)
  262.         {
  263.             av_frame_free(&aud_frame);
  264.         }
  265.         if (outctx)
  266.         {
  267.             for (int i = 0; i < outctx->nb_streams; i++)
  268.                 av_freep(&outctx->streams[i]);
  269.  
  270.             avio_close(outctx->pb);
  271.             av_free(outctx);
  272.         }
  273.  
  274.         if (aud_codec_context)
  275.         {
  276.             avcodec_close(aud_codec_context);
  277.             av_free(aud_codec_context);
  278.         }
  279.     }
  280.  
  281.     void fill_samples(float_t *dst, int nb_samples, int nb_channels, int sample_rate, float_t *t)
  282.     {
  283.         int i, j;
  284.         float_t tincr = 1.0 / sample_rate;
  285.         const float_t c = 2 * M_PI * 440.0;
  286.         /* generate sin tone with 440Hz frequency and duplicated channels */
  287.         for (i = 0; i < nb_samples; i++) {
  288.             *dst = sin(c * *t);
  289.             for (j = 1; j < nb_channels; j++)
  290.                 dst[j] = dst[0];
  291.             dst += nb_channels;
  292.             *t += tincr;
  293.         }
  294.     }
  295.  
  296.     int main()
  297.     {
  298.         int frame_rate = 30;
  299.         int sec = 12;
  300.         int bit_rate = 192000;
  301.         float t = 0;
  302.  
  303.         int src_samples_linesize;
  304.         int src_nb_samples = 1024;
  305.         int src_channels = 2;
  306.         int sample_rate = 48000;
  307.  
  308.         uint8_t **src_data = NULL;
  309.  
  310.         int ret;
  311.  
  312.         initialize(sample_rate, src_nb_samples, bit_rate, "sound_test.webm");
  313.  
  314.         ret = av_samples_alloc_array_and_samples(&src_data, &src_samples_linesize, src_channels,
  315.             src_nb_samples, AV_SAMPLE_FMT_FLT, 0);
  316.  
  317.         for (size_t i = 0; i < frame_rate * sec; i++)
  318.         {
  319.             fill_samples((float *)src_data[0], src_nb_samples, src_channels, sample_rate, &t);
  320.             write_audio_frame((float *)src_data[0]);
  321.         }
  322.         finish_audio_encoding();
  323.  
  324.         cleanup();
  325.  
  326.         return 0;
  327.     }
  328. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement