Advertisement
Guest User

Untitled

a guest
Jul 2nd, 2017
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.05 KB | None | 0 0
  1. #include <algorithm>
  2. #include <iterator>
  3.  
  4. extern "C"
  5. {
  6.  
  7. //#define OGG
  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.     enum InfoCodes
  19.     {
  20.         ENCODED_VIDEO,
  21.         ENCODED_AUDIO,
  22.         ENCODED_AUDIO_AND_VIDEO,
  23.         NOT_ENOUGH_AUDIO_DATA,
  24.     };
  25.  
  26.     enum ErrorCodes
  27.     {
  28.         RES_NOT_MUL_OF_TWO = -1,
  29.         ERROR_FINDING_VID_CODEC = -2,
  30.         ERROR_CONTEXT_CREATION = -3,
  31.         ERROR_CONTEXT_ALLOCATING = -4,
  32.         ERROR_OPENING_VID_CODEC = -5,
  33.         ERROR_OPENING_FILE = -6,
  34.         ERROR_ALLOCATING_FRAME = -7,
  35.         ERROR_ALLOCATING_PIC_BUF = -8,
  36.         ERROR_ENCODING_FRAME_SEND = -9,
  37.         ERROR_ENCODING_FRAME_RECEIVE = -10,
  38.         ERROR_FINDING_AUD_CODEC = -11,
  39.         ERROR_OPENING_AUD_CODEC = -12,
  40.         ERROR_INIT_RESMPL_CONTEXT = -13,
  41.         ERROR_ENCODING_SAMPLES_SEND = -14,
  42.         ERROR_ENCODING_SAMPLES_RECEIVE = -15,
  43.         ERROR_WRITING_HEADER = -16,
  44.         ERROR_INIT_AUDIO_RESPAMLER = -17,
  45.     };
  46.  
  47.     AVCodecID aud_codec_comp_id = AV_CODEC_ID_OPUS;
  48.     AVSampleFormat sample_fmt_comp = AV_SAMPLE_FMT_FLT;
  49.  
  50.     AVCodecID aud_codec_id;
  51.     AVSampleFormat sample_fmt;
  52.  
  53. #ifndef OGG
  54.     char* compressed_cont = "webm";
  55. #endif
  56. #ifdef OGG
  57.     char* compressed_cont = "ogg";
  58. #endif
  59.  
  60.     AVCodec *aud_codec = NULL;
  61.     AVCodecContext *aud_codec_context = NULL;
  62.     AVFormatContext *outctx;
  63.     AVStream *audio_st;
  64.     AVFrame *aud_frame;
  65.     SwrContext *audio_swr_ctx;
  66.  
  67.     int vid_frame_counter, aud_frame_counter;
  68.     int vid_width, vid_height;
  69.  
  70.     char* concat(const char *s1, const char *s2)
  71.     {
  72.         char *result = (char*)malloc(strlen(s1) + strlen(s2) + 1);
  73.  
  74.         strcpy(result, s1);
  75.         strcat(result, s2);
  76.  
  77.         return result;
  78.     }
  79.  
  80.     int setup_audio_codec()
  81.     {
  82.         aud_codec_id = aud_codec_comp_id;
  83.         sample_fmt = sample_fmt_comp;
  84.  
  85.         // Fixup audio codec
  86.         if (aud_codec == NULL)
  87.         {
  88.             aud_codec = avcodec_find_encoder(aud_codec_id);
  89.             avcodec_register(aud_codec);
  90.         }
  91.  
  92.         if (!aud_codec)
  93.             return ERROR_FINDING_AUD_CODEC;
  94.  
  95.         return 0;
  96.     }
  97.  
  98.     int initialize_audio_stream(AVFormatContext *local_outctx, int sample_rate, int per_frame_audio_samples, int audio_bitrate)
  99.     {
  100.         aud_codec_context = avcodec_alloc_context3(aud_codec);
  101.         if (!aud_codec_context)
  102.             return ERROR_CONTEXT_CREATION;
  103.  
  104.         aud_codec_context->bit_rate = audio_bitrate;
  105.         aud_codec_context->sample_rate = sample_rate;
  106.         aud_codec_context->sample_fmt = sample_fmt;
  107.         aud_codec_context->channel_layout = AV_CH_LAYOUT_STEREO;
  108.         aud_codec_context->channels = av_get_channel_layout_nb_channels(aud_codec_context->channel_layout);
  109.         //aud_codec_context->profile = FF_PROFILE_AAC_MAIN;
  110.  
  111.         aud_codec_context->codec = aud_codec;
  112.         aud_codec_context->codec_id = aud_codec_id;
  113.  
  114.         AVRational time_base;
  115.         time_base.num = per_frame_audio_samples;
  116.         time_base.den = aud_codec_context->sample_rate;
  117.         aud_codec_context->time_base = time_base;
  118.  
  119.         int ret = avcodec_open2(aud_codec_context, aud_codec, NULL);
  120.  
  121.         if (ret < 0)
  122.             return ERROR_OPENING_AUD_CODEC;
  123.  
  124.         local_outctx->audio_codec = aud_codec;
  125.         local_outctx->audio_codec_id = aud_codec_id;
  126.  
  127.         audio_st = avformat_new_stream(local_outctx, aud_codec);
  128.  
  129.         audio_st->codecpar->bit_rate = aud_codec_context->bit_rate;
  130.         audio_st->codecpar->sample_rate = aud_codec_context->sample_rate;
  131.         audio_st->codecpar->channels = aud_codec_context->channels;
  132.         audio_st->codecpar->channel_layout = aud_codec_context->channel_layout;
  133.         audio_st->codecpar->codec_id = aud_codec_context->codec_id;
  134.         audio_st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
  135.         audio_st->codecpar->format = aud_codec_context->sample_fmt;
  136.         audio_st->codecpar->frame_size = aud_codec_context->frame_size;
  137.         audio_st->codecpar->block_align = aud_codec_context->block_align;
  138.         audio_st->codecpar->initial_padding = aud_codec_context->initial_padding;
  139.         audio_st->codecpar->extradata = aud_codec_context->extradata;
  140.         audio_st->codecpar->extradata_size = aud_codec_context->extradata_size;
  141.  
  142.         aud_frame = av_frame_alloc();
  143.         aud_frame->nb_samples = aud_codec_context->frame_size;
  144.         aud_frame->format = aud_codec_context->sample_fmt;
  145.         aud_frame->channel_layout = aud_codec_context->channel_layout;
  146.         aud_frame->sample_rate = aud_codec_context->sample_rate;
  147.  
  148.         int buffer_size;
  149.         if (aud_codec_context->frame_size == 0)
  150.         {
  151.             buffer_size = per_frame_audio_samples * 2 * 4;
  152.             aud_frame->nb_samples = per_frame_audio_samples;
  153.         }
  154.         else
  155.         {
  156.             buffer_size = av_samples_get_buffer_size(NULL, aud_codec_context->channels, aud_codec_context->frame_size,
  157.                 aud_codec_context->sample_fmt, 0);
  158.         }
  159.  
  160.         if (av_sample_fmt_is_planar(sample_fmt))
  161.             ret = av_frame_get_buffer(aud_frame, buffer_size / 2);
  162.         else
  163.             ret = av_frame_get_buffer(aud_frame, buffer_size);
  164.  
  165.         if (!aud_frame || ret < 0)
  166.             return ERROR_ALLOCATING_FRAME;
  167.  
  168.         aud_frame_counter = 0;
  169.  
  170.         return 0;
  171.     }
  172.  
  173.     int initialize_audio_only_encoding(int sample_rate, int per_frame_audio_samples, int audio_bitrate, const char *filename)
  174.     {
  175.         int ret;
  176.  
  177.         avcodec_register_all();
  178.         av_register_all();
  179.  
  180.         outctx = avformat_alloc_context();
  181.  
  182.         char* with_dot = concat(filename, ".");
  183.         char* full_filename = concat(with_dot, compressed_cont);
  184.  
  185.         ret = avformat_alloc_output_context2(&outctx, NULL, compressed_cont, full_filename);
  186.  
  187.         free(with_dot);
  188.  
  189.         if (ret < 0)
  190.         {
  191.             free(full_filename);
  192.             return ERROR_CONTEXT_CREATION;
  193.         }
  194.  
  195.         ret = setup_audio_codec();
  196.         if (ret < 0)
  197.             return ret;
  198.  
  199.         // Setup Audio
  200.         ret = initialize_audio_stream(outctx, sample_rate, per_frame_audio_samples, audio_bitrate);
  201.         if (ret < 0)
  202.             return ret;
  203.  
  204.         av_dump_format(outctx, 0, full_filename, 1);
  205.  
  206.         if (!(outctx->oformat->flags & AVFMT_NOFILE))
  207.         {
  208.             if (avio_open(&outctx->pb, full_filename, AVIO_FLAG_WRITE) < 0)
  209.             {
  210.                 free(full_filename);
  211.                 return ERROR_OPENING_FILE;
  212.             }
  213.         }
  214.  
  215.         free(full_filename);
  216.  
  217.         ret = avformat_write_header(outctx, NULL);
  218.         if (ret < 0)
  219.             return ERROR_WRITING_HEADER;
  220.  
  221.         return 0;
  222.     }
  223.  
  224.     int write_interleaved_audio_frame(float_t *aud_sample)
  225.     {
  226.         int ret;
  227.  
  228.         aud_frame->data[0] = (uint8_t*)aud_sample;
  229.         aud_frame->extended_data[0] = (uint8_t*)aud_sample;
  230.  
  231.         aud_frame->pts = aud_frame_counter++;
  232.  
  233.         ret = avcodec_send_frame(aud_codec_context, aud_frame);
  234.  
  235.         AVPacket pkt;
  236.         av_init_packet(&pkt);
  237.         pkt.data = NULL;
  238.         pkt.size = 0;
  239.  
  240.         while (true)
  241.         {
  242.             ret = avcodec_receive_packet(aud_codec_context, &pkt);
  243.             if (!ret)
  244.             {
  245.                 av_packet_rescale_ts(&pkt, aud_codec_context->time_base, audio_st->time_base);
  246.  
  247.                 pkt.stream_index = audio_st->index;
  248.  
  249.                 av_interleaved_write_frame(outctx, &pkt);
  250.  
  251.                 av_packet_unref(&pkt);
  252.             }
  253.             if (ret == AVERROR(EAGAIN))
  254.                 break;
  255.             else if (ret < 0)
  256.                 return ERROR_ENCODING_SAMPLES_RECEIVE;
  257.             else
  258.                 break;
  259.         }
  260.  
  261.         return ENCODED_AUDIO;
  262.     }
  263.  
  264.     int write_audio_frame(float_t *aud_sample)
  265.     {
  266.         int ret;
  267.         aud_frame->data[0] = (uint8_t*)aud_sample;
  268.         aud_frame->extended_data[0] = (uint8_t*)aud_sample;
  269.  
  270.         aud_frame->pts = aud_frame_counter++;
  271.  
  272.         ret = avcodec_send_frame(aud_codec_context, aud_frame);
  273.         if (ret < 0)
  274.             return ERROR_ENCODING_FRAME_SEND;
  275.  
  276.         AVPacket pkt;
  277.         av_init_packet(&pkt);
  278.         pkt.data = NULL;
  279.         pkt.size = 0;
  280.  
  281.         fflush(stdout);
  282.  
  283.         while (true)
  284.         {
  285.             ret = avcodec_receive_packet(aud_codec_context, &pkt);
  286.             if (!ret)
  287.                 if (pkt.pts != AV_NOPTS_VALUE)
  288.                     pkt.pts = av_rescale_q(pkt.pts, aud_codec_context->time_base, audio_st->time_base);
  289.             if (pkt.dts != AV_NOPTS_VALUE)
  290.                 pkt.dts = av_rescale_q(pkt.dts, aud_codec_context->time_base, audio_st->time_base);
  291.             {
  292.  
  293.                 av_write_frame(outctx, &pkt);
  294.                 av_packet_unref(&pkt);
  295.             }
  296.             if (ret == AVERROR(EAGAIN))
  297.                 break;
  298.             else if (ret < 0)
  299.                 return ERROR_ENCODING_FRAME_RECEIVE;
  300.             else
  301.                 break;
  302.         }
  303.  
  304.         return ENCODED_AUDIO;
  305.     }
  306.  
  307.     int finish_audio_encoding()
  308.     {
  309.         AVPacket pkt;
  310.         av_init_packet(&pkt);
  311.         pkt.data = NULL;
  312.         pkt.size = 0;
  313.  
  314.         fflush(stdout);
  315.  
  316.         int ret = avcodec_send_frame(aud_codec_context, NULL);
  317.         if (ret < 0)
  318.             return ERROR_ENCODING_FRAME_SEND;
  319.  
  320.         while (true)
  321.         {
  322.             ret = avcodec_receive_packet(aud_codec_context, &pkt);
  323.             if (!ret)
  324.             {
  325.                 if (pkt.pts != AV_NOPTS_VALUE)
  326.                     pkt.pts = av_rescale_q(pkt.pts, aud_codec_context->time_base, audio_st->time_base);
  327.                 if (pkt.dts != AV_NOPTS_VALUE)
  328.                     pkt.dts = av_rescale_q(pkt.dts, aud_codec_context->time_base, audio_st->time_base);
  329.  
  330.                 av_write_frame(outctx, &pkt);
  331.                 av_packet_unref(&pkt);
  332.             }
  333.             if (ret == -AVERROR(AVERROR_EOF))
  334.                 break;
  335.             else if (ret < 0)
  336.                 return ERROR_ENCODING_FRAME_RECEIVE;
  337.         }
  338.  
  339.         av_write_trailer(outctx);
  340.  
  341.         return 0;
  342.     }
  343.  
  344.     void cleanup()
  345.     {
  346.         if (aud_frame)
  347.         {
  348.             av_frame_free(&aud_frame);
  349.         }
  350.         if (outctx)
  351.         {
  352.             for (int i = 0; i < outctx->nb_streams; i++)
  353.                 av_freep(&outctx->streams[i]);
  354.  
  355.             avio_close(outctx->pb);
  356.             av_free(outctx);
  357.         }
  358.  
  359.         if (aud_codec_context)
  360.         {
  361.             avcodec_close(aud_codec_context);
  362.             av_free(aud_codec_context);
  363.         }
  364.     }
  365.  
  366.     void fill_samples(float_t *dst, int nb_samples, int nb_channels, int sample_rate, float_t *t)
  367.     {
  368.         int i, j;
  369.         float_t tincr = 1.0 / sample_rate;
  370.         const float_t c = 2 * M_PI * 440.0;
  371.  
  372.         for (i = 0; i < nb_samples; i++) {
  373.             *dst = sin(c * *t);
  374.             for (j = 1; j < nb_channels; j++)
  375.                 dst[j] = dst[0];
  376.             dst += nb_channels;
  377.             *t += tincr;
  378.         }
  379.     }
  380.  
  381.     int main()
  382.     {
  383.         int sec = 5;
  384.         int frame_rate = 30;
  385.         float t = 0, tincr = 0, tincr2 = 0;
  386.  
  387.         int src_samples_linesize;
  388.         int src_nb_samples = 960;
  389.         int src_channels = 2;
  390.         int sample_rate = 48000;
  391.  
  392.         uint8_t **src_data = NULL;
  393.  
  394.         int ret;
  395.  
  396.         initialize_audio_only_encoding(48000, src_nb_samples, 192000, "sound_FLT_960");
  397.  
  398.         ret = av_samples_alloc_array_and_samples(&src_data, &src_samples_linesize, src_channels,
  399.             src_nb_samples, AV_SAMPLE_FMT_FLT, 0);
  400.  
  401.         for (size_t i = 0; i < frame_rate * sec; i++)
  402.         {
  403.                 fill_samples((float *)src_data[0], src_nb_samples, src_channels, sample_rate, &t);
  404.                 write_interleaved_audio_frame((float *)src_data[0]);
  405.         }
  406.  
  407.         finish_audio_encoding();
  408.  
  409.         cleanup();
  410.  
  411.         return 0;
  412.     }
  413. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement