DavidNorgren

Untitled

Aug 23rd, 2015
62
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 17.33 KB | None | 0 0
  1. /*
  2.     http://cristobaldobranco.github.io/blog/2015/01/20/compiling-ffmpeg-with-windows-tools/
  3.     Build statically in x86
  4.     ./configure --toolchain=msvc --arch=x86 --prefix=build/ --disable-network
  5.     make
  6.     make install
  7. */
  8.  
  9. #pragma comment (lib, "libavutil.a")
  10. #pragma comment (lib, "libavformat.a")
  11. #pragma comment (lib, "libavcodec.a")
  12. #pragma comment (lib, "libswresample.a")
  13. #pragma comment (lib, "libswscale.a")
  14.  
  15. #define __STDC_CONSTANT_MACROS
  16.  
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <math.h>
  20. #include <vector>
  21. #include <queue>
  22.  
  23. extern "C" {
  24.     #include <libavutil/opt.h>
  25.     #include <libavutil/mathematics.h>
  26.     #include <libavformat/avformat.h>
  27.     #include <libswscale/swscale.h>
  28.     #include <libswresample/swresample.h>
  29. }
  30.  
  31. #define OUT_FILE    "out.mpg" // "out.avi" for avi
  32.  
  33. #define STREAM_FORMAT       "mpeg"  // NULL for avi
  34. #define STREAM_DURATION     15
  35.  
  36. #define STREAM_VIDEO_FRAME_RATE     30
  37. #define STREAM_VIDEO_WIDTH          1280
  38. #define STREAM_VIDEO_HEIGHT         720
  39. #define STREAM_VIDEO_BIT_RATE       400000
  40. #define STREAM_VIDEO_PIXEL_FORMAT   AV_PIX_FMT_YUV420P
  41.  
  42. #define STREAM_AUDIO_BIT_RATE           320000
  43. #define STREAM_AUDIO_SAMPLE_RATE        44100
  44. #define STREAM_AUDIO_SAMPLE_FORMAT      AV_SAMPLE_FMT_S16 // AV_SAMPLE_FMT_FLTP  for avi
  45. #define STREAM_AUDIO_SAMPLE_TYPE        int16_t // float for avi
  46. #define STREAM_AUDIO_SAMPLE_MAX         SHRT_MAX // 1 for avi
  47. #define STREAM_AUDIO_SAMPLE_MIN         SHRT_MIN // -1 for avi
  48. #define STREAM_AUDIO_CHANNEL_LAYOUT     AV_CH_LAYOUT_STEREO
  49. #define STREAM_AUDIO_CHANNELS           2
  50.  
  51. using namespace std;
  52.  
  53. void die(const char *msg) {
  54.     fprintf(stderr, "%s\n", msg);
  55.     exit(1);
  56. }
  57.  
  58.  
  59.  
  60. // A file (tested with .mp3, .wav, .ogg, .flac, .wma, .m4a)
  61.  
  62. typedef struct File {
  63.  
  64.     vector<AVFrame*> frames;
  65.  
  66.     File(char* filename);
  67.     ~File();
  68.  
  69. } File;
  70.  
  71.  
  72.  
  73. // A sound
  74.  
  75. typedef struct Sound {
  76.  
  77.     File* file;
  78.     uint64_t play, start, end;
  79.     double volume;
  80.  
  81.     Sound(File* file, double play, double volume);
  82.  
  83. } Sound;
  84.  
  85.  
  86.  
  87. // Media file output
  88. AVFormatContext *outContext;
  89.  
  90. // Video
  91. AVStream *videoStream;
  92. AVCodec *videoCodec;
  93. AVCodecContext *videoCodecContext;
  94. AVFrame *videoFrame;
  95. AVRational videoTimeBase;
  96. uint64_t videoFrameNum;
  97. SwsContext *videoSwsContext;
  98.  
  99. // Audio
  100. AVStream *audioStream;
  101. AVCodec *audioCodec;
  102. AVCodecContext *audioCodecContext;
  103. AVRational audioTimeBase;
  104. uint64_t audioFrameNum;
  105. vector<Sound*> sounds;
  106.  
  107.  
  108.  
  109. // Video
  110.  
  111. void videoInit() {
  112.  
  113.     // Find encoder
  114.     videoCodec = avcodec_find_encoder(outContext->oformat->video_codec);
  115.     if (!videoCodec)
  116.         die("Could not find video encoder!");
  117.  
  118.  
  119.     // Start stream
  120.     videoStream = avformat_new_stream(outContext, videoCodec);
  121.     if (!videoStream)
  122.         die("Could not allocate video stream!");
  123.     videoCodecContext = videoStream->codec;
  124.     videoStream->id = 0;
  125.  
  126.    
  127.     // Setup
  128.     videoCodecContext->codec_id = outContext->oformat->video_codec;
  129.     videoCodecContext->bit_rate = STREAM_VIDEO_BIT_RATE;
  130.     videoCodecContext->width = STREAM_VIDEO_WIDTH;
  131.     videoCodecContext->height = STREAM_VIDEO_HEIGHT;
  132.     videoCodecContext->time_base = { 1, STREAM_VIDEO_FRAME_RATE };
  133.     videoCodecContext->pix_fmt = STREAM_VIDEO_PIXEL_FORMAT;
  134.     videoCodecContext->gop_size = 12; // Emit one intra frame every twelve frames at most
  135.     videoCodecContext->mb_decision = 2;
  136.  
  137.     if (outContext->oformat->flags & AVFMT_GLOBALHEADER)
  138.         videoCodecContext->flags |= CODEC_FLAG_GLOBAL_HEADER;
  139.  
  140.    
  141.     // Open the codec
  142.     if (avcodec_open2(videoCodecContext, videoCodec, NULL) < 0)
  143.         die("Could not open video codec");
  144.  
  145.  
  146.     // Allocate and init a re-usable frame
  147.     videoFrame = av_frame_alloc();
  148.     if (!videoFrame)
  149.         die("Could not allocate video frame");
  150.  
  151.     videoFrame->pts = 0;
  152.     videoFrame->format = STREAM_VIDEO_PIXEL_FORMAT;
  153.     videoFrame->width = STREAM_VIDEO_WIDTH;
  154.     videoFrame->height = STREAM_VIDEO_HEIGHT;
  155.  
  156.     if (av_frame_get_buffer(videoFrame, 24) < 0)
  157.         die("Could not allocate memory for video frame");
  158.  
  159.  
  160.     // Scaling context
  161.     videoSwsContext = sws_getContext(STREAM_VIDEO_WIDTH, STREAM_VIDEO_HEIGHT, AV_PIX_FMT_RGB24,
  162.                                      STREAM_VIDEO_WIDTH, STREAM_VIDEO_HEIGHT, STREAM_VIDEO_PIXEL_FORMAT,
  163.                                      SWS_BILINEAR, NULL, NULL, NULL);
  164.     if (!videoSwsContext)
  165.         die("Could not initialize the conversion context");
  166.  
  167. }
  168.  
  169. // Frame
  170.  
  171. void getImage(uint8_t *data) {
  172.     for (int y = 0; y < STREAM_VIDEO_HEIGHT; y++) {
  173.         for (int x = 0; x < STREAM_VIDEO_WIDTH; x++) {
  174.             int pos = (y * STREAM_VIDEO_WIDTH + x);
  175.             data[pos * 3] = x + y + videoFrameNum * 3;          // R
  176.             data[pos * 3 + 1] = 128 + y + videoFrameNum * 2;    // G
  177.             data[pos * 3 + 2] = 64 + x + videoFrameNum * 5;     // B
  178.         }
  179.     }
  180. }
  181.  
  182. bool videoWrite() {
  183.  
  184.     // Check if done
  185.     if (av_compare_ts(videoFrameNum, videoCodecContext->time_base, STREAM_DURATION, { 1, 1 }) >= 0)
  186.         return true;
  187.  
  188.  
  189.     // Convert
  190.     uint8_t* data = new uint8_t[STREAM_VIDEO_WIDTH * STREAM_VIDEO_HEIGHT * 3];
  191.     uint8_t* inData[1] = { data }; // RGB24 have one plane
  192.     int inLinesize[1] = { 3 * STREAM_VIDEO_WIDTH }; // RGB stride
  193.  
  194.     getImage(data);
  195.     sws_scale(videoSwsContext, inData, inLinesize, 0, STREAM_VIDEO_HEIGHT, videoFrame->data, videoFrame->linesize);
  196.     delete data;
  197.  
  198.  
  199.     // Init packet
  200.     int gotPacket;
  201.     AVPacket packet;
  202.     av_init_packet(&packet);
  203.     packet.size = 0;
  204.     packet.data = NULL;
  205.  
  206.  
  207.     // Encode the image
  208.     videoFrame->pts = av_rescale_q(videoFrameNum, videoCodecContext->time_base, videoStream->time_base);
  209.     if (avcodec_encode_video2(videoCodecContext, &packet, videoFrame, &gotPacket) < 0)
  210.         die("Error encoding video frame");
  211.  
  212.  
  213.     // Write the compressed frame to the media file.
  214.     if (gotPacket) {
  215.         packet.stream_index = videoStream->index;
  216.  
  217.         if (av_interleaved_write_frame(outContext, &packet) != 0)
  218.             die("Error while writing video frame");
  219.     }
  220.  
  221.  
  222.     // Advance
  223.     videoFrameNum++;
  224.  
  225.  
  226.     // Free
  227.     av_free_packet(&packet);
  228.  
  229.     return false;
  230. }
  231.  
  232. void videoFlush() {
  233.     while (1) {
  234.         int gotPacket;
  235.         AVPacket flushPacket;
  236.         av_init_packet(&flushPacket);
  237.         flushPacket.data = NULL;
  238.         flushPacket.size = 0;
  239.  
  240.         if (avcodec_encode_video2(videoCodecContext, &flushPacket, NULL, &gotPacket) < 0)
  241.             die("Error encoding audio frame");
  242.  
  243.         if (gotPacket) {
  244.             flushPacket.stream_index = videoStream->index;
  245.             printf("Video packet of size %d flushed!\n ", flushPacket.size);
  246.  
  247.             if (av_interleaved_write_frame(outContext, &flushPacket) != 0)
  248.                 die("Error while writing video frame");
  249.         } else
  250.             break;
  251.     }
  252. }
  253.  
  254. // Close
  255.  
  256. void videoClose() {
  257.     avcodec_close(videoCodecContext);
  258.     av_frame_free(&videoFrame);
  259.     sws_freeContext(videoSwsContext);
  260. }
  261.  
  262.  
  263.  
  264. // Audio
  265.  
  266. void audioInit() {
  267.  
  268.     // Find encoder
  269.     audioCodec = avcodec_find_encoder(outContext->oformat->audio_codec);
  270.     if (!audioCodec)
  271.         die("Could not find audio encoder!");
  272.  
  273.  
  274.     // Start stream
  275.     audioStream = avformat_new_stream(outContext, audioCodec);
  276.     if (!audioStream)
  277.         die("Could not allocate audio stream!");
  278.  
  279.     audioCodecContext = audioStream->codec;
  280.     audioStream->id = 1;
  281.  
  282.     // Setup
  283.     audioCodecContext->sample_fmt = STREAM_AUDIO_SAMPLE_FORMAT;
  284.     audioCodecContext->sample_rate = STREAM_AUDIO_SAMPLE_RATE;
  285.     audioCodecContext->bit_rate = STREAM_AUDIO_BIT_RATE;
  286.     audioCodecContext->channels = STREAM_AUDIO_CHANNELS;
  287.     audioCodecContext->channel_layout = STREAM_AUDIO_CHANNEL_LAYOUT;
  288.  
  289.     if (outContext->oformat->flags & AVFMT_GLOBALHEADER)
  290.         audioCodecContext->flags |= CODEC_FLAG_GLOBAL_HEADER;
  291.  
  292.  
  293.     // Open the codec
  294.     if (avcodec_open2(audioCodecContext, audioCodec, NULL) < 0)
  295.         die("Could not open audio codec");
  296.  
  297. }
  298.  
  299. // Frame
  300.  
  301. bool audioWrite() {
  302.  
  303.     if (av_compare_ts(audioFrameNum, audioTimeBase, STREAM_DURATION, { 1, 1 }) >= 0)
  304.         return true;
  305.  
  306.  
  307.     // Allocate frame
  308.     AVFrame *frame = av_frame_alloc();
  309.     if (!frame)
  310.         die("Could not allocate audio frame");
  311.  
  312.     frame->nb_samples = audioCodecContext->frame_size;
  313.     frame->format = STREAM_AUDIO_SAMPLE_FORMAT;
  314.     frame->channel_layout = STREAM_AUDIO_CHANNEL_LAYOUT;
  315.     frame->channels = STREAM_AUDIO_CHANNELS;
  316.     frame->sample_rate = STREAM_AUDIO_SAMPLE_RATE;
  317.  
  318.     if (av_frame_get_buffer(frame, 0) < 0)
  319.         die("Could not get buffer for frame");
  320.  
  321.     if (av_frame_make_writable(frame) < 0)
  322.         die("Could not make frame writable");
  323.  
  324.  
  325.     // Find sounds
  326.     vector<Sound*> frameSounds;
  327.     for (unsigned int i = 0; i < sounds.size(); i++)
  328.         if (audioFrameNum >= sounds[i]->play &&  audioFrameNum < sounds[i]->play + sounds[i]->file->frames.size())
  329.             frameSounds.push_back(sounds[i]);
  330.  
  331.  
  332.     // Write to frame (mix sounds)
  333.     int dataSize = sizeof(STREAM_AUDIO_SAMPLE_TYPE);
  334.     int isPlanar = av_sample_fmt_is_planar(STREAM_AUDIO_SAMPLE_FORMAT);
  335.  
  336.     for (int c = 0; c < 1 + isPlanar; c++) {
  337.         for (int i = 0; i < frame->linesize[0]; i += dataSize) {
  338.             STREAM_AUDIO_SAMPLE_TYPE dstVal = 0; // 0=silence
  339.  
  340.             for (unsigned int j = 0; j < frameSounds.size(); j++) {
  341.                 STREAM_AUDIO_SAMPLE_TYPE srcVal;
  342.                 memcpy(&srcVal, &frameSounds[j]->file->frames[audioFrameNum - frameSounds[j]->play]->data[c][i], dataSize);
  343.  
  344.                 // Clamp audio
  345.                 double tmp = (double)dstVal + (double)(srcVal * frameSounds[j]->volume);
  346.                 if (tmp > STREAM_AUDIO_SAMPLE_MAX)
  347.                     tmp = STREAM_AUDIO_SAMPLE_MAX;
  348.                 if (tmp < STREAM_AUDIO_SAMPLE_MIN)
  349.                     tmp = STREAM_AUDIO_SAMPLE_MIN;
  350.                 dstVal = tmp;
  351.             }
  352.  
  353.             memcpy(&frame->data[c][i], &dstVal, dataSize);
  354.         }
  355.     }
  356.  
  357.     frame->pts = av_rescale_q(audioFrameNum, audioTimeBase, audioCodecContext->time_base);
  358.  
  359.  
  360.     // Allocate packet
  361.     int gotPacket;
  362.     AVPacket outPacket;
  363.     av_init_packet(&outPacket);
  364.     outPacket.data = NULL;
  365.     outPacket.size = 0;
  366.  
  367.  
  368.     // Encode
  369.     if (avcodec_encode_audio2(audioCodecContext, &outPacket, frame, &gotPacket) < 0)
  370.         die("Error encoding audio frame");
  371.  
  372.  
  373.     // Write to file
  374.     if (gotPacket) {
  375.         av_packet_rescale_ts(&outPacket, audioCodecContext->time_base, audioStream->time_base);
  376.         outPacket.stream_index = audioStream->index;
  377.  
  378.         if (av_interleaved_write_frame(outContext, &outPacket) != 0)
  379.             die("Error while writing audio frame");
  380.     }
  381.  
  382.  
  383.     // Free
  384.     av_frame_free(&frame);
  385.     av_free_packet(&outPacket);
  386.  
  387.  
  388.     // Advance
  389.     audioFrameNum++;
  390.  
  391.     return false;
  392.  
  393. }
  394.  
  395.  
  396. // Flush
  397.  
  398. void audioFlush() {
  399.     while (1) {
  400.         int gotPacket;
  401.         AVPacket flushPacket;
  402.         av_init_packet(&flushPacket);
  403.         flushPacket.data = NULL;
  404.         flushPacket.size = 0;
  405.  
  406.         if (avcodec_encode_audio2(audioCodecContext, &flushPacket, NULL, &gotPacket) < 0)
  407.             die("Error encoding audio frame");
  408.  
  409.         if (gotPacket) {
  410.             flushPacket.stream_index = audioStream->index;
  411.             printf("Audio packet of size %d flushed!\n ", flushPacket.size);
  412.  
  413.             if (av_interleaved_write_frame(outContext, &flushPacket) != 0)
  414.                 die("Error while writing audio frame");
  415.         } else
  416.             break;
  417.     }
  418. }
  419.  
  420. // Close
  421.  
  422. void audioClose() {
  423.     avcodec_close(audioCodecContext);
  424. }
  425.  
  426.  
  427. // File functions
  428.  
  429. File::File(char* filename) {
  430.  
  431.     AVFormatContext *formatContext;
  432.     AVCodecContext *codecContext;
  433.  
  434.     // Create contex
  435.     formatContext = avformat_alloc_context();
  436.     if (avformat_open_input(&formatContext, filename, NULL, NULL)<0)
  437.         die("Could not open file");
  438.  
  439.  
  440.     // Find info
  441.     if (avformat_find_stream_info(formatContext, 0)<0)
  442.         die("Could not find file info");
  443.  
  444.     av_dump_format(formatContext, 0, filename, false);
  445.  
  446.  
  447.     // Find audio stream
  448.     AVCodec *codec;
  449.     int streamId = av_find_best_stream(formatContext, AVMEDIA_TYPE_AUDIO, -1, -1, &codec, 0);
  450.     if (streamId < 0)
  451.         die("Could not find Audio Stream");
  452.  
  453.     codecContext = avcodec_alloc_context3(codec);
  454.     avcodec_copy_context(codecContext, formatContext->streams[streamId]->codec);
  455.  
  456.  
  457.     // Open codec
  458.     if (avcodec_open2(codecContext, codec, 0)<0)
  459.         die("Codec cannot be found");
  460.  
  461.  
  462.     // Set up resample context
  463.     SwrContext *swrContext = swr_alloc();
  464.     if (!swrContext)
  465.         die("Failed to alloc swr context");
  466.  
  467.     av_opt_set_int(swrContext, "in_channel_count", codecContext->channels, 0);
  468.     av_opt_set_int(swrContext, "in_channel_layout", codecContext->channel_layout, 0);
  469.     av_opt_set_int(swrContext, "in_sample_rate", codecContext->sample_rate, 0);
  470.     av_opt_set_sample_fmt(swrContext, "in_sample_fmt", codecContext->sample_fmt, 0);
  471.  
  472.     av_opt_set_int(swrContext, "out_channel_count", STREAM_AUDIO_CHANNELS, 0);
  473.     av_opt_set_int(swrContext, "out_channel_layout", STREAM_AUDIO_CHANNEL_LAYOUT, 0);
  474.     av_opt_set_int(swrContext, "out_sample_rate", STREAM_AUDIO_SAMPLE_RATE, 0);
  475.     av_opt_set_sample_fmt(swrContext, "out_sample_fmt", STREAM_AUDIO_SAMPLE_FORMAT, 0);
  476.  
  477.     if (swr_init(swrContext))
  478.         die("Failed to init swr context");
  479.  
  480.  
  481.     // Allocate re-usable frame
  482.     AVFrame *frameDecoded = av_frame_alloc();
  483.     if (!frameDecoded)
  484.         die("Could not allocate audio frame");
  485.  
  486.     frameDecoded->format = codecContext->sample_fmt;
  487.     frameDecoded->channel_layout = codecContext->channel_layout;
  488.     frameDecoded->channels = codecContext->channels;
  489.     frameDecoded->sample_rate = codecContext->sample_rate;
  490.  
  491.  
  492.     // Load frames
  493.     AVPacket inPacket;
  494.     av_init_packet(&inPacket);
  495.     inPacket.data = NULL;
  496.     inPacket.size = 0;
  497.  
  498.     int gotFrame, samples = 0;
  499.  
  500.     while (av_read_frame(formatContext, &inPacket) >= 0) {
  501.  
  502.         if (inPacket.stream_index == streamId) {
  503.  
  504.             if (avcodec_decode_audio4(codecContext, frameDecoded, &gotFrame, &inPacket) < 0)
  505.                 die("Could not decode packet");
  506.  
  507.             if (gotFrame) {
  508.  
  509.                 // Begin conversion
  510.                 if (swr_convert(swrContext, NULL, 0, (const uint8_t **)frameDecoded->data, frameDecoded->nb_samples) < 0)
  511.                     die("Could not convert");
  512.  
  513.                 while (swr_get_out_samples(swrContext, 0) >= audioCodecContext->frame_size) {
  514.  
  515.                     // Allocate data
  516.                     uint8_t **convertedData = NULL;
  517.  
  518.                     if (av_samples_alloc_array_and_samples(&convertedData, NULL, STREAM_AUDIO_CHANNELS, audioCodecContext->frame_size, STREAM_AUDIO_SAMPLE_FORMAT, 0) < 0)
  519.                         die("Could not allocate samples");
  520.  
  521.  
  522.                     // Allocate frame
  523.                     AVFrame *frameConverted = av_frame_alloc();
  524.                     if (!frameConverted)
  525.                         die("Could not allocate audio frame");
  526.  
  527.                     frameConverted->nb_samples = audioCodecContext->frame_size;
  528.                     frameConverted->format = STREAM_AUDIO_SAMPLE_FORMAT;
  529.                     frameConverted->channel_layout = STREAM_AUDIO_CHANNEL_LAYOUT;
  530.                     frameConverted->channels = STREAM_AUDIO_CHANNELS;
  531.                     frameConverted->sample_rate = STREAM_AUDIO_SAMPLE_RATE;
  532.  
  533.  
  534.                     // Convert
  535.                     int out = swr_convert(swrContext, convertedData, frameConverted->nb_samples, NULL, 0);
  536.                     if (out < 0)
  537.                         die("Could not convert");
  538.  
  539.  
  540.                     // Calculate buffer size
  541.                     size_t bufferSize = av_samples_get_buffer_size(NULL, STREAM_AUDIO_CHANNELS, frameConverted->nb_samples, STREAM_AUDIO_SAMPLE_FORMAT, 0);
  542.                     if (bufferSize < 0)
  543.                         die("Invalid buffer size");
  544.  
  545.  
  546.                     // Fill frame
  547.                     if (avcodec_fill_audio_frame(frameConverted, STREAM_AUDIO_CHANNELS, STREAM_AUDIO_SAMPLE_FORMAT, convertedData[0], bufferSize, 0) < 0)
  548.                         die("Could not fill frame");
  549.  
  550.  
  551.                     // Store away
  552.                     frames.push_back(frameConverted);
  553.  
  554.                 }
  555.             }
  556.         }
  557.     }
  558.  
  559.     printf("This file generated %d packets\n\n", frames.size());
  560.  
  561.     // Clean up
  562.     av_frame_free(&frameDecoded);
  563.     av_free_packet(&inPacket);
  564.     swr_free(&swrContext);
  565.     avcodec_close(codecContext);
  566. }
  567.  
  568. File::~File() {
  569.     for (unsigned int i = 0; i < frames.size(); i++)
  570.         av_frame_free(&frames[i]);
  571. }
  572.  
  573.  
  574. // Sound functions
  575.  
  576. Sound::Sound(File* file, double play, double volume) {
  577.     this->file = file;
  578.     this->play = av_rescale_q(play * 1000, { 1, 1000 }, audioTimeBase); // Seconds to frame number
  579.     this->volume = volume;
  580.  
  581.     printf("Sound created starting at %gs (frame %d)...\n", play, this->play);
  582. }
  583.  
  584.  
  585. // Main program
  586.  
  587. int main() {
  588.  
  589.     // Initialize libavcodec, and register all codecs and formats.
  590.     av_register_all();
  591.  
  592.  
  593.     // Allocate the output media context
  594.     avformat_alloc_output_context2(&outContext, NULL, STREAM_FORMAT, &OUT_FILE[0]);
  595.     if (!outContext)
  596.         die("Could not allocate output  context");
  597.  
  598.  
  599.     // Add the audio and video streams using the default format codecs
  600.     // and initialize the codecs.
  601.     videoInit();
  602.     audioInit();
  603.  
  604.     av_dump_format(outContext, 0, &OUT_FILE[0], 1);
  605.  
  606.  
  607.     // Open the output file
  608.     if (avio_open(&outContext->pb, &OUT_FILE[0], AVIO_FLAG_WRITE) < 0)
  609.         die("Could not open");
  610.  
  611.     videoFrameNum = 0;
  612.     videoTimeBase = videoCodecContext->time_base;
  613.     audioFrameNum = 0;
  614.     audioTimeBase = { audioCodecContext->frame_size, STREAM_AUDIO_SAMPLE_RATE };
  615.  
  616.  
  617.     // Write the stream header, if any.
  618.     if (avformat_write_header(outContext, NULL) < 0)
  619.         die("Error occurred when opening output file");
  620.  
  621.  
  622.     // Load files
  623.     File* song = new File("sounds/frozenparadise.flac");
  624.     File* chicken = new File("sounds/chicken.ogg");
  625.     File* fart = new File("sounds/fart.mp3");
  626.  
  627.  
  628.     // Add sounds
  629.     sounds.push_back(new Sound(song, 0, 0.25));
  630.     sounds.push_back(new Sound(fart, 0.9, 1));
  631.     sounds.push_back(new Sound(fart, 1.85, 1));
  632.     sounds.push_back(new Sound(fart, 2.35, 1));
  633.     sounds.push_back(new Sound(fart, 2.95, 1));
  634.     sounds.push_back(new Sound(chicken, 4, 2));
  635.     sounds.push_back(new Sound(chicken, 8, 0.5));
  636.     sounds.push_back(new Sound(fart, 10, 10));
  637.  
  638.  
  639.     // Write interleaved frames
  640.     printf("Writing frames\n");
  641.  
  642.     bool videoDone, audioDone;
  643.     videoDone = audioDone = false;
  644.  
  645.     while (!videoDone || !audioDone) {
  646.         if (!videoDone && (audioDone || av_compare_ts(videoFrameNum, videoTimeBase, audioFrameNum, audioTimeBase) <= 0))
  647.             videoDone = videoWrite();
  648.         else
  649.             audioDone = audioWrite();
  650.         printf(".");
  651.     }
  652.  
  653.     videoFlush();
  654.     audioFlush();
  655.  
  656.  
  657.     // Write the trailer
  658.     av_write_trailer(outContext);
  659.  
  660.  
  661.     // Close each codec.
  662.     videoClose();
  663.     audioClose();
  664.  
  665.  
  666.     // Close the output file.
  667.     avio_close(outContext->pb);
  668.  
  669.  
  670.     // Free the stream
  671.     avformat_free_context(outContext);
  672.  
  673.  
  674.     printf("All done!\n");
  675.     system("pause");
  676.  
  677.     return 0;
  678. }
Advertisement
Add Comment
Please, Sign In to add comment