1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-01 03:40:16 +02:00

First version using libvlc instead of phonon - added QIODevice support, less debug, no more segfault

This commit is contained in:
dridri
2014-09-30 15:21:29 +02:00
committed by Uwe L. Korn
parent 82acc6b60e
commit 439335ecef
6 changed files with 77 additions and 53 deletions

View File

@@ -716,16 +716,14 @@ AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString
// and Phonon handles the deletion of the
// QNR_IODeviceStream object
ioToKeep.clear();
// TODO d->audioOutput->setAutoDelete( true );
d->audioOutput->setAutoDelete( true );
}
else
{
tLog() << "CASE 2";
/* TODO
d->audioOutput->setCurrentSource( io.data() );
// We handle the deletion via tracking in d->input
d->audioOutput->setAutoDelete( false );
*/
}
}
else
@@ -758,9 +756,7 @@ AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString
d->audioOutput->setCurrentSource( QUrl::fromLocalFile( furl ) );
}
/* TODO
d->audioOutput->setAutoDelete( true );
*/
}
if ( !d->input.isNull() )
@@ -1251,6 +1247,8 @@ AudioEngine::currentTrackTotalTime() const
{
// TODO : This is too hacky. The problem is that I don't know why
// libVLC doesn't report total duration for stream data (imem://)
// But it's not a real problem for playback, since
// EndOfStream is emitted by libVLC itself
if ( d_func()->audioOutput->totalTime() == 0 && d_func()->currentTrack && d_func()->currentTrack->track() ) {
return d_func()->currentTrack->track()->duration() * 1000 + 1000;
}

View File

@@ -44,16 +44,6 @@ private:
Tomahawk::playlistinterface_ptr queue;
AudioOutput* audioOutput;
/*
Phonon::MediaObject* mediaObject;
Phonon::AudioOutput* audioOutput;
Phonon::Path audioPath;
Phonon::Effect* audioEffect;
Phonon::AudioDataOutput* audioDataOutput;
Phonon::Path audioDataPath;
*/
unsigned int timeElapsed;
bool expectStop;

View File

@@ -54,11 +54,15 @@ AudioOutput::AudioOutput( QObject* parent )
: QObject( parent )
, currentState( Stopped )
, muted( false )
, m_autoDelete ( true )
, m_volume( 1.0 )
, m_currentTime( 0 )
, m_totalTime( 0 )
, m_aboutToFinish( false )
, dspPluginCallback( 0 )
, vlcInstance( 0 )
, vlcPlayer( 0 )
, vlcMedia( 0 )
{
tDebug() << Q_FUNC_INFO;
@@ -126,8 +130,6 @@ AudioOutput::AudioOutput( QObject* parent )
libvlc_event_attach( manager, events[ i ], &AudioOutput::vlcEventCallback, this );
}
getchar();
tDebug() << "AudioOutput::AudioOutput OK !\n";
}
@@ -137,6 +139,13 @@ AudioOutput::~AudioOutput()
tDebug() << Q_FUNC_INFO;
}
void
AudioOutput::setAutoDelete ( bool ad )
{
m_autoDelete = ad;
}
void
AudioOutput::setCurrentSource(MediaStream stream)
{
@@ -150,6 +159,15 @@ AudioOutput::setCurrentSource(MediaStream* stream)
setState(Loading);
if ( vlcMedia != 0 ) {
// Ensure playback is stopped, then release media
libvlc_media_player_stop( vlcPlayer );
libvlc_media_release( vlcMedia );
vlcMedia = 0;
}
if ( m_autoDelete && currentStream != 0 ) {
delete currentStream;
}
currentStream = stream;
m_totalTime = 0;
m_currentTime = 0;
@@ -166,16 +184,18 @@ AudioOutput::setCurrentSource(MediaStream* stream)
case MediaStream::Url:
tDebug() << "MediaStream::Url:" << stream->url();
if (stream->url().scheme().isEmpty()) {
if ( stream->url().scheme().isEmpty() ) {
url = "file:///";
if (stream->url().isRelative())
url.append(QFile::encodeName(QDir::currentPath()) + '/');
if ( stream->url().isRelative() ) {
url.append( QFile::encodeName( QDir::currentPath() ) + '/' );
}
}
url += stream->url().toEncoded();
break;
case MediaStream::Stream:
url = QByteArray("imem://");
case MediaStream::IODevice:
url = QByteArray( "imem://" );
break;
}
@@ -199,19 +219,13 @@ AudioOutput::setCurrentSource(MediaStream* stream)
if ( stream->type() == MediaStream::Url ) {
m_totalTime = libvlc_media_get_duration( vlcMedia );
}
else if ( stream->type() == MediaStream::Stream ) {
else if ( stream->type() == MediaStream::Stream || stream->type() == MediaStream::IODevice ) {
libvlc_media_add_option_flag(vlcMedia, "imem-cat=4", libvlc_media_option_trusted);
libvlc_media_add_option_flag(vlcMedia, (QString("imem-data=") + QString::number((quint64)stream)).toUtf8().data(), libvlc_media_option_trusted);
libvlc_media_add_option_flag(vlcMedia, (QString("imem-get=") + QString::number((quint64)&MediaStream::readCallback)).toUtf8().data(), libvlc_media_option_trusted);
libvlc_media_add_option_flag(vlcMedia, (QString("imem-release=") + QString::number((quint64)&MediaStream::readDoneCallback)).toUtf8().data(), libvlc_media_option_trusted);
libvlc_media_add_option_flag(vlcMedia, (QString("imem-seek=") + QString::number((quint64)&MediaStream::seekCallback)).toUtf8().data(), libvlc_media_option_trusted);
}
libvlc_media_add_option(vlcMedia, "audio-filter=dsp");
libvlc_media_add_option(vlcMedia, ":audio-filter=dsp");
libvlc_media_add_option(vlcMedia, "--audio-filter=dsp");
libvlc_media_add_option(vlcMedia, "audio-filter dsp");
libvlc_media_add_option(vlcMedia, ":audio-filter dsp");
libvlc_media_add_option(vlcMedia, "--audio-filter dsp");
m_aboutToFinish = false;
setState(Stopped);
@@ -246,13 +260,16 @@ AudioOutput::currentTime()
void
AudioOutput::setCurrentTime( qint64 time )
{
m_currentTime = time;
// TODO : This is a bit hacky, but m_totalTime is only used to determine
// if we are about to finish
if ( m_totalTime <= 0 ) {
m_totalTime = AudioEngine::instance()->currentTrackTotalTime();
}
m_currentTime = time;
emit tick( time );
tDebug() << "Current time : " << m_currentTime << " / " << m_totalTime;
// tDebug() << "Current time : " << m_currentTime << " / " << m_totalTime;
if ( time < m_totalTime - ABOUT_TO_FINISH_TIME ) {
m_aboutToFinish = false;
@@ -329,27 +346,13 @@ AudioOutput::seek( qint64 milliseconds )
case Buffering:
break;
default:
// Seeking while not being in a playingish state is cached for later.
// TODO m_seekpoint = milliseconds;
return;
}
tDebug() << "AudioOutput:: seeking" << milliseconds << "msec";
libvlc_media_player_set_time ( vlcPlayer, milliseconds );
/*
const qint64 time = currentTime();
const qint64 total = totalTime();
*/
/*
// Reset last tick marker so we emit time even after seeking
if (time < m_lastTick)
m_lastTick = time;
if (time < total - m_prefinishMark)
m_prefinishEmitted = false;
if (time < total - ABOUT_TO_FINISH_TIME)
m_aboutToFinishEmitted = false;
*/
setCurrentTime( milliseconds );
}

View File

@@ -58,6 +58,7 @@ public:
qreal volume();
qint64 currentTime();
qint64 totalTime();
void setAutoDelete ( bool ad );
void setDspCallback( void ( *cb ) ( signed short*, int, int ) );
@@ -82,6 +83,7 @@ private:
AudioState currentState;
MediaStream* currentStream;
bool muted;
bool m_autoDelete;
qreal m_volume;
qint64 m_currentTime;
qint64 m_totalTime;

View File

@@ -22,6 +22,7 @@
#include "utils/Logger.h"
#define BLOCK_SIZE 1048576
static QString s_aeInfoIdentifier = QString( "MEDIASTREAM" );
@@ -29,6 +30,7 @@ static QString s_aeInfoIdentifier = QString( "MEDIASTREAM" );
MediaStream::MediaStream()
: m_type( Unknown )
, m_url( QUrl() )
, m_ioDevice ( 0 )
, m_eos( false )
, m_pos( 0 )
, m_streamSize( 0 )
@@ -46,6 +48,15 @@ MediaStream::MediaStream( const QUrl &url )
}
MediaStream::MediaStream( QIODevice* device )
: m_type(IODevice)
{
tDebug() << Q_FUNC_INFO;
m_ioDevice = device;
}
MediaStream::~MediaStream()
{
tDebug() << Q_FUNC_INFO;
@@ -98,7 +109,7 @@ MediaStream::endOfData()
int
MediaStream::readCallback ( void* data, const char* cookie, int64_t* dts, int64_t* pts, unsigned* flags, size_t* bufferSize, void** buffer )
{
tDebug() << Q_FUNC_INFO;
// tDebug() << Q_FUNC_INFO;
Q_UNUSED(cookie);
Q_UNUSED(dts);
@@ -111,7 +122,16 @@ MediaStream::readCallback ( void* data, const char* cookie, int64_t* dts, int64_
return -1;
}
*bufferSize = that->needData(buffer);
if ( that->m_type == Stream ) {
*bufferSize = that->needData(buffer);
}
else if ( that->m_type == IODevice ) {
QByteArray data = that->m_ioDevice->read(BLOCK_SIZE);
*buffer = new char[data.size()];
memcpy(*buffer, data.data(), data.size());
*bufferSize = data.size();
}
return 0;
}
@@ -121,12 +141,16 @@ MediaStream::readDoneCallback ( void *data, const char *cookie, size_t bufferSiz
{
tDebug() << Q_FUNC_INFO;
Q_UNUSED(data);
Q_UNUSED(cookie);
Q_UNUSED(bufferSize);
// TODO : causes segfault
// delete static_cast<char *>(buffer);
MediaStream* that = static_cast < MediaStream * > ( data );
if ( ( that->m_type == Stream || that->m_type == IODevice ) && buffer != 0 && bufferSize > 0 ) {
// TODO : causes segfault
tDebug() << "buffer : " << buffer;
delete static_cast<char *>(buffer);
}
return 0;
}
@@ -135,14 +159,18 @@ MediaStream::readDoneCallback ( void *data, const char *cookie, size_t bufferSiz
int
MediaStream::seekCallback ( void *data, const uint64_t pos )
{
tDebug() << Q_FUNC_INFO;
// tDebug() << Q_FUNC_INFO;
MediaStream* that = static_cast < MediaStream * > ( data );
if ( static_cast < int64_t > ( pos ) > that->streamSize() ) {
if ( that->m_type == Stream && static_cast < int64_t > ( pos ) > that->streamSize() ) {
return -1;
}
that->m_pos = pos;
if ( that->m_type == IODevice ) {
that->m_ioDevice->seek(pos);
}
return 0;
}

View File

@@ -28,15 +28,17 @@
#include <stdint.h>
#include <QUrl>
#include <QIODevice>
class DLLEXPORT MediaStream
{
public:
enum MediaType { Unknown = -1, Empty = 0, Url = 1, Stream = 2 };
enum MediaType { Unknown = -1, Empty = 0, Url = 1, Stream = 2, IODevice = 3 };
MediaStream();
MediaStream( const QUrl &url );
MediaStream( QIODevice* device );
virtual ~MediaStream();
MediaType type();
@@ -57,6 +59,7 @@ protected:
MediaType m_type;
QUrl m_url;
QIODevice* m_ioDevice;
bool m_eos;
qint64 m_pos;