[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