QMediaPlayer: GStreamer backend changes for playlist support.

Register type find function to check if unrecognized media is a playlist.
Emit MediaIsPlaylist error and let frontend handle playlists.

Change-Id: Ib17da1c46014ac3c0f2f48b75ea9de2f0428b573
Reviewed-by: Dmytro Poplavskiy <dmytro.poplavskiy@nokia.com>
This commit is contained in:
Lev Zelenskiy
2012-03-05 14:16:06 +10:00
committed by Qt by Nokia
parent 2c034beab5
commit b1eba5e9b2
2 changed files with 69 additions and 14 deletions

View File

@@ -47,6 +47,7 @@
#include "qgstreamervideorendererinterface.h" #include "qgstreamervideorendererinterface.h"
#include "gstvideoconnector.h" #include "gstvideoconnector.h"
#include <private/qgstutils_p.h> #include <private/qgstutils_p.h>
#include <private/playlistfileparser_p.h>
#include <gst/gstvalue.h> #include <gst/gstvalue.h>
#include <gst/base/gstbasesrc.h> #include <gst/base/gstbasesrc.h>
@@ -113,8 +114,12 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent)
m_displayPrerolledFrame(true), m_displayPrerolledFrame(true),
m_sourceType(UnknownSrc), m_sourceType(UnknownSrc),
m_everPlayed(false), m_everPlayed(false),
m_isLiveSource(false) m_isLiveSource(false),
m_isPlaylist(false)
{ {
gboolean result = gst_type_find_register(0, "playlist", GST_RANK_MARGINAL, playlistTypeFindFunction, 0, 0, this, 0);
Q_ASSERT(result == TRUE);
#ifdef USE_PLAYBIN2 #ifdef USE_PLAYBIN2
m_playbin = gst_element_factory_make("playbin2", NULL); m_playbin = gst_element_factory_make("playbin2", NULL);
#endif #endif
@@ -236,6 +241,7 @@ void QGstreamerPlayerSession::loadFromStream(const QNetworkRequest &request, QIO
m_duration = -1; m_duration = -1;
m_lastPosition = 0; m_lastPosition = 0;
m_haveQueueElement = false; m_haveQueueElement = false;
m_isPlaylist = false;
if (m_appSrc) if (m_appSrc)
m_appSrc->deleteLater(); m_appSrc->deleteLater();
@@ -268,6 +274,7 @@ void QGstreamerPlayerSession::loadFromUri(const QNetworkRequest &request)
m_duration = -1; m_duration = -1;
m_lastPosition = 0; m_lastPosition = 0;
m_haveQueueElement = false; m_haveQueueElement = false;
m_isPlaylist = false;
if (m_playbin) { if (m_playbin) {
m_tags.clear(); m_tags.clear();
@@ -794,10 +801,13 @@ bool QGstreamerPlayerSession::play()
if (m_playbin) { if (m_playbin) {
m_pendingState = QMediaPlayer::PlayingState; m_pendingState = QMediaPlayer::PlayingState;
if (gst_element_set_state(m_playbin, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { if (gst_element_set_state(m_playbin, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
if (!m_isPlaylist) {
qWarning() << "GStreamer; Unable to play -" << m_request.url().toString(); qWarning() << "GStreamer; Unable to play -" << m_request.url().toString();
m_pendingState = m_state = QMediaPlayer::StoppedState; m_pendingState = m_state = QMediaPlayer::StoppedState;
emit stateChanged(m_state); emit stateChanged(m_state);
} else {
return true;
}
} else { } else {
resumeVideoProbes(); resumeVideoProbes();
return true; return true;
@@ -818,10 +828,13 @@ bool QGstreamerPlayerSession::pause()
return true; return true;
if (gst_element_set_state(m_playbin, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) { if (gst_element_set_state(m_playbin, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) {
if (!m_isPlaylist) {
qWarning() << "GStreamer; Unable to pause -" << m_request.url().toString(); qWarning() << "GStreamer; Unable to pause -" << m_request.url().toString();
m_pendingState = m_state = QMediaPlayer::StoppedState; m_pendingState = m_state = QMediaPlayer::StoppedState;
emit stateChanged(m_state); emit stateChanged(m_state);
} else {
return true;
}
} else { } else {
resumeVideoProbes(); resumeVideoProbes();
return true; return true;
@@ -1199,6 +1212,8 @@ bool QGstreamerPlayerSession::processBusMessage(const QGstreamerMessage &message
gst_message_parse_warning(gm, &err, &debug); gst_message_parse_warning(gm, &err, &debug);
if (err->domain == GST_STREAM_ERROR && err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND) if (err->domain == GST_STREAM_ERROR && err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND)
emit error(int(QMediaPlayer::FormatError), tr("Cannot play stream of type: <unknown>")); emit error(int(QMediaPlayer::FormatError), tr("Cannot play stream of type: <unknown>"));
// GStreamer shows warning for HTTP playlists
if (!m_isPlaylist)
qWarning() << "Warning:" << QString::fromUtf8(err->message); qWarning() << "Warning:" << QString::fromUtf8(err->message);
g_error_free(err); g_error_free(err);
g_free(debug); g_free(debug);
@@ -1206,6 +1221,11 @@ bool QGstreamerPlayerSession::processBusMessage(const QGstreamerMessage &message
GError *err; GError *err;
gchar *debug; gchar *debug;
gst_message_parse_error(gm, &err, &debug); gst_message_parse_error(gm, &err, &debug);
// remember playlist value,
// it could be set to false after call to processInvalidMedia
bool isPlaylist = m_isPlaylist;
// Nearly all errors map to ResourceError // Nearly all errors map to ResourceError
QMediaPlayer::Error qerror = QMediaPlayer::ResourceError; QMediaPlayer::Error qerror = QMediaPlayer::ResourceError;
if (err->domain == GST_STREAM_ERROR if (err->domain == GST_STREAM_ERROR
@@ -1214,7 +1234,9 @@ bool QGstreamerPlayerSession::processBusMessage(const QGstreamerMessage &message
qerror = QMediaPlayer::AccessDeniedError; qerror = QMediaPlayer::AccessDeniedError;
} }
processInvalidMedia(qerror, QString::fromUtf8(err->message)); processInvalidMedia(qerror, QString::fromUtf8(err->message));
if (!isPlaylist)
qWarning() << "Error:" << QString::fromUtf8(err->message); qWarning() << "Error:" << QString::fromUtf8(err->message);
g_error_free(err); g_error_free(err);
g_free(debug); g_free(debug);
} }
@@ -1640,9 +1662,14 @@ void QGstreamerPlayerSession::processInvalidMedia(QMediaPlayer::Error errorCode,
#ifdef DEBUG_PLAYBIN #ifdef DEBUG_PLAYBIN
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
#endif #endif
if (m_isPlaylist) {
stop();
emit error(int(QMediaPlayer::MediaIsPlaylist), tr("Media is loaded as a playlist"));
} else {
emit invalidMedia(); emit invalidMedia();
stop(); stop();
emit error(int(errorCode), errorString); emit error(int(errorCode), errorString);
}
} }
void QGstreamerPlayerSession::showPrerollFrames(bool enabled) void QGstreamerPlayerSession::showPrerollFrames(bool enabled)
@@ -1795,4 +1822,28 @@ void QGstreamerPlayerSession::resumeVideoProbes()
probe->stopFlushing(); probe->stopFlushing();
} }
void QGstreamerPlayerSession::playlistTypeFindFunction(GstTypeFind *find, gpointer userData)
{
QGstreamerPlayerSession* session = (QGstreamerPlayerSession*)userData;
const gchar *uri = 0;
g_object_get(G_OBJECT(session->m_playbin), "uri", &uri, NULL);
guint64 length = gst_type_find_get_length(find);
if (!length)
length = 1024;
else
length = qMin(length, guint64(1024));
while (length > 0) {
guint8 *data = gst_type_find_peek(find, 0, length);
if (data) {
session->m_isPlaylist = (QPlaylistFileParser::findPlaylistType(QString::fromUtf8(uri), 0, data, length) != QPlaylistFileParser::UNKNOWN);
return;
}
length >>= 1; // for HTTP files length is not available,
// so we have to try different buffer sizes
}
}
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@@ -188,6 +188,8 @@ private:
void flushVideoProbes(); void flushVideoProbes();
void resumeVideoProbes(); void resumeVideoProbes();
static void playlistTypeFindFunction(GstTypeFind *find, gpointer userData);
QNetworkRequest m_request; QNetworkRequest m_request;
QMediaPlayer::State m_state; QMediaPlayer::State m_state;
QMediaPlayer::State m_pendingState; QMediaPlayer::State m_pendingState;
@@ -252,6 +254,8 @@ private:
SourceType m_sourceType; SourceType m_sourceType;
bool m_everPlayed; bool m_everPlayed;
bool m_isLiveSource; bool m_isLiveSource;
bool m_isPlaylist;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE