PDA

View Full Version : QAudioOutput + FFMPEG



Biberbaer
29th August 2011, 14:28
Hey all,
Im currently writing on a video player with Qt and I want to use QAudioOutput from the Multimedia module together with ffmpeg. However after decoding the audio data most of the time I just hear noise, below my code:


void MainWindow::try_with_ffmpeg()
{
av_register_all();

int audioStream = -1;
AVCodecContext *codecContext;
AVCodec *codec;
AVPacket packet;

av_open_input_file(&formatContext, WMV, NULL,0,NULL);
av_find_stream_info(formatContext);
av_dump_format(formatContext, 0, WMV,0);

for( unsigned int i=0; i < formatContext->nb_streams; i++ )
{
if( formatContext->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO )
{
audioStream = i;
break;
}
}
if( audioStream == -1 )
{
qWarning() << "Didnt find audio stream";
return;
}

codecContext = formatContext->streams[audioStream]->codec;

codec = avcodec_find_decoder(codecContext->codec_id);
avcodec_open(codecContext,codec);

med_buffer = (uint8_t*)malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
buffer.open(QBuffer::WriteOnly);

int i=0;

while( av_read_frame(formatContext,&packet) >= 0 )
{
qint64 written=0;
if( packet.stream_index == audioStream )
{
// qDebug() << "reading audio packet";
int len, data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
len = avcodec_decode_audio3(codecContext, (int16_t*)med_buffer, &data_size, &packet);
if( len <= 0 )
qWarning() << "no data read to buffer";
else
{
written = buffer.write((const char*)med_buffer, len);

qDebug()<< "i= " << ++i << "len = " << len << "\twritten =" << written << "\tbuffer.size() =" << buffer.size();
}

if( buffer.size() > 10000000 )
{
qDebug() << "buffer.size()=" << buffer.size();
break;
}

}

}
qDebug() << "bitRate= " << codecContext->bit_rate
<< "\nsampleRate = " << codecContext->sample_rate;
QAudioFormat format;
format.setFrequency(codecContext->sample_rate);
format.setChannels(2);
format.setSampleSize(16);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);

QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
if (!info.isFormatSupported(format)) {
qWarning()<<"raw audio format not supported by backend, cannot play audio.";
format = info.nearestFormat(format);
}

audio = new QAudioOutput(format, this);

connect(audio,SIGNAL(stateChanged(QAudio::State)), SLOT(stateChanged(QAudio::State)));

if( !buffer.open(QBuffer::ReadWrite) )
qWarning() << "Couldnt open Buffer";

qDebug() << "buffer.size()=" << buffer.size();

audio->start(&buffer);
}

If I convert a file with ffmpeg -i bla.ogg -acodec pcm_s16le output.wav to a pcm file, the audio stream is played correctly, however, if I use another codec audio fails.

Any Ideas?

Biberbaer
30th August 2011, 15:22
Ok solved the problem by myself:


void MainWindow::try_with_ffmpeg()
{
av_register_all();

int audioStream = -1;
AVCodecContext *codecContext;
AVCodec *codec;
AVPacket packet;

av_open_input_file(&formatContext, WMV, NULL,0,NULL);
av_find_stream_info(formatContext);
av_dump_format(formatContext, 0, WMV,0);

for( unsigned int i=0; i < formatContext->nb_streams; i++ )
{
if( formatContext->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO )
{
audioStream = i;
break;
}
}
if( audioStream == -1 )
{
qWarning() << "Didnt find audio stream";
return;
}

codecContext = formatContext->streams[audioStream]->codec;

codec = avcodec_find_decoder(codecContext->codec_id);
avcodec_open(codecContext,codec);

med_buffer = (uint8_t*)malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
buffer.open(QBuffer::WriteOnly);

while( av_read_frame(formatContext,&packet) >= 0 )
{
qint64 written=0;
if( packet.stream_index == audioStream )
{
qDebug() << "size= " << packet.size;
while(packet.size > 0)
{
int len, data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
//decode
len = avcodec_decode_audio3(codecContext, (int16_t*)med_buffer, &data_size, &packet);
if( len <= 0 )
qWarning() << "no data read to buffer";
if( data_size > 0 )
written = buffer.write((const char*)med_buffer, data_size);

packet.size -= len;
packet.data += len;

if( buffer.size() > 10000000 )
{
qDebug() << "buffer.size()=" << buffer.size();
break;
}
}

}

}

QAudioFormat format;
format.setFrequency(codecContext->sample_rate);
format.setChannels(2);
format.setSampleSize(16);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);

QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());

if (!info.isFormatSupported(format)) {
qWarning()<<"raw audio format not supported by backend, cannot play audio.";
format = info.nearestFormat(format);
}

audio = new QAudioOutput(format, this);

connect(audio,SIGNAL(stateChanged(QAudio::State)), SLOT(stateChanged(QAudio::State)));

if( !buffer.open(QBuffer::ReadWrite) )
qWarning() << "Couldnt open Buffer";

qDebug() << "buffer.size()=" << buffer.size();

audio->start(&buffer);
}

rsafir
20th June 2014, 11:25
Hello,

I'm trying to use FFMPEG for an audio converter but i can't import the libraries. Can you attach the code to see how you did it?

Thank you very much!

inforathinam
14th January 2015, 02:46
I would like to create sample audio player...Could you pls send me the full code....



Ok solved the problem by myself:


void MainWindow::try_with_ffmpeg()
{
av_register_all();

int audioStream = -1;
AVCodecContext *codecContext;
AVCodec *codec;
AVPacket packet;

av_open_input_file(&formatContext, WMV, NULL,0,NULL);
av_find_stream_info(formatContext);
av_dump_format(formatContext, 0, WMV,0);

for( unsigned int i=0; i < formatContext->nb_streams; i++ )
{
if( formatContext->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO )
{
audioStream = i;
break;
}
}
if( audioStream == -1 )
{
qWarning() << "Didnt find audio stream";
return;
}

codecContext = formatContext->streams[audioStream]->codec;

codec = avcodec_find_decoder(codecContext->codec_id);
avcodec_open(codecContext,codec);

med_buffer = (uint8_t*)malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
buffer.open(QBuffer::WriteOnly);

while( av_read_frame(formatContext,&packet) >= 0 )
{
qint64 written=0;
if( packet.stream_index == audioStream )
{
qDebug() << "size= " << packet.size;
while(packet.size > 0)
{
int len, data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
//decode
len = avcodec_decode_audio3(codecContext, (int16_t*)med_buffer, &data_size, &packet);
if( len <= 0 )
qWarning() << "no data read to buffer";
if( data_size > 0 )
written = buffer.write((const char*)med_buffer, data_size);

packet.size -= len;
packet.data += len;

if( buffer.size() > 10000000 )
{
qDebug() << "buffer.size()=" << buffer.size();
break;
}
}

}

}

QAudioFormat format;
format.setFrequency(codecContext->sample_rate);
format.setChannels(2);
format.setSampleSize(16);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);

QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());

if (!info.isFormatSupported(format)) {
qWarning()<<"raw audio format not supported by backend, cannot play audio.";
format = info.nearestFormat(format);
}

audio = new QAudioOutput(format, this);

connect(audio,SIGNAL(stateChanged(QAudio::State)), SLOT(stateChanged(QAudio::State)));

if( !buffer.open(QBuffer::ReadWrite) )
qWarning() << "Couldnt open Buffer";

qDebug() << "buffer.size()=" << buffer.size();

audio->start(&buffer);
}

Kryzon
16th January 2015, 18:28
His post is from 2011, it's not likely that he'll read your request.

You may want to look at the following:

- Qt Phonon (4.8) music player example.
http://qt-project.org/doc/qt-4.8/phonon-qmusicplayer.html

- Amarok, an advanced open source audio player built with Qt.
https://amarok.kde.org/en/contribute

- MLT Framework, a multimedia framework that can be used along with Qt.
http://www.mltframework.org/bin/view/MLT/Features
https://github.com/mltframework/BuildOnMe (simple Qt example)
https://github.com/mltframework/shotcut