Advertisement
Guest User

FFMpeg + OpenAL

a guest
Jul 24th, 2013
773
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.06 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <Windows.h>
  4.  
  5. EXTERN_C {
  6. #include <libavformat/avformat.h>
  7. #include <libavcodec/avcodec.h>
  8. };
  9.  
  10. #include <AL/al.h>
  11. #include <AL/alc.h>
  12.  
  13.  
  14. #define AL_BUFFER_MAX 6
  15. #define MAX_AUDIOQ_SIZE (10 * 16 * 1024)
  16. #define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio
  17.  
  18. #define FILE_LOCATION "test.wav"
  19.  
  20. //aiff = s16
  21.  
  22. struct AudioFile
  23. {
  24.     AVFormatContext*    fmtCtx;
  25.     AVCodecContext*     codecCtx;
  26.     AVCodec*            codec;
  27.     AVStream*           stream;
  28.  
  29.     unsigned int        frequency;
  30.     unsigned int        channels;
  31.     unsigned int        sampleRate;
  32.     unsigned int        bitRate;
  33.     unsigned int        format;
  34.     ALuint              ALSource;
  35.     ALuint              ALBuffer[AL_BUFFER_MAX];
  36.  
  37.     ALuint              ALCurrentBuffer;
  38. };
  39.  
  40.  
  41. void printAlError(ALenum alError)
  42. {
  43.     printf("[OpenAL] The error is 0x%X (", alError);
  44.     switch(alError) {
  45.     case AL_INVALID_NAME:
  46.         printf("AL_INVALID_NAME");
  47.         break;
  48.  
  49.     case AL_INVALID_ENUM:
  50.         printf("AL_INVALID_ENUM");
  51.         break;
  52.  
  53.     case AL_INVALID_VALUE:
  54.         printf("AL_INVALID_VALUE");
  55.         break;
  56.  
  57.     case AL_INVALID_OPERATION:
  58.         printf("AL_INVALID_OPERATION");
  59.         break;
  60.  
  61.     case AL_OUT_OF_MEMORY:
  62.         printf("AL_OUT_OF_MEMORY");
  63.         break;
  64.  
  65.     default:
  66.         printf("unknown");
  67.     }
  68.     printf(")\n");
  69. }
  70.  
  71. int bufferFrame(AudioFile* af, ALuint bufferID)
  72. {
  73.     int err = 0;
  74.     ALenum alError;
  75.     int frameComplete = 0;
  76.     int encBytesProcessed = 0;
  77.     int dataSize = 0;
  78.     AVPacket *packet = (AVPacket*)malloc(sizeof(AVPacket));
  79.     AVFrame *decodedFrame = NULL;
  80.  
  81.     av_init_packet(packet);
  82.  
  83.     err = av_read_frame(af->fmtCtx, packet);
  84.     if (err)
  85.         printf("[FFMPEG] There was an error reading the frame\n");
  86.    
  87.     while(!frameComplete)
  88.     {
  89.         if(!decodedFrame)
  90.         {
  91.             if(!(decodedFrame = avcodec_alloc_frame()))
  92.                 printf("[FFMPEG] Run out of memory, stop the streaming\n");
  93.         }
  94.         else
  95.         {
  96.             avcodec_get_frame_defaults(decodedFrame);
  97.         }
  98.  
  99.         encBytesProcessed += avcodec_decode_audio4(af->codecCtx, decodedFrame, &frameComplete, packet);
  100.  
  101.         if (frameComplete)
  102.         {
  103.             dataSize = av_samples_get_buffer_size(NULL, af->codecCtx->channels, decodedFrame->nb_samples, af->codecCtx->sample_fmt, 0);
  104.  
  105.             if (af->format == AL_FORMAT_MONO16)
  106.             {
  107.                 alBufferData(bufferID,af->format, *decodedFrame->data, dataSize, decodedFrame->sample_rate/2);
  108.             }
  109.             else
  110.             {
  111.                 alBufferData(bufferID,af->format, decodedFrame->data, dataSize, decodedFrame->sample_rate);
  112.             }
  113.            
  114.  
  115.             av_free_packet(packet);
  116.             av_free(decodedFrame);
  117.  
  118.             if((alError = alGetError()) != AL_NO_ERROR) {
  119.                 printf("[OpenAL] Error while buffering.\n");
  120.                 printAlError(alError);
  121.             }
  122.         }
  123.     }
  124.  
  125.     return 1;
  126. }
  127.  
  128.  
  129. int main()
  130. {
  131.     ALCcontext* ALcontext;
  132.     ALCdevice*  ALdevice;
  133.  
  134.     //Initalise OpenAL
  135.     //==========================================================
  136.     printf("[OpenAL] Opening OpenAL\n");
  137.     ALdevice = alcOpenDevice(NULL);
  138.     if (!ALdevice)
  139.         printf("[OpenAL] Device could not be opened\n");
  140.  
  141.     ALcontext = alcCreateContext(ALdevice, NULL);
  142.     alcMakeContextCurrent(ALcontext);
  143.     if(!ALcontext)
  144.         printf("[OpenAL] Counld not create OpenAL Context\n");
  145.  
  146.     ALCint nummono, numstereo;
  147.     alcGetIntegerv(ALdevice, ALC_MONO_SOURCES, 1, &nummono);
  148.     alcGetIntegerv(ALdevice, ALC_STEREO_SOURCES, 1, &numstereo);
  149.  
  150.     printf("[OpenAL] Audio Device %s\n", alcGetString( NULL, ALC_DEVICE_SPECIFIER ));
  151.     printf("[OpenAL] Max mono sources: %d\n", nummono);
  152.     printf("[OpenAL] Max stereo sources: %d\n", numstereo);
  153.  
  154.     alListener3f(AL_POSITION, 0.0f, 0.0f, 0.0f);
  155.     //==========================================================
  156.  
  157.  
  158.     //Inislaise AVcodec and AVformat
  159.     //==========================================================
  160.     printf("[FFMPEG] registering Codecs\n");
  161.     avcodec_register_all();
  162.     av_register_all();
  163.     //==========================================================
  164.  
  165.  
  166.     //Initalise file
  167.     //==========================================================
  168.     printf("[FFMPEG] Inisalising Audio File\n");
  169.     AudioFile* audioTest = new AudioFile;
  170.     alGenBuffers(AL_BUFFER_MAX, audioTest->ALBuffer);
  171.     alGenSources(1, &audioTest->ALSource);
  172.     alSourcei(audioTest->ALSource, AL_SOURCE_RELATIVE, AL_TRUE);
  173.     alSourcei(audioTest->ALSource, AL_ROLLOFF_FACTOR, 0);
  174.  
  175.     audioTest->fmtCtx = avformat_alloc_context();
  176.     if(!audioTest->fmtCtx)
  177.         printf("[FFMPEG] Could not create AVformat Context\n");
  178.     //==========================================================
  179.  
  180.     //load file
  181.     //==========================================================
  182.     printf("[FFMPEG] loading Audio File %s\n", FILE_LOCATION);
  183.  
  184.     int err;
  185.     //open the actual file 
  186.     err = avformat_open_input(&audioTest->fmtCtx, FILE_LOCATION, NULL, NULL);
  187.     if (err)
  188.         printf("[FFMPEG] avformat_open_input returned an error %d\n", err);
  189.     //obtain infomation about the stream
  190.     err = avformat_find_stream_info(audioTest->fmtCtx, NULL);
  191.     if (err)
  192.         printf("[FFMPEG] avformat_find_stream_info returned an error %d\n", err);
  193.    
  194.     printf("[FFMPEG] Finding Audio Stream\n");
  195.     //obtain the stream
  196.     AVStream* AVaudioStream = NULL;
  197.     for(int i = 0; i < audioTest->fmtCtx->nb_streams; i++)
  198.     {
  199.         if(audioTest->fmtCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
  200.         {
  201.             AVaudioStream = audioTest->fmtCtx->streams[i];
  202.             break;
  203.         }
  204.     }
  205.     //==========================================================
  206.  
  207.     //open the codec
  208.     //=========================================================
  209.     printf("[FFMPEG] Finding and Opening Codec\n");
  210.     audioTest->codecCtx = AVaudioStream->codec;
  211.     audioTest->codec = avcodec_find_decoder(audioTest->codecCtx->codec_id);
  212.  
  213.     err = avcodec_open2(audioTest->codecCtx, audioTest->codec, NULL);
  214.     if(err)
  215.         printf("[FFMPEG] avcodec_open2 returned an error %d\n", err);
  216.     //=========================================================
  217.  
  218.  
  219.     //print info
  220.     //=========================================================
  221.     printf("[FFMPEG] filename = %s\n", audioTest->fmtCtx->filename);
  222.     printf("[FFMPEG] Channels in Stream = %d\n", audioTest->codecCtx->channels);
  223.     printf("[FFMPEG] Codec Type = %s\n", audioTest->codecCtx->codec->long_name);
  224.     printf("[FFMPEG] Sample Rate = %d\n", audioTest->codecCtx->sample_rate);
  225.     printf("[FFMPEG] bit Rate = %d\n", audioTest->codecCtx->bit_rate);
  226.     printf("[FFMPEG] block Alignment = %d\n", audioTest->codecCtx->block_align);
  227.     printf("[FFMPEG] bits Per Sample = %d\n", audioTest->codecCtx->bits_per_raw_sample);
  228.     printf("[FFMPEG] data format = %s\n", av_get_sample_fmt_name(audioTest->codecCtx->sample_fmt));
  229.     //=========================================================
  230.  
  231.     //setting audio format
  232.     //=========================================================
  233.    
  234.     printf("[FFMPEG] setting audio format\n");
  235.     audioTest->sampleRate   = audioTest->codecCtx->sample_rate;
  236.     audioTest->channels     = audioTest->codecCtx->channels;
  237.     audioTest->bitRate      = audioTest->codecCtx->bit_rate; //aparently this is always 16bit
  238.     audioTest->format       = 0;
  239.     audioTest->stream       = AVaudioStream;
  240.  
  241.     switch(audioTest->channels)
  242.     {
  243.     case 1:
  244.         {
  245.             audioTest->format = AL_FORMAT_MONO16;
  246.         }
  247.     case 2:
  248.         {
  249.             audioTest->format = AL_FORMAT_STEREO16;
  250.         }
  251.     case 4:
  252.         {
  253.             if (alIsExtensionPresent("AL_EXT_MCFORMATS"))
  254.             {
  255.                 audioTest->format = alGetEnumValue("AL_FORMAT_QUAD16");
  256.             }
  257.         }
  258.     case 6:
  259.         {
  260.             if (alIsExtensionPresent("AL_EXT_MCFORMATS"))
  261.             {
  262.                 audioTest->format = alGetEnumValue("AL_FORMAT_51CHN16");
  263.             }
  264.         }
  265.     }
  266.     //=========================================================
  267.  
  268.     //stream audio
  269.     //=========================================================
  270.     ALenum alError;
  271.     int bufferProc = 0;
  272.     int totalBProc = 0;
  273.     ALint queuedBuffers = 0, state = 0;
  274.     printf("[Program] Preloading buffers\n");
  275.     for(int i = 0; i < AL_BUFFER_MAX; i++)
  276.     {
  277.         bufferFrame(audioTest, audioTest->ALBuffer[i]);
  278.     }
  279.  
  280.     alSourceQueueBuffers(audioTest->ALSource, AL_BUFFER_MAX, audioTest->ALBuffer);
  281.     alSourcePlay(audioTest->ALSource);
  282.  
  283.     if((alError = alGetError()) != AL_NO_ERROR) {
  284.         printf("[OpenAL] Error starting the stream.\n");
  285.         printAlError(alError);
  286.     }
  287.    
  288.     while(1)
  289.     {
  290.         alGetSourcei(audioTest->ALSource, AL_BUFFERS_PROCESSED, &bufferProc);
  291.  
  292.         totalBProc += bufferProc;
  293.  
  294.         while(bufferProc)
  295.         {
  296.             audioTest->ALCurrentBuffer = 0;
  297.             alSourceUnqueueBuffers(audioTest->ALSource, 1, &audioTest->ALCurrentBuffer);
  298.             bufferFrame(audioTest, audioTest->ALCurrentBuffer);
  299.             alSourceQueueBuffers(audioTest->ALSource, 1, &audioTest->ALCurrentBuffer);
  300.        
  301.             bufferProc--;
  302.         }
  303.         alGetSourcei(audioTest->ALSource, AL_SOURCE_STATE, &state);
  304.         if (state != AL_PLAYING)
  305.         {
  306.             // If there are Buffers in the Source Queue then the Source was starved of audio
  307.             // data, so needs to be restarted (because there is more audio data to play)
  308.             alGetSourcei(audioTest->ALSource, AL_BUFFERS_QUEUED, &queuedBuffers);
  309.             if (queuedBuffers)
  310.             {
  311.                 alSourcePlay(audioTest->ALSource);
  312.             }
  313.             else
  314.             {
  315.                 // Finished playing
  316.                 break;
  317.             }
  318.         }
  319.  
  320.     }
  321.  
  322.     alSourceStop(audioTest->ALSource);
  323.     //=========================================================
  324.  
  325.  
  326.     avcodec_close(audioTest->codecCtx);
  327.     av_free(audioTest->codecCtx);
  328.     av_free(audioTest->fmtCtx);
  329.  
  330.     alcMakeContextCurrent(NULL);
  331.     alcDestroyContext(ALcontext);
  332.     alcCloseDevice(ALdevice);
  333.  
  334.     delete audioTest;
  335.  
  336. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement