[Libav-user] ffmpeg open AL

Dmitry Adjiev adjiev.dmitry at gmail.com
Thu Nov 6 03:34:59 CET 2014


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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://ffmpeg.org/pipermail/libav-user/attachments/20141106/bf8db532/attachment.html>


More information about the Libav-user mailing list