mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
playback/player: Add Qt bindings and player
This commit is contained in:
parent
09864feff4
commit
82b2c53618
14 changed files with 1606 additions and 0 deletions
27
playback/player/qt/deployment.pri
Normal file
27
playback/player/qt/deployment.pri
Normal file
|
@ -0,0 +1,27 @@
|
|||
android-no-sdk {
|
||||
target.path = /data/user/qt
|
||||
export(target.path)
|
||||
INSTALLS += target
|
||||
} else:android {
|
||||
x86 {
|
||||
target.path = /libs/x86
|
||||
} else: armeabi-v7a {
|
||||
target.path = /libs/armeabi-v7a
|
||||
} else {
|
||||
target.path = /libs/armeabi
|
||||
}
|
||||
export(target.path)
|
||||
INSTALLS += target
|
||||
} else:unix {
|
||||
isEmpty(target.path) {
|
||||
qnx {
|
||||
target.path = /tmp/$${TARGET}/bin
|
||||
} else {
|
||||
target.path = /opt/$${TARGET}/bin
|
||||
}
|
||||
export(target.path)
|
||||
}
|
||||
INSTALLS += target
|
||||
}
|
||||
|
||||
export(INSTALLS)
|
BIN
playback/player/qt/fontawesome-webfont.ttf
Normal file
BIN
playback/player/qt/fontawesome-webfont.ttf
Normal file
Binary file not shown.
10
playback/player/qt/fontawesome-webfont.ttf.txt
Normal file
10
playback/player/qt/fontawesome-webfont.ttf.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
|
||||
Font Awesome
|
||||
|
||||
URL: http://fontawesome.io
|
||||
|
||||
Font License
|
||||
|
||||
License: SIL OFL 1.1
|
||||
URL: http://scripts.sil.org/OFL
|
||||
|
214
playback/player/qt/fontawesome.js
Normal file
214
playback/player/qt/fontawesome.js
Normal file
|
@ -0,0 +1,214 @@
|
|||
var Icon = {
|
||||
Glass : "\uf000",
|
||||
Music : "\uf001",
|
||||
Search : "\uf002",
|
||||
Envelope : "\uf003",
|
||||
Heart : "\uf004",
|
||||
Star : "\uf005",
|
||||
StarEmpty : "\uf006",
|
||||
User : "\uf007",
|
||||
Film : "\uf008",
|
||||
ThLarge : "\uf009",
|
||||
Th : "\uf00a",
|
||||
ThList : "\uf00b",
|
||||
Ok : "\uf00c",
|
||||
Remove : "\uf00d",
|
||||
ZoomIn : "\uf00e",
|
||||
ZoomOut : "\uf010",
|
||||
Off : "\uf011",
|
||||
Signal : "\uf012",
|
||||
Cog : "\uf013",
|
||||
Trash : "\uf014",
|
||||
Home : "\uf015",
|
||||
File : "\uf016",
|
||||
Time : "\uf017",
|
||||
Road : "\uf018",
|
||||
DownloadAlt : "\uf019",
|
||||
Download : "\uf01a",
|
||||
Upload : "\uf01b",
|
||||
Inbox : "\uf01c",
|
||||
PlayCircle : "\uf01d",
|
||||
Repeat : "\uf01e",
|
||||
Refresh : "\uf021",
|
||||
ListAlt : "\uf022",
|
||||
Lock : "\uf023",
|
||||
Flag : "\uf024",
|
||||
Headphones : "\uf025",
|
||||
VolumeOff : "\uf026",
|
||||
VolumeDown : "\uf027",
|
||||
VolumeUp : "\uf028",
|
||||
Qrcode : "\uf029",
|
||||
Barcode : "\uf02a",
|
||||
Tag : "\uf02b",
|
||||
Tags : "\uf02c",
|
||||
Book : "\uf02d",
|
||||
Bookmark : "\uf02e",
|
||||
Print : "\uf02f",
|
||||
Camera : "\uf030",
|
||||
Font : "\uf031",
|
||||
Bold : "\uf032",
|
||||
Italic : "\uf033",
|
||||
TextHeight : "\uf034",
|
||||
TextWidth : "\uf035",
|
||||
AlignLeft : "\uf036",
|
||||
AlignCenter : "\uf037",
|
||||
AlignRight : "\uf038",
|
||||
AlignJustify : "\uf039",
|
||||
List : "\uf03a",
|
||||
IndentLeft : "\uf03b",
|
||||
IndentRight : "\uf03c",
|
||||
FacetimeVideo : "\uf03d",
|
||||
Picture : "\uf03e",
|
||||
Pencil : "\uf040",
|
||||
MapMarker : "\uf041",
|
||||
Adjust : "\uf042",
|
||||
Tint : "\uf043",
|
||||
Edit : "\uf044",
|
||||
Share : "\uf045",
|
||||
Check : "\uf046",
|
||||
Move : "\uf047",
|
||||
StepBackward : "\uf048",
|
||||
StepForward : "\uf049",
|
||||
Backward : "\uf04a",
|
||||
Play : "\uf04b",
|
||||
Pause : "\uf04c",
|
||||
Stop : "\uf04d",
|
||||
Forward : "\uf04e",
|
||||
FastForward : "\uf050",
|
||||
StepForward : "\uf051",
|
||||
Eject : "\uf052",
|
||||
ChevronLeft : "\uf053",
|
||||
ChevronRight : "\uf054",
|
||||
PlusSign : "\uf055",
|
||||
MinusSign : "\uf056",
|
||||
RemoveSign : "\uf057",
|
||||
OkSign : "\uf058",
|
||||
QuestionSign : "\uf059",
|
||||
InfoSign : "\uf05a",
|
||||
Screenshot : "\uf05b",
|
||||
RemoveCircle : "\uf05c",
|
||||
OkCircle : "\uf05d",
|
||||
BanCircle : "\uf05e",
|
||||
ArrowLeft : "\uf060",
|
||||
ArrowRight : "\uf061",
|
||||
ArrowUp : "\uf062",
|
||||
ArrowDown : "\uf063",
|
||||
ShareAlt : "\uf064",
|
||||
ResizeFull : "\uf065",
|
||||
ResizeSmall : "\uf066",
|
||||
Plus : "\uf067",
|
||||
Minus : "\uf068",
|
||||
Asterish : "\uf069",
|
||||
ExclamationSign : "\uf06a",
|
||||
Gift : "\uf06b",
|
||||
Leave : "\uf06c",
|
||||
Fire : "\uf06d",
|
||||
EyeOpen : "\uf06e",
|
||||
EyeClose : "\uf070",
|
||||
WarningSign : "\uf071",
|
||||
Plane : "\uf072",
|
||||
Calendar : "\uf073",
|
||||
Random : "\uf074",
|
||||
Comment : "\uf075",
|
||||
Magnet : "\uf076",
|
||||
ChevronUp : "\uf077",
|
||||
ChevronDown : "\uf078",
|
||||
Retweet : "\uf079",
|
||||
ShoppingCart : "\uf07a",
|
||||
FolderClose : "\uf07b",
|
||||
FolderOpen : "\uf07c",
|
||||
ResizeVertical : "\uf07d",
|
||||
ResizeHorizontal : "\uf07e",
|
||||
BarChart : "\uf080",
|
||||
TwitterSign : "\uf081",
|
||||
FacebookSign : "\uf082",
|
||||
CameraRetro : "\uf083",
|
||||
Key : "\uf084",
|
||||
Cogs : "\uf085",
|
||||
Comments : "\uf086",
|
||||
ThumbsUp : "\uf087",
|
||||
ThumbsDown : "\uf088",
|
||||
StarHalf : "\uf089",
|
||||
HeartEmpty : "\uf08a",
|
||||
Signout : "\uf08b",
|
||||
LinkedinSign : "\uf08c",
|
||||
Pushpin : "\uf08d",
|
||||
ExternalLink : "\uf08e",
|
||||
Signin : "\uf090",
|
||||
Trophy : "\uf091",
|
||||
GithubSign : "\uf092",
|
||||
UploadAlt : "\uf093",
|
||||
Lemon : "\uf094",
|
||||
Phone : "\uf095",
|
||||
CheckEmpty : "\uf096",
|
||||
BookmarkEmpty : "\uf097",
|
||||
PhoneSign : "\uf098",
|
||||
Twitter : "\uf099",
|
||||
Facebook : "\uf09a",
|
||||
Github : "\uf09b",
|
||||
Unlock : "\uf09c",
|
||||
CreditCard : "\uf09d",
|
||||
Rss : "\uf09e",
|
||||
Hdd : "\uf0a0",
|
||||
Bullhorn : "\uf0a1",
|
||||
Bell : "\uf0a2",
|
||||
Certificate : "\uf0a3",
|
||||
HandRight : "\uf0a4",
|
||||
HandLeft : "\uf0a5",
|
||||
HandUp : "\uf0a6",
|
||||
HandDown : "\uf0a7",
|
||||
CircleArrowLeft : "\uf0a8",
|
||||
CircleArrowRight : "\uf0a9",
|
||||
CircleArrowUp : "\uf0aa",
|
||||
CircleArrowDown : "\uf0ab",
|
||||
Globe : "\uf0ac",
|
||||
Wrench : "\uf0ad",
|
||||
Tasks : "\uf0ae",
|
||||
Filter : "\uf0b0",
|
||||
Briefcase : "\uf0b1",
|
||||
Fullscreen : "\uf0b2",
|
||||
Group : "\uf0c0",
|
||||
Link : "\uf0c1",
|
||||
Cloud : "\uf0c2",
|
||||
Beaker : "\uf0c3",
|
||||
Cut : "\uf0c4",
|
||||
Copy : "\uf0c5",
|
||||
PaperClip : "\uf0c6",
|
||||
Save : "\uf0c7",
|
||||
SignBlank : "\uf0c8",
|
||||
Reorder : "\uf0c9",
|
||||
ListUl : "\uf0ca",
|
||||
ListOl : "\uf0cb",
|
||||
Strikethrough : "\uf0cc",
|
||||
Underline : "\uf0cd",
|
||||
Table : "\uf0ce",
|
||||
Magic : "\uf0d0",
|
||||
Truck : "\uf0d1",
|
||||
Pinterest : "\uf0d2",
|
||||
PinterestSign : "\uf0d3",
|
||||
GooglePlusSign : "\uf0d4",
|
||||
GooglePlus : "\uf0d5",
|
||||
Money : "\uf0d6",
|
||||
CaretDown : "\uf0d7",
|
||||
CaretUp : "\uf0d8",
|
||||
CaretLeft : "\uf0d9",
|
||||
CaretRight : "\uf0da",
|
||||
Columns : "\uf0db",
|
||||
Sort : "\uf0dc",
|
||||
SortDown : "\uf0dd",
|
||||
SortUp : "\uf0de",
|
||||
EnvelopeAlt : "\uf0e0",
|
||||
Linkedin : "\uf0e1",
|
||||
Undo : "\uf0e2",
|
||||
Legal : "\uf0e3",
|
||||
Dashboard : "\uf0e4",
|
||||
CommentAlt : "\uf0e5",
|
||||
CommentsAlt : "\uf0e6",
|
||||
Bolt : "\uf0e7",
|
||||
Sitemap : "\uf0e8",
|
||||
Unbrella : "\uf0e9",
|
||||
Paste : "\uf0ea",
|
||||
ClosedCaptions : "\uf20a",
|
||||
UserMd : "\uf200",
|
||||
};
|
||||
|
52
playback/player/qt/main.cpp
Normal file
52
playback/player/qt/main.cpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* Copyright (C) 2015 Alexandre Moreno <alexmorenocano@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <QApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
|
||||
#include "player.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
qmlRegisterType<Player>("Player", 1, 0, "Player");
|
||||
|
||||
/* the plugin must be loaded before loading the qml file to register the
|
||||
* GstGLVideoItem qml item
|
||||
* FIXME Add a QQmlExtensionPlugin into qmlglsink to register GstGLVideoItem
|
||||
* with the QML engine, then remove this */
|
||||
gst_init(NULL,NULL);
|
||||
GstElement *sink = gst_element_factory_make ("qmlglsink", NULL);
|
||||
gst_object_unref(sink);
|
||||
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
|
||||
|
||||
QObject *rootObject = engine.rootObjects().first();
|
||||
|
||||
Player *player = rootObject->findChild<Player*>("player");
|
||||
QQuickItem *videoItem = rootObject->findChild<QQuickItem*>("videoItem");
|
||||
player->setVideoOutput(videoItem);
|
||||
|
||||
|
||||
return app.exec();
|
||||
}
|
461
playback/player/qt/main.qml
Normal file
461
playback/player/qt/main.qml
Normal file
|
@ -0,0 +1,461 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* Copyright (C) 2015 Alexandre Moreno <alexmorenocano@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
import QtQuick 2.4
|
||||
import QtQuick.Controls 1.1
|
||||
import QtQuick.Controls.Styles 1.3
|
||||
import QtQuick.Dialogs 1.2
|
||||
import QtQuick.Window 2.1
|
||||
import Player 1.0
|
||||
import org.freedesktop.gstreamer.GLVideoItem 1.0
|
||||
|
||||
import "fontawesome.js" as FontAwesome
|
||||
|
||||
ApplicationWindow {
|
||||
id: window
|
||||
visible: true
|
||||
width: 640
|
||||
height: 480
|
||||
x: 30
|
||||
y: 30
|
||||
color: "black"
|
||||
// title : player.mediaInfo.title
|
||||
|
||||
Player {
|
||||
id: player
|
||||
objectName: "player"
|
||||
volume: 0.5
|
||||
onStateChanged: {
|
||||
if (state === Player.STOPPED) {
|
||||
playbutton.text = FontAwesome.Icon.Play
|
||||
}
|
||||
}
|
||||
onResolutionChanged: {
|
||||
if (player.videoAvailable) {
|
||||
window.width = resolution.width
|
||||
window.height = resolution.height
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GstGLVideoItem {
|
||||
id: video
|
||||
objectName: "videoItem"
|
||||
anchors.centerIn: parent
|
||||
width: 640
|
||||
height: 480
|
||||
}
|
||||
|
||||
FileDialog {
|
||||
id: fileDialog
|
||||
//nameFilters: [TODO globs from mime types]
|
||||
onAccepted: player.source = fileUrl
|
||||
}
|
||||
|
||||
Action {
|
||||
id: fileOpenAction
|
||||
text: "Open"
|
||||
onTriggered: fileDialog.open()
|
||||
}
|
||||
|
||||
menuBar: MenuBar {
|
||||
Menu {
|
||||
title: "&File"
|
||||
MenuItem { action: fileOpenAction }
|
||||
MenuItem { text: "Quit"; onTriggered: Qt.quit() }
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
FontLoader {
|
||||
source: "fonts/fontawesome-webfont.ttf"
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id : playbar
|
||||
color: Qt.rgba(1, 1, 1, 0.7)
|
||||
border.width: 1
|
||||
border.color: "white"
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 15
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width : grid.width + 20
|
||||
height: 40//childrenRect.height + 20
|
||||
radius: 5
|
||||
|
||||
MouseArea {
|
||||
id: mousearea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onEntered: {
|
||||
parent.opacity = 1.0
|
||||
hidetimer.start()
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: hidetimer
|
||||
interval: 10000
|
||||
onTriggered: {
|
||||
parent.opacity = 0.0
|
||||
stop()
|
||||
}
|
||||
}
|
||||
|
||||
Grid {
|
||||
id: grid
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
// anchors.top: parent.top
|
||||
// anchors.topMargin: 5
|
||||
|
||||
spacing: 7
|
||||
rows: 1
|
||||
verticalItemAlignment: Qt.AlignVCenter
|
||||
|
||||
Text {
|
||||
id : openmedia
|
||||
font.pointSize: 17
|
||||
font.family: "FontAwesome"
|
||||
text: FontAwesome.Icon.FolderOpen
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onPressed: fileDialog.open()
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: 17
|
||||
height: 17
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
font.pointSize: 17
|
||||
font.family: "FontAwesome"
|
||||
text: FontAwesome.Icon.StepBackward
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: 25
|
||||
height: 25
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
id : playbutton
|
||||
font.pointSize: 25
|
||||
font.family: "FontAwesome"
|
||||
//font.weight: Font.Light
|
||||
text: FontAwesome.Icon.PlayCircle
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: playArea
|
||||
anchors.fill: parent
|
||||
onPressed: {
|
||||
if (player.state !== Player.PLAYING) {
|
||||
player.play()
|
||||
playbutton.text = FontAwesome.Icon.Pause
|
||||
playbutton.font.pointSize = 17
|
||||
} else {
|
||||
player.pause()
|
||||
playbutton.text = FontAwesome.Icon.PlayCircle
|
||||
playbutton.font.pointSize = 25
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: 17
|
||||
height: 17
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
font.pointSize: 17
|
||||
font.family: "FontAwesome"
|
||||
text: FontAwesome.Icon.StepForward
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: 40
|
||||
height: 17
|
||||
Text {
|
||||
id: timelabel
|
||||
anchors.centerIn: parent
|
||||
font.pointSize: 13
|
||||
color: "black"
|
||||
text: {
|
||||
var current = new Date(Math.floor(slider.value / 1e6));
|
||||
current.getMinutes() + ":" + ('0'+current.getSeconds()).slice(-2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: 200
|
||||
height: 38
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: player.mediaInfo.title
|
||||
font.pointSize: 15
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Item {
|
||||
width: 40
|
||||
height: 17
|
||||
Text {
|
||||
id: durationlabel
|
||||
anchors.centerIn: parent
|
||||
font.pointSize: 13
|
||||
color: "black"
|
||||
text: {
|
||||
var duration = new Date(Math.floor(player.duration / 1e6));
|
||||
duration.getMinutes() + ":" + ('0'+duration.getSeconds()).slice(-2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: 17
|
||||
height: 17
|
||||
|
||||
|
||||
Text {
|
||||
id : volume
|
||||
anchors.centerIn: parent
|
||||
font.pointSize: 17
|
||||
font.family: "FontAwesome"
|
||||
text: {
|
||||
if (volumeslider.value > volumeslider.maximumValue / 2) {
|
||||
FontAwesome.Icon.VolumeUp
|
||||
} else if (volumeslider.value === 0) {
|
||||
FontAwesome.Icon.VolumeOff
|
||||
} else {
|
||||
FontAwesome.Icon.VolumeDown
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id : volumebar
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.top
|
||||
//anchors.bottomMargin:3
|
||||
color: "lightgray"
|
||||
width: 17
|
||||
height: 66
|
||||
visible: false
|
||||
radius: 5
|
||||
|
||||
Slider {
|
||||
id: volumeslider
|
||||
value: player.volume
|
||||
minimumValue: 0.0
|
||||
maximumValue: 1.0
|
||||
stepSize: 0.001
|
||||
anchors.centerIn: parent
|
||||
orientation: Qt.Vertical
|
||||
onPressedChanged: player.volume = value
|
||||
|
||||
style: SliderStyle {
|
||||
groove: Item {
|
||||
implicitWidth: 47
|
||||
implicitHeight: 3
|
||||
anchors.centerIn: parent
|
||||
|
||||
Rectangle {
|
||||
antialiasing: true
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
color: "gray"
|
||||
opacity: 0.8
|
||||
radius: 5
|
||||
|
||||
Rectangle {
|
||||
antialiasing: true
|
||||
height: parent.height
|
||||
width: parent.width * control.value / control.maximumValue
|
||||
color: "red"
|
||||
radius: 5
|
||||
}
|
||||
}
|
||||
}
|
||||
handle: Rectangle {
|
||||
anchors.centerIn: parent
|
||||
color: control.pressed ? "white" : "lightgray"
|
||||
border.color: "gray"
|
||||
border.width: 1
|
||||
implicitWidth: 11
|
||||
implicitHeight: 11
|
||||
radius: 90
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onPressed: {
|
||||
volumebar.visible = !volumebar.visible
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: volumebar
|
||||
hoverEnabled: true
|
||||
propagateComposedEvents: true
|
||||
|
||||
onClicked: mouse.accepted = false;
|
||||
onPressed: mouse.accepted = false;
|
||||
onReleased: mouse.accepted = false;
|
||||
onDoubleClicked: mouse.accepted = false;
|
||||
onPositionChanged: mouse.accepted = false;
|
||||
onPressAndHold: mouse.accepted = false;
|
||||
|
||||
onExited: {
|
||||
volumebar.visible = false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Text {
|
||||
id: sub
|
||||
font.pointSize: 17
|
||||
font.family: "FontAwesome"
|
||||
text: FontAwesome.Icon.ClosedCaptions
|
||||
}
|
||||
|
||||
Text {
|
||||
id : fullscreen
|
||||
font.pointSize: 17
|
||||
font.family: "FontAwesome"
|
||||
text: FontAwesome.Icon.ResizeFull
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
if (window.visibility === Window.FullScreen) {
|
||||
window.showNormal()
|
||||
fullscreen.text = FontAwesome.Icon.ResizeFull
|
||||
} else {
|
||||
window.showFullScreen()
|
||||
fullscreen.text = FontAwesome.Icon.ResizeSmall
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: playbar.width
|
||||
height: 5
|
||||
anchors.bottom: playbar.bottom
|
||||
|
||||
Slider {
|
||||
id: slider
|
||||
maximumValue: player.duration
|
||||
value: player.position
|
||||
onPressedChanged: player.seek(value)
|
||||
enabled: player.mediaInfo.isSeekable
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
MouseArea {
|
||||
id: sliderMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
propagateComposedEvents: true
|
||||
|
||||
onClicked: mouse.accepted = false;
|
||||
onPressed: mouse.accepted = false;
|
||||
onReleased: mouse.accepted = false;
|
||||
onDoubleClicked: mouse.accepted = false;
|
||||
onPositionChanged: mouse.accepted = false;
|
||||
onPressAndHold: mouse.accepted = false;
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: hoveredcliptime
|
||||
width: 40
|
||||
height: 17
|
||||
color: "lightgray"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: sliderMouseArea.containsMouse
|
||||
x: sliderMouseArea.mouseX
|
||||
|
||||
Text {
|
||||
font.pointSize: 13
|
||||
color: "black"
|
||||
anchors.centerIn: parent
|
||||
text: {
|
||||
var value = (sliderMouseArea.mouseX - slider.x) * player.duration / (slider.width - slider.x)
|
||||
var date = new Date(Math.floor(value / 1e6));
|
||||
date.getMinutes() + ":" + ('0' + date.getSeconds()).slice(-2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
style: SliderStyle {
|
||||
groove: Item {
|
||||
implicitWidth: playbar.width
|
||||
implicitHeight: 5
|
||||
|
||||
Rectangle {
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: "gray"
|
||||
opacity: 0.8
|
||||
|
||||
Rectangle {
|
||||
antialiasing: true
|
||||
color: "red"
|
||||
height: parent.height
|
||||
width: parent.width * control.value / control.maximumValue
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
antialiasing: true
|
||||
color: "yellow"
|
||||
height: parent.height
|
||||
width: parent.width * player.buffering / 100
|
||||
}
|
||||
}
|
||||
}
|
||||
handle: Rectangle {
|
||||
anchors.centerIn: parent
|
||||
color: control.pressed ? "white" : "lightgray"
|
||||
implicitWidth: 4
|
||||
implicitHeight: 5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
53
playback/player/qt/play.pro
Normal file
53
playback/player/qt/play.pro
Normal file
|
@ -0,0 +1,53 @@
|
|||
TEMPLATE = app
|
||||
|
||||
QT += qml quick widgets
|
||||
|
||||
CONFIG += c++11
|
||||
|
||||
DEFINES += GST_USE_UNSTABLE_API
|
||||
|
||||
INCLUDEPATH += ../lib
|
||||
|
||||
RESOURCES += qml.qrc
|
||||
|
||||
# Additional import path used to resolve QML modules in Qt Creator's code model
|
||||
QML_IMPORT_PATH =
|
||||
|
||||
# Default rules for deployment.
|
||||
include(deployment.pri)
|
||||
|
||||
# not tested (yet)
|
||||
unix:!macx {
|
||||
QT_CONFIG -= no-pkg-config
|
||||
CONFIG += link_pkgconfig
|
||||
PKGCONFIG = \
|
||||
gstreamer-1.0 \
|
||||
gstreamer-audio-1.0 \
|
||||
gstreamer-tag-1.0 \
|
||||
gstreamer-pbutils-1.0 \
|
||||
gstreamer-video-1.0 \
|
||||
gstreamer-gl-1.0
|
||||
}
|
||||
|
||||
macx {
|
||||
QMAKE_MAC_SDK = macosx10.9
|
||||
INCLUDEPATH += /Library/Frameworks/GStreamer.framework/Headers
|
||||
|
||||
LIBS += \
|
||||
-framework AppKit \
|
||||
-F/Library/Frameworks -framework GStreamer
|
||||
}
|
||||
|
||||
HEADERS += \
|
||||
qgstplayer.h \
|
||||
player.h \
|
||||
quickrenderer.h
|
||||
|
||||
SOURCES += main.cpp \
|
||||
qgstplayer.cpp \
|
||||
../lib/gst/player/gstplayer.c \
|
||||
../lib/gst/player/gstplayer-media-info.c \
|
||||
player.cpp \
|
||||
quickrenderer.cpp
|
||||
|
||||
DISTFILES +=
|
41
playback/player/qt/player.cpp
Normal file
41
playback/player/qt/player.cpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
|
||||
/* GStreamer
|
||||
*
|
||||
* Copyright (C) 2015 Alexandre Moreno <alexmorenocano@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "player.h"
|
||||
#include "quickrenderer.h"
|
||||
|
||||
Player::Player(QObject *parent)
|
||||
: Player(parent, new QuickRenderer)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Player::Player(QObject *parent, QuickRenderer *renderer)
|
||||
: QGstPlayer(parent, renderer)
|
||||
, renderer_(renderer)
|
||||
{
|
||||
renderer_->setParent(this);
|
||||
}
|
||||
|
||||
void Player::setVideoOutput(QQuickItem *output)
|
||||
{
|
||||
renderer_->setVideoItem(output);
|
||||
}
|
44
playback/player/qt/player.h
Normal file
44
playback/player/qt/player.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* Copyright (C) 2015 Alexandre Moreno <alexmorenocano@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef PLAYER_H
|
||||
#define PLAYER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QQuickItem>
|
||||
#include "qgstplayer.h"
|
||||
|
||||
class QuickRenderer;
|
||||
|
||||
class Player : public QGstPlayer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Player(QObject *parent = 0);
|
||||
void setVideoOutput(QQuickItem *output);
|
||||
|
||||
private:
|
||||
Player(QObject *parent, QuickRenderer *renderer);
|
||||
QuickRenderer *renderer_;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(Player*)
|
||||
|
||||
#endif // PLAYER_H
|
435
playback/player/qt/qgstplayer.cpp
Normal file
435
playback/player/qt/qgstplayer.cpp
Normal file
|
@ -0,0 +1,435 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* Copyright (C) 2015 Alexandre Moreno <alexmorenocano@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "qgstplayer.h"
|
||||
#include <QDebug>
|
||||
#include <QSize>
|
||||
|
||||
#include <QMetaObject>
|
||||
|
||||
class QGstPlayerRegisterMetaTypes
|
||||
{
|
||||
public:
|
||||
QGstPlayerRegisterMetaTypes()
|
||||
{
|
||||
qRegisterMetaType<QGstPlayer::State>("State");
|
||||
}
|
||||
|
||||
} _register;
|
||||
|
||||
QGstPlayer::MediaInfo::MediaInfo(GstPlayerMediaInfo *media_info)
|
||||
: mediaInfo_(media_info)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString QGstPlayer::MediaInfo::title() const
|
||||
{
|
||||
QString title = QString::fromLocal8Bit
|
||||
(gst_player_media_info_get_title(mediaInfo_));
|
||||
|
||||
// if media has no title, return the file name
|
||||
if (title.isEmpty()) {
|
||||
QUrl url(gst_player_media_info_get_uri(mediaInfo_));
|
||||
title = url.fileName();
|
||||
}
|
||||
|
||||
return title;
|
||||
}
|
||||
|
||||
bool QGstPlayer::MediaInfo::isSeekable() const
|
||||
{
|
||||
return gst_player_media_info_is_seekable(mediaInfo_);
|
||||
}
|
||||
|
||||
bool QGstPlayer::isVideoAvailable() const
|
||||
{
|
||||
GstPlayerVideoInfo *video_info;
|
||||
|
||||
video_info = gst_player_get_current_video_track (player_);
|
||||
if (video_info) {
|
||||
g_object_unref (video_info);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QQmlPropertyMap *QGstPlayer::mediaInfo() const
|
||||
{
|
||||
return mediaInfoMap_;
|
||||
}
|
||||
|
||||
QGstPlayer::QGstPlayer(QObject *parent, QGstPlayer::VideoRenderer *renderer)
|
||||
: QObject(parent)
|
||||
, player_()
|
||||
, state_(STOPPED)
|
||||
, videoDimensions_(QSize())
|
||||
, mediaInfoMap_()
|
||||
, videoAvailable_(false)
|
||||
{
|
||||
|
||||
player_ = gst_player_new_full(renderer ? renderer->renderer() : 0, 0);
|
||||
|
||||
g_object_connect(player_,
|
||||
"swapped-signal::state-changed", G_CALLBACK (QGstPlayer::onStateChanged), this,
|
||||
"swapped-signal::position-updated", G_CALLBACK (QGstPlayer::onPositionUpdated), this,
|
||||
"swapped-signal::duration-changed", G_CALLBACK (QGstPlayer::onDurationChanged), this,
|
||||
"swapped-signal::buffering", G_CALLBACK (QGstPlayer::onBufferingChanged), this,
|
||||
"swapped-signal::video-dimensions-changed", G_CALLBACK (QGstPlayer::onVideoDimensionsChanged), this,
|
||||
"swapped-signal::volume-changed", G_CALLBACK (QGstPlayer::onVolumeChanged), this,
|
||||
"swapped-signal::mute-changed", G_CALLBACK (QGstPlayer::onMuteChanged), this,
|
||||
"swapped-signal::media-info-updated", G_CALLBACK (QGstPlayer::onMediaInfoUpdated), this, NULL);
|
||||
|
||||
mediaInfoMap_ = new QQmlPropertyMap(this);
|
||||
}
|
||||
|
||||
void
|
||||
QGstPlayer::onStateChanged(QGstPlayer * player, GstPlayerState state)
|
||||
{
|
||||
player->state_ = static_cast<QGstPlayer::State>(state);
|
||||
|
||||
emit player->stateChanged(player->state_);
|
||||
}
|
||||
|
||||
void
|
||||
QGstPlayer::onPositionUpdated(QGstPlayer * player, GstClockTime position)
|
||||
{
|
||||
emit player->positionChanged(position);
|
||||
}
|
||||
|
||||
void
|
||||
QGstPlayer::onDurationChanged(QGstPlayer * player, GstClockTime duration)
|
||||
{
|
||||
emit player->durationChanged(duration);
|
||||
}
|
||||
|
||||
void
|
||||
QGstPlayer::onBufferingChanged(QGstPlayer * player, int percent)
|
||||
{
|
||||
emit player->bufferingChanged(percent);
|
||||
}
|
||||
|
||||
void
|
||||
QGstPlayer::onVideoDimensionsChanged(QGstPlayer * player, int w, int h)
|
||||
{
|
||||
QSize res(w,h);
|
||||
|
||||
player->setResolution(res);
|
||||
|
||||
emit player->resolutionChanged(res);
|
||||
}
|
||||
|
||||
void
|
||||
QGstPlayer::onVolumeChanged(QGstPlayer *player)
|
||||
{
|
||||
qreal new_val;
|
||||
|
||||
new_val = gst_player_get_volume (player->player_);
|
||||
|
||||
emit player->volumeChanged(new_val);
|
||||
}
|
||||
|
||||
void
|
||||
QGstPlayer::onMuteChanged(QGstPlayer *player)
|
||||
{
|
||||
bool new_val;
|
||||
|
||||
new_val = gst_player_get_mute (player->player_);
|
||||
|
||||
emit player->mutedChanged(new_val);
|
||||
}
|
||||
|
||||
void
|
||||
QGstPlayer::onMediaInfoUpdated(QGstPlayer *player, GstPlayerMediaInfo *media_info)
|
||||
{
|
||||
MediaInfo mediaInfo(media_info);
|
||||
|
||||
player->mediaInfoMap_->insert(QLatin1String("title"),
|
||||
QVariant(mediaInfo.title()));
|
||||
player->mediaInfoMap_->insert(QLatin1String("isSeekable"),
|
||||
QVariant(mediaInfo.isSeekable()));
|
||||
|
||||
bool val = player->isVideoAvailable();
|
||||
|
||||
if (player->videoAvailable_ != val) {
|
||||
player->videoAvailable_ = val;
|
||||
emit player->videoAvailableChanged(val);
|
||||
}
|
||||
|
||||
emit player->mediaInfoChanged();
|
||||
}
|
||||
|
||||
QUrl QGstPlayer::source() const
|
||||
{
|
||||
Q_ASSERT(player_ != 0);
|
||||
QString url = QString::fromLocal8Bit(gst_player_get_uri(player_));
|
||||
|
||||
return QUrl(url);
|
||||
}
|
||||
|
||||
qint64 QGstPlayer::duration() const
|
||||
{
|
||||
Q_ASSERT(player_ != 0);
|
||||
|
||||
return gst_player_get_duration(player_);
|
||||
}
|
||||
|
||||
qint64 QGstPlayer::position() const
|
||||
{
|
||||
Q_ASSERT(player_ != 0);
|
||||
|
||||
return gst_player_get_position(player_);
|
||||
}
|
||||
|
||||
qreal QGstPlayer::volume() const
|
||||
{
|
||||
Q_ASSERT(player_ != 0);
|
||||
|
||||
return gst_player_get_volume(player_);
|
||||
}
|
||||
|
||||
bool QGstPlayer::isMuted() const
|
||||
{
|
||||
Q_ASSERT(player_ != 0);
|
||||
|
||||
return gst_player_get_mute(player_);
|
||||
}
|
||||
|
||||
int QGstPlayer::buffering() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
QSize QGstPlayer::resolution() const
|
||||
{
|
||||
return videoDimensions_;
|
||||
}
|
||||
|
||||
void QGstPlayer::setResolution(QSize size)
|
||||
{
|
||||
videoDimensions_ = size;
|
||||
}
|
||||
|
||||
QGstPlayer::State QGstPlayer::state() const
|
||||
{
|
||||
return state_;
|
||||
}
|
||||
|
||||
GstElement *QGstPlayer::pipeline() const
|
||||
{
|
||||
Q_ASSERT(player_ != 0);
|
||||
|
||||
return gst_player_get_pipeline(player_);
|
||||
}
|
||||
|
||||
void QGstPlayer::play()
|
||||
{
|
||||
Q_ASSERT(player_ != 0);
|
||||
|
||||
gst_player_play(player_);
|
||||
}
|
||||
|
||||
void QGstPlayer::pause()
|
||||
{
|
||||
Q_ASSERT(player_ != 0);
|
||||
|
||||
gst_player_pause(player_);
|
||||
}
|
||||
|
||||
void QGstPlayer::stop()
|
||||
{
|
||||
Q_ASSERT(player_ != 0);
|
||||
|
||||
gst_player_stop(player_);
|
||||
}
|
||||
|
||||
void QGstPlayer::seek(qint64 position)
|
||||
{
|
||||
Q_ASSERT(player_ != 0);
|
||||
|
||||
gst_player_seek(player_, position);
|
||||
}
|
||||
|
||||
void QGstPlayer::setSource(QUrl const& url)
|
||||
{
|
||||
Q_ASSERT(player_ != 0);
|
||||
QByteArray uri = url.toString().toLocal8Bit();
|
||||
|
||||
gst_player_set_uri(player_, uri.data());
|
||||
|
||||
emit sourceChanged(url);
|
||||
}
|
||||
|
||||
void QGstPlayer::setVolume(qreal val)
|
||||
{
|
||||
Q_ASSERT(player_ != 0);
|
||||
|
||||
gst_player_set_volume(player_, val);
|
||||
}
|
||||
|
||||
void QGstPlayer::setMuted(bool val)
|
||||
{
|
||||
Q_ASSERT(player_ != 0);
|
||||
|
||||
gst_player_set_mute(player_, val);
|
||||
}
|
||||
|
||||
void QGstPlayer::setPosition(qint64 pos)
|
||||
{
|
||||
Q_ASSERT(player_ != 0);
|
||||
|
||||
gst_player_seek(player_, pos);
|
||||
}
|
||||
|
||||
GstPlayerVideoRenderer *QGstPlayer::VideoRenderer::renderer()
|
||||
{
|
||||
return renderer_;
|
||||
}
|
||||
|
||||
QGstPlayer::VideoRenderer::VideoRenderer()
|
||||
{
|
||||
renderer_ = static_cast<GstPlayerVideoRenderer*>
|
||||
(g_object_new (GST_TYPE_PLAYER_QT_VIDEO_RENDERER, "renderer", this, NULL));
|
||||
}
|
||||
|
||||
QGstPlayer::VideoRenderer::~VideoRenderer()
|
||||
{
|
||||
if (renderer_) gst_object_unref(renderer_);
|
||||
}
|
||||
|
||||
struct _GstPlayerQtVideoRenderer
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
gpointer renderer;
|
||||
};
|
||||
|
||||
struct _GstPlayerQtVideoRendererClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
static void
|
||||
gst_player_qt_video_renderer_interface_init
|
||||
(GstPlayerVideoRendererInterface * iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GstPlayerQtVideoRenderer,
|
||||
gst_player_qt_video_renderer, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (GST_TYPE_PLAYER_VIDEO_RENDERER,
|
||||
gst_player_qt_video_renderer_interface_init))
|
||||
|
||||
enum
|
||||
{
|
||||
QT_VIDEO_RENDERER_PROP_0,
|
||||
QT_VIDEO_RENDERER_PROP_RENDERER,
|
||||
QT_VIDEO_RENDERER_PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec * qt_video_renderer_param_specs
|
||||
[QT_VIDEO_RENDERER_PROP_LAST] = { NULL, };
|
||||
|
||||
static void
|
||||
gst_player_qt_video_renderer_set_property (GObject * object,
|
||||
guint prop_id, const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstPlayerQtVideoRenderer *self = GST_PLAYER_QT_VIDEO_RENDERER (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case QT_VIDEO_RENDERER_PROP_RENDERER:
|
||||
qDebug() << "setting renderer";
|
||||
self->renderer = g_value_get_pointer (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_player_qt_video_renderer_get_property (GObject * object,
|
||||
guint prop_id, GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstPlayerQtVideoRenderer *self = GST_PLAYER_QT_VIDEO_RENDERER (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case QT_VIDEO_RENDERER_PROP_RENDERER:
|
||||
g_value_set_pointer (value, self->renderer);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_player_qt_video_renderer_finalize (GObject * object)
|
||||
{
|
||||
GstPlayerQtVideoRenderer *self = GST_PLAYER_QT_VIDEO_RENDERER (object);
|
||||
|
||||
G_OBJECT_CLASS
|
||||
(gst_player_qt_video_renderer_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_player_qt_video_renderer_class_init
|
||||
(GstPlayerQtVideoRendererClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->set_property =
|
||||
gst_player_qt_video_renderer_set_property;
|
||||
gobject_class->get_property =
|
||||
gst_player_qt_video_renderer_get_property;
|
||||
gobject_class->finalize = gst_player_qt_video_renderer_finalize;
|
||||
|
||||
qt_video_renderer_param_specs
|
||||
[QT_VIDEO_RENDERER_PROP_RENDERER] =
|
||||
g_param_spec_pointer ("renderer", "Qt Renderer", "",
|
||||
static_cast<GParamFlags>(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_properties (gobject_class,
|
||||
QT_VIDEO_RENDERER_PROP_LAST,
|
||||
qt_video_renderer_param_specs);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_player_qt_video_renderer_init (GstPlayerQtVideoRenderer * self)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static GstElement *
|
||||
gst_player_qt_video_renderer_create_video_sink
|
||||
(GstPlayerVideoRenderer * iface, GstPlayer *player)
|
||||
{
|
||||
GstPlayerQtVideoRenderer *self = GST_PLAYER_QT_VIDEO_RENDERER (iface);
|
||||
|
||||
g_assert(self->renderer != NULL);
|
||||
|
||||
return static_cast<QGstPlayer::VideoRenderer*>(self->renderer)->createVideoSink();
|
||||
}
|
||||
|
||||
static void
|
||||
gst_player_qt_video_renderer_interface_init
|
||||
(GstPlayerVideoRendererInterface * iface)
|
||||
{
|
||||
iface->create_video_sink = gst_player_qt_video_renderer_create_video_sink;
|
||||
}
|
162
playback/player/qt/qgstplayer.h
Normal file
162
playback/player/qt/qgstplayer.h
Normal file
|
@ -0,0 +1,162 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* Copyright (C) 2015 Alexandre Moreno <alexmorenocano@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef QGSTPLAYER_H
|
||||
#define QGSTPLAYER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QUrl>
|
||||
#include <QSize>
|
||||
//#include <QtGui/qwindowdefs.h>
|
||||
#include <QtQml/QQmlPropertyMap>
|
||||
#include <gst/player/player.h>
|
||||
|
||||
class QGstPlayer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
|
||||
Q_PROPERTY(qint64 duration READ duration NOTIFY durationChanged)
|
||||
Q_PROPERTY(qint64 position READ position NOTIFY positionChanged)
|
||||
Q_PROPERTY(qreal volume READ volume WRITE setVolume NOTIFY volumeChanged)
|
||||
Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged)
|
||||
Q_PROPERTY(int buffering READ buffering NOTIFY bufferingChanged)
|
||||
Q_PROPERTY(QSize resolution READ resolution WRITE setResolution NOTIFY resolutionChanged)
|
||||
Q_PROPERTY(State state READ state NOTIFY stateChanged)
|
||||
Q_PROPERTY(QObject *mediaInfo READ mediaInfo NOTIFY mediaInfoChanged)
|
||||
Q_PROPERTY(bool videoAvailable READ isVideoAvailable NOTIFY videoAvailableChanged)
|
||||
|
||||
Q_ENUMS(State)
|
||||
|
||||
public:
|
||||
|
||||
class VideoRenderer;
|
||||
|
||||
explicit QGstPlayer(QObject *parent = 0, VideoRenderer *renderer = 0);
|
||||
|
||||
typedef GstPlayerError Error;
|
||||
enum State {
|
||||
STOPPED = GST_PLAYER_STATE_STOPPED,
|
||||
BUFFERING = GST_PLAYER_STATE_BUFFERING,
|
||||
PAUSED = GST_PLAYER_STATE_PAUSED,
|
||||
PLAYING = GST_PLAYER_STATE_PLAYING
|
||||
};
|
||||
|
||||
class VideoRenderer
|
||||
{
|
||||
public:
|
||||
GstPlayerVideoRenderer *renderer();
|
||||
virtual GstElement *createVideoSink() = 0;
|
||||
protected:
|
||||
VideoRenderer();
|
||||
virtual ~VideoRenderer();
|
||||
private:
|
||||
GstPlayerVideoRenderer *renderer_;
|
||||
};
|
||||
|
||||
// TODO add remaining bits
|
||||
class MediaInfo
|
||||
{
|
||||
public:
|
||||
MediaInfo(GstPlayerMediaInfo *media_info);
|
||||
QString title() const;
|
||||
bool isSeekable() const;
|
||||
private:
|
||||
GstPlayerMediaInfo *mediaInfo_;
|
||||
};
|
||||
|
||||
QUrl source() const;
|
||||
qint64 duration() const;
|
||||
qint64 position() const;
|
||||
qreal volume() const;
|
||||
bool isMuted() const;
|
||||
int buffering() const;
|
||||
State state() const;
|
||||
GstElement *pipeline() const;
|
||||
QSize resolution() const;
|
||||
void setResolution(QSize size);
|
||||
bool isVideoAvailable() const;
|
||||
QQmlPropertyMap *mediaInfo() const;
|
||||
|
||||
|
||||
signals:
|
||||
void stateChanged(State new_state);
|
||||
void bufferingChanged(int percent);
|
||||
void enfOfStream();
|
||||
void positionChanged(qint64 new_position);
|
||||
void durationChanged(qint64 duration);
|
||||
void resolutionChanged(QSize resolution);
|
||||
void volumeChanged(qreal volume);
|
||||
void mutedChanged(bool muted);
|
||||
void mediaInfoChanged();
|
||||
void sourceChanged(QUrl new_url);
|
||||
void videoAvailableChanged(bool videoAvailable);
|
||||
|
||||
public slots:
|
||||
void play();
|
||||
void pause();
|
||||
void stop();
|
||||
void seek(qint64 position);
|
||||
void setSource(QUrl const& url);
|
||||
void setVolume(qreal val);
|
||||
void setMuted(bool val);
|
||||
void setPosition(qint64 pos);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QGstPlayer)
|
||||
static void onStateChanged(QGstPlayer *, GstPlayerState state);
|
||||
static void onPositionUpdated(QGstPlayer *, GstClockTime position);
|
||||
static void onDurationChanged(QGstPlayer *, GstClockTime duration);
|
||||
static void onBufferingChanged(QGstPlayer *, int percent);
|
||||
static void onVideoDimensionsChanged(QGstPlayer *, int w, int h);
|
||||
static void onVolumeChanged(QGstPlayer *);
|
||||
static void onMuteChanged(QGstPlayer *);
|
||||
static void onMediaInfoUpdated(QGstPlayer *, GstPlayerMediaInfo *media_info);
|
||||
|
||||
GstPlayer *player_;
|
||||
State state_;
|
||||
QSize videoDimensions_;
|
||||
QQmlPropertyMap *mediaInfoMap_;
|
||||
bool videoAvailable_;
|
||||
};
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GstPlayerQtVideoRenderer
|
||||
GstPlayerQtVideoRenderer;
|
||||
|
||||
typedef struct _GstPlayerQtVideoRendererClass
|
||||
GstPlayerQtVideoRendererClass;
|
||||
|
||||
#define GST_TYPE_PLAYER_QT_VIDEO_RENDERER (gst_player_qt_video_renderer_get_type ())
|
||||
#define GST_IS_PLAYER_QT_VIDEO_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PLAYER_QT_VIDEO_RENDERER))
|
||||
#define GST_IS_PLAYER_QT_VIDEO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PLAYER_QT_VIDEO_RENDERER))
|
||||
#define GST_PLAYER_QT_VIDEO_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_PLAYER_QT_VIDEO_RENDERER, GstPlayerQtVideoRendererClass))
|
||||
#define GST_PLAYER_QT_VIDEO_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PLAYER_QT_VIDEO_RENDERER, GstPlayerQtVideoRenderer))
|
||||
#define GST_PLAYER_QT_VIDEO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PLAYER_QT_VIDEO_RENDERER, GstPlayerQtVideoRendererClass))
|
||||
#define GST_PLAYER_QT_VIDEO_RENDERER_CAST(obj) ((GstPlayerQtVideoRenderer*)(obj))
|
||||
|
||||
GType gst_player_qt_video_renderer_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
Q_DECLARE_METATYPE(QGstPlayer*)
|
||||
Q_DECLARE_METATYPE(QGstPlayer::State)
|
||||
|
||||
#endif // QGSTPLAYER_H
|
9
playback/player/qt/qml.qrc
Normal file
9
playback/player/qt/qml.qrc
Normal file
|
@ -0,0 +1,9 @@
|
|||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>main.qml</file>
|
||||
<file>fontawesome.js</file>
|
||||
</qresource>
|
||||
<qresource prefix="/fonts">
|
||||
<file>fontawesome-webfont.ttf</file>
|
||||
</qresource>
|
||||
</RCC>
|
56
playback/player/qt/quickrenderer.cpp
Normal file
56
playback/player/qt/quickrenderer.cpp
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* Copyright (C) 2015 Alexandre Moreno <alexmorenocano@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "quickrenderer.h"
|
||||
|
||||
QuickRenderer::QuickRenderer(QObject *parent)
|
||||
: QObject(parent)
|
||||
, QGstPlayer::VideoRenderer()
|
||||
, sink()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QuickRenderer::~QuickRenderer()
|
||||
{
|
||||
if (sink) gst_object_unref(sink);
|
||||
}
|
||||
|
||||
GstElement *QuickRenderer::createVideoSink()
|
||||
{
|
||||
GstElement *qmlglsink = gst_element_factory_make("qmlglsink", NULL);
|
||||
|
||||
GstElement *glsinkbin = gst_element_factory_make ("glsinkbin", NULL);
|
||||
|
||||
Q_ASSERT(qmlglsink && glsinkbin);
|
||||
|
||||
g_object_set (glsinkbin, "sink", qmlglsink, NULL);
|
||||
|
||||
sink = static_cast<GstElement*>(gst_object_ref_sink(qmlglsink));
|
||||
|
||||
return glsinkbin;
|
||||
}
|
||||
|
||||
void QuickRenderer::setVideoItem(QQuickItem *item)
|
||||
{
|
||||
Q_ASSERT(item);
|
||||
|
||||
g_object_set(sink, "widget", item, NULL);
|
||||
}
|
42
playback/player/qt/quickrenderer.h
Normal file
42
playback/player/qt/quickrenderer.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* Copyright (C) 2015 Alexandre Moreno <alexmorenocano@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef QUICKPLAYER_H
|
||||
#define QUICKPLAYER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QQuickItem>
|
||||
#include "qgstplayer.h"
|
||||
|
||||
class QuickRenderer : public QObject, public QGstPlayer::VideoRenderer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QuickRenderer(QObject *parent = 0);
|
||||
~QuickRenderer();
|
||||
|
||||
GstElement *createVideoSink();
|
||||
void setVideoItem(QQuickItem *item);
|
||||
|
||||
private:
|
||||
GstElement *sink;
|
||||
};
|
||||
|
||||
#endif // QUICKPLAYER_H
|
Loading…
Reference in a new issue