[Libav-user] ffmpeg open AL
Dmitry Adjiev
adjiev.dmitry at gmail.com
Sun Nov 9 13:25:56 CET 2014
2014-11-06 5:34 GMT+03:00 Dmitry Adjiev <adjiev.dmitry at gmail.com>:
> Hello.
> This code plays file too fast as I understood ...
> I had this done from internet, I just made some changes for actual ffmpeg
> version
>
> /*
> * ffmpeg/libav audio decode and playback using openal
> *
> *
> * sources of inspiration:
> *
> http://blinkingblip.wordpress.com/2011/10/08/decoding-and-playing-an-audio-stream-using-libavcodec-libavformat-and-libao/
> *
> http://git.libav.org/?p=libav.git;a=blob;f=libavcodec/api-example.c;hb=HEAD
> * http://kcat.strangesoft.net/openal-tutorial.html
> *
> * compile:
> * gcc decode.c -lavformat -lopenal
> *
> * Cheers
> * Xerxes Rånby
> */
>
> #include <stdio.h>
>
> #include <libavcodec/avcodec.h>
> #include <libavformat/avformat.h>
> #include <libavutil/avutil.h>
>
> #include <AL/al.h>
> #include <AL/alc.h>
>
> void die(const char* message)
> {
> fprintf(stderr, "%s\n", message);
> exit(1);
> }
>
> int main(int argc, char* argv[])
> {
> if (argc < 2) {
> die("Please provide the file path as the first argument");
> }
>
> const char* input_filename = argv[1];
>
> // This call is necessarily done once in your app to initialize
> // libavformat to register all the muxers, demuxers and protocols.
> av_register_all();
>
> // A media container
> AVFormatContext* container = 0;
>
> if (avformat_open_input(&container, input_filename, NULL, NULL) < 0) {
> die("Could not open file");
> }
>
> if (avformat_find_stream_info(container, NULL) < 0) {
> die("Could not find file info");
> }
>
> int stream_id = -1;
>
> // To find the first audio stream. This process may not be necessary
> // if you can gurarantee that the container contains only the desired
> // audio stream
> int i;
> for (i = 0; i < container->nb_streams; i++) {
> if (container->streams[i]->codec->codec_type ==
> AVMEDIA_TYPE_AUDIO) {
> stream_id = i;
> break;
> }
> }
>
> if (stream_id == -1) {
> die("Could not find an audio stream");
> }
>
> // Find the apropriate codec and open it
> AVCodecContext* codec_context = container->streams[stream_id]->codec;
> AVCodec* codec = avcodec_find_decoder(codec_context->codec_id);
>
> if (!avcodec_open2(codec_context, codec, NULL) < 0) {
> die("Could not find open the needed codec");
> }
>
> // To initalize openal for playback
> ALCdevice *dev;
> ALCcontext *ctx;
> dev = alcOpenDevice(NULL);
> if(!dev)
> {
> fprintf(stderr, "Oops\n");
> return 1;
> }
> ctx = alcCreateContext(dev, NULL);
> alcMakeContextCurrent(ctx);
> if(!ctx)
> {
> fprintf(stderr, "Oops2\n");
> return 1;
> }
>
> int initBuffer = 1;
> int bufferNumber = 0;
> #define NUM_BUFFERS 3
> #define BUFFER_SIZE 4096
> ALuint source, buffers[NUM_BUFFERS];
> ALuint frequency = 44100;
> ALenum format = AL_FORMAT_STEREO16;
>
> alGenBuffers(NUM_BUFFERS, buffers);
> alGenSources(1, &source);
> if(alGetError() != AL_NO_ERROR)
> {
> fprintf(stderr, "Error generating :(\n");
> return 1;
> }
>
> // libav
> AVPacket packet;
> AVFrame* decodedFrame;
> decodedFrame=av_frame_alloc();
> int len;
>
> while (1) {
>
> // Read one packet into `packet`
> if (av_read_frame(container, &packet) < 0) {
> break; // End of stream. Done decoding.
> }
>
> if(packet.stream_index!=stream_id) {
> // Skip Video and subtitle packets
> printf("V");
> continue;
> }
> printf("A");
> // Decodes audio data from `packet` into the frame
>
> while( packet.size >0) {
> int finishedFrame=0;
> len = avcodec_decode_audio4(codec_context, decodedFrame,
> &finishedFrame, &packet);
>
> if(len<0) {
> printf("error");
> break; // Error in decoding
> }
>
> if (finishedFrame) {
> // Decoded data is now available in
> // decodedFrame->data[0]
>
> int data_size = av_samples_get_buffer_size(NULL,
> codec_context->channels,
>
> decodedFrame->nb_samples,
>
> codec_context->sample_fmt, 1);
>
> // OpenAL consumes buffers in the background
> // we first need to initialize the OpenAL buffers then
> // start continous playback.
> if(initBuffer) {
> alBufferData(buffers[bufferNumber], format,
> decodedFrame->data[0], data_size, frequency);
> if(alGetError() != AL_NO_ERROR) {
> fprintf(stderr, "Error loading :(\n");
> return 1;
> }
>
> if(bufferNumber==2){
> // all buffers queued
> alSourceQueueBuffers(source, NUM_BUFFERS, buffers);
> // start playback
> alSourcePlay(source);
> if(alGetError() != AL_NO_ERROR) {
> fprintf(stderr, "Error starting :(\n");
> return 1;
> }
> initBuffer=0;
> }
>
> // update buffer number to fill
> bufferNumber=(bufferNumber+1)%3;
> } else {
> // OpenAL is playing in the background.
> // one new frame with audio data is ready
>
> // first wait for openal to release one buffer
> ALuint buffer;
> ALint val;
> do {
> alGetSourcei(source, AL_BUFFERS_PROCESSED, &val);
> } while (val <=0);
>
> // fill and requeue the empty buffer
> alSourceUnqueueBuffers(source, 1, &buffer);
> alBufferData(buffer, format, decodedFrame->data[0],
> data_size, frequency);
> alSourceQueueBuffers(source, 1, &buffer);
> if(alGetError() != AL_NO_ERROR) {
> fprintf(stderr, "Error buffering :(\n");
> return 1;
> }
>
> //Restart openal playback if needed
> alGetSourcei(source, AL_SOURCE_STATE, &val);
> if(val != AL_PLAYING)
> alSourcePlay(source);
> }
> }
>
> //There may be more than one frame of audio data
> //inside the packet.
> packet.size-=len;
> packet.data+=len;
> } // while packet.size > 0
> } // while more packets exist inside container.
>
> avformat_close_input(&container);
>
> // Wait for openal to finish playback of any remaining buffers.
> ALint val;
> do {
> alGetSourcei(source, AL_SOURCE_STATE, &val);
> } while(val == AL_PLAYING);
>
> // Free OpenAL resources
> alDeleteSources(1, &source);
> alDeleteBuffers(NUM_BUFFERS, buffers);
>
> alcMakeContextCurrent(NULL);
> alcDestroyContext(ctx);
> alcCloseDevice(dev);
>
> fprintf(stdout, "Done playing. Exiting...");
>
> return 0;
> }
>
>
> What I do wrong?
> --
> Regards,
> Dmitry
>
It works fine with wav, so I plain to resample any sound to playabple
format and play
--
Regards,
Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://ffmpeg.org/pipermail/libav-user/attachments/20141109/91fd9766/attachment.html>
More information about the Libav-user
mailing list