From 5abbeab161d1637a45de264ce92dab23fcaeac69 Mon Sep 17 00:00:00 2001 From: Luca Carlon Date: Mon, 25 Jul 2016 19:27:30 +0200 Subject: [PATCH] Released code for version 5.3.0-beta1. --- PiOmxTextures.pro | 19 +- piomxtextures_browser_we/main.cpp | 63 +++ .../piomxtextures_browser_we.pro | 12 + piomxtextures_browser_we/poc_main.qml | 12 + piomxtextures_browser_we/res.qrc | 5 + piomxtextures_browser_wk/main.cpp | 94 ++++ piomxtextures_browser_wk/main_wk2.qml | 7 + .../piomxtextures_browser_wk.pro | 9 + piomxtextures_browser_wk/res.qrc | 5 + piomxtextures_lib/piomxtextures_lib.pro | 2 +- piomxtextures_pocplayer/img/loader.gif | Bin 0 -> 8238 bytes piomxtextures_pocplayer/main.cpp | 1 + .../qml/POC_MediaOutput.qml | 400 +++++++++--------- piomxtextures_pocplayer/qml/main.qml | 6 + .../qml/main_multipleanim.qml | 4 +- piomxtextures_pocplayer/resources_imgs.qrc | 1 + piomxtextures_pocplayer_widget/main.cpp | 44 ++ .../piomxtextures_pocplayer_widget.pro | 6 + piomxtextures_pocplayer_yt/main.cpp | 57 +++ .../piomxtextures_pocplayer_yt.pro | 15 + piomxtextures_pocplayer_yt/player.html | 111 +++++ piomxtextures_pocplayer_yt/poc_bridge.cpp | 25 ++ piomxtextures_pocplayer_yt/poc_bridge.h | 27 ++ piomxtextures_pocplayer_yt/res.qrc | 5 + .../piomxtextures_qmlutils.pro | 2 +- piomxtextures_qmlutils/pot_videoprobe.cpp | 11 - piomxtextures_qmlutils/pot_videoprobe.h | 4 - .../mediaplayer/openmaxilplayercontrol.cpp | 19 +- .../openmaxilvideorenderercontrol.cpp | 13 +- piomxtextures_samples/loader.gif | Bin 0 -> 8238 bytes .../piomxtextures_samples.pro | 3 +- piomxtextures_samples/video_probe.qml | 70 +++ .../video_simple_buffering.qml | 89 ++++ piomxtextures_samples/webkit_simple.qml | 41 ++ piomxtextures_src/omx_mediaprocessor.cpp | 171 +++++--- piomxtextures_src/omx_mediaprocessor.h | 10 +- piomxtextures_src/omx_omxplayer_logging.cpp | 2 + piomxtextures_src/omxplayer_lib/OMXCore.cpp | 49 ++- piomxtextures_src/omxplayer_lib/OMXCore.h | 6 +- piomxtextures_src/omxplayer_lib/linux/RBP.cpp | 15 + piomxtextures_src/omxplayer_lib/linux/RBP.h | 7 + piomxtextures_src/piomxtextures_src.pri | 2 +- piomxtextures_tools/ffmpeg_test.c | 129 ++++++ 43 files changed, 1257 insertions(+), 316 deletions(-) create mode 100644 piomxtextures_browser_we/main.cpp create mode 100644 piomxtextures_browser_we/piomxtextures_browser_we.pro create mode 100644 piomxtextures_browser_we/poc_main.qml create mode 100644 piomxtextures_browser_we/res.qrc create mode 100644 piomxtextures_browser_wk/main.cpp create mode 100644 piomxtextures_browser_wk/main_wk2.qml create mode 100644 piomxtextures_browser_wk/piomxtextures_browser_wk.pro create mode 100644 piomxtextures_browser_wk/res.qrc create mode 100644 piomxtextures_pocplayer/img/loader.gif create mode 100644 piomxtextures_pocplayer_widget/main.cpp create mode 100644 piomxtextures_pocplayer_widget/piomxtextures_pocplayer_widget.pro create mode 100644 piomxtextures_pocplayer_yt/main.cpp create mode 100644 piomxtextures_pocplayer_yt/piomxtextures_pocplayer_yt.pro create mode 100644 piomxtextures_pocplayer_yt/player.html create mode 100644 piomxtextures_pocplayer_yt/poc_bridge.cpp create mode 100644 piomxtextures_pocplayer_yt/poc_bridge.h create mode 100644 piomxtextures_pocplayer_yt/res.qrc create mode 100644 piomxtextures_samples/loader.gif create mode 100644 piomxtextures_samples/video_probe.qml create mode 100644 piomxtextures_samples/video_simple_buffering.qml create mode 100644 piomxtextures_samples/webkit_simple.qml create mode 100644 piomxtextures_tools/ffmpeg_test.c diff --git a/PiOmxTextures.pro b/PiOmxTextures.pro index c715305..2a90f74 100644 --- a/PiOmxTextures.pro +++ b/PiOmxTextures.pro @@ -31,4 +31,21 @@ SUBDIRS = \ piomxtextures_app \ piomxtextures_pocplayer \ piomxtextures_samples \ - piomxtextures_qmlutils + piomxtextures_qmlutils \ + piomxtextures_pocplayer_widget + +qtHaveModule(webkit) { +message("Building wk1 sample...") +SUBDIRS += piomxtextures_browser_wk +SUBDIRS += piomxtextures_pocplayer_yt +} + +qtHaveModule(webenginewidgets) { +#message("Building we sample based on widgets...") +#SUBDIRS += piomxtextures_browser_we_widget +} + +qtHaveModule(webengine) { +message("Building we sample based on QML...") +SUBDIRS += piomxtextures_browser_we +} diff --git a/piomxtextures_browser_we/main.cpp b/piomxtextures_browser_we/main.cpp new file mode 100644 index 0000000..3071331 --- /dev/null +++ b/piomxtextures_browser_we/main.cpp @@ -0,0 +1,63 @@ +/* + * Project: PiOmxTextures + * Author: Luca Carlon + * Date: 11.29.2015 + * + * Copyright (c) 2015 Luca Carlon. All rights reserved. + * + * This file is part of PiOmxTextures. + * + * PiOmxTextures is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PiOmxTextures 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PiOmxTextures. If not, see . + */ + +/*------------------------------------------------------------------------------ +| includes ++-----------------------------------------------------------------------------*/ +#include +#include +#include +#include + +/*------------------------------------------------------------------------------ +| main ++-----------------------------------------------------------------------------*/ +int main(int argc, char* argv[]) +{ + QApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); + QApplication a(argc, argv); + + QStringList args = a.arguments(); + const bool opengl = !args.contains("--no-opengl"); + args.removeAll("--no-opengl"); + + if (opengl) { + qDebug("QML QtWebEngine..."); + + QQuickView* view = new QQuickView; + view->setSource(QUrl("qrc:/poc_main.qml")); + view->showFullScreen(); + + QObject* o = view->rootObject()->findChild("webEngineView"); + o->setProperty("url", args.at(1)); + } + else { + qDebug("Widget QtWebEngine..."); + + QWebEngineView* view = new QWebEngineView; + view->load(QUrl(args.at(1))); + view->show(); + } + + return a.exec(); +} diff --git a/piomxtextures_browser_we/piomxtextures_browser_we.pro b/piomxtextures_browser_we/piomxtextures_browser_we.pro new file mode 100644 index 0000000..d0fa317 --- /dev/null +++ b/piomxtextures_browser_we/piomxtextures_browser_we.pro @@ -0,0 +1,12 @@ +QT += core gui webenginewidgets + +TARGET = piomxtextures_browser_we +TEMPLATE = app + +SOURCES += main.cpp + +DISTFILES += \ + poc_main.qml + +RESOURCES += \ + res.qrc diff --git a/piomxtextures_browser_we/poc_main.qml b/piomxtextures_browser_we/poc_main.qml new file mode 100644 index 0000000..53e4579 --- /dev/null +++ b/piomxtextures_browser_we/poc_main.qml @@ -0,0 +1,12 @@ +import QtQuick 2.0 +import QtWebEngine 1.2 + +Rectangle { + anchors.fill: parent + color: "red" + + WebEngineView { + objectName: "webEngineView" + anchors.fill: parent + } +} diff --git a/piomxtextures_browser_we/res.qrc b/piomxtextures_browser_we/res.qrc new file mode 100644 index 0000000..40c7545 --- /dev/null +++ b/piomxtextures_browser_we/res.qrc @@ -0,0 +1,5 @@ + + + poc_main.qml + + diff --git a/piomxtextures_browser_wk/main.cpp b/piomxtextures_browser_wk/main.cpp new file mode 100644 index 0000000..493ad5e --- /dev/null +++ b/piomxtextures_browser_wk/main.cpp @@ -0,0 +1,94 @@ +/* + * Project: PiOmxTextures + * Author: Luca Carlon + * Date: 11.29.2015 + * + * Copyright (c) 2015 Luca Carlon. All rights reserved. + * + * This file is part of PiOmxTextures. + * + * PiOmxTextures is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PiOmxTextures 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PiOmxTextures. If not, see . + */ + +/*------------------------------------------------------------------------------ +| includes ++-----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*------------------------------------------------------------------------------ +| main ++-----------------------------------------------------------------------------*/ +int main(int argc, char* argv[]) +{ + QApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); + QApplication a(argc, argv); + + QStringList args = a.arguments(); + const bool opengl = !args.contains("--no-opengl"); + const bool wk2 = args.contains("--wk2"); + args.removeAll("--no-opengl"); + args.removeAll("--wk2"); + args.removeAll("--wk1"); // Default. + + const QString surl = args.at(1); + + if (!wk2) { + QGraphicsWebView* webItem = new QGraphicsWebView; + QOpenGLWidget* glViewport = new QOpenGLWidget; + + QGraphicsView* view = new QGraphicsView; + + // Set EGL to 24bit color depth. + QSurfaceFormat curSurface = glViewport->format(); + curSurface.setRedBufferSize(8); + curSurface.setGreenBufferSize(8); + curSurface.setBlueBufferSize(8); + curSurface.setAlphaBufferSize(0); + glViewport->setFormat(curSurface); + + view->setRenderHints(QPainter::Antialiasing); + view->setScene(new QGraphicsScene); + if (opengl) + view->setViewport(glViewport); + else + QObject::connect(qApp, SIGNAL(aboutToQuit()), + glViewport, SLOT(deleteLater())); + view->showFullScreen(); + + view->scene()->setBackgroundBrush(QBrush(Qt::red)); + view->scene()->setSceneRect(QRectF(0, 0, 1910, 1070)); + view->scene()->addItem(webItem); + + webItem->setUrl(QUrl(surl)); + webItem->setMinimumSize(1910, 1070); + } + else { + QQuickView* view = new QQuickView; + view->setSource(QUrl("qrc:/main_wk2.qml")); + view->show(); + + QObject* o = view->rootObject(); + o->setProperty("url", args.at(1)); + } + + return a.exec(); +} diff --git a/piomxtextures_browser_wk/main_wk2.qml b/piomxtextures_browser_wk/main_wk2.qml new file mode 100644 index 0000000..b258360 --- /dev/null +++ b/piomxtextures_browser_wk/main_wk2.qml @@ -0,0 +1,7 @@ +import QtQuick 2.0 +import QtWebKit 3.0 + +WebView { + objectName: "webView" + anchors.fill: parent +} diff --git a/piomxtextures_browser_wk/piomxtextures_browser_wk.pro b/piomxtextures_browser_wk/piomxtextures_browser_wk.pro new file mode 100644 index 0000000..5ecb76b --- /dev/null +++ b/piomxtextures_browser_wk/piomxtextures_browser_wk.pro @@ -0,0 +1,9 @@ +QT += core gui webkitwidgets quick + +TARGET = piomxtextures_browser_wk +TEMPLATE = app + +SOURCES += main.cpp + +RESOURCES += \ + res.qrc diff --git a/piomxtextures_browser_wk/res.qrc b/piomxtextures_browser_wk/res.qrc new file mode 100644 index 0000000..bb415a2 --- /dev/null +++ b/piomxtextures_browser_wk/res.qrc @@ -0,0 +1,5 @@ + + + main_wk2.qml + + diff --git a/piomxtextures_lib/piomxtextures_lib.pro b/piomxtextures_lib/piomxtextures_lib.pro index 576fe4d..4a222bd 100644 --- a/piomxtextures_lib/piomxtextures_lib.pro +++ b/piomxtextures_lib/piomxtextures_lib.pro @@ -23,7 +23,7 @@ TEMPLATE = lib -VERSION = 5.2.0 +VERSION = 5.3.0 QT += core core-private gui gui-private opengl quick quick-private CONFIG += no_private_qt_headers_warning diff --git a/piomxtextures_pocplayer/img/loader.gif b/piomxtextures_pocplayer/img/loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..cc70a7a8b3d426c30e76686fac70c0dcd4c70125 GIT binary patch literal 8238 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 literal 0 HcmV?d00001 diff --git a/piomxtextures_pocplayer/main.cpp b/piomxtextures_pocplayer/main.cpp index 2975a09..42bd5fc 100644 --- a/piomxtextures_pocplayer/main.cpp +++ b/piomxtextures_pocplayer/main.cpp @@ -78,6 +78,7 @@ bool show_media(QQuickView* view, QString mediaLocation) QObject* rootObject = dynamic_cast(view->rootObject()); QObject* mediaOutput = rootObject->findChild("mediaOutput"); QMetaObject::invokeMethod(mediaOutput, "showUrlMedia", Q_ARG(QVariant, uri.toString())); + QMetaObject::invokeMethod(mediaOutput, "play"); return true; } diff --git a/piomxtextures_pocplayer/qml/POC_MediaOutput.qml b/piomxtextures_pocplayer/qml/POC_MediaOutput.qml index 9dabe9b..933f7dd 100644 --- a/piomxtextures_pocplayer/qml/POC_MediaOutput.qml +++ b/piomxtextures_pocplayer/qml/POC_MediaOutput.qml @@ -24,203 +24,205 @@ import QtQuick 2.0 Item { - signal controlBarDismissed() - - property var currentOutput: videoOutput - - width: parent.width - height: parent.height - state: "VIDEO" - - // The video output component. - POC_VideoOutput { - id: videoOutput - sourceUrl: mediaPlayer - - onControlBarDismissed: parent.controlBarDismissed() - } - - // The image output. - POC_ImageOutput { - id: imageOutput - opacity: 0.0 - enabled: false - - onControlBarDismissed: parent.controlBarDismissed() - } - - /** - * Determines the type of media and plays it using the passed path. - */ - function showLocalMedia(mediaUri) { - showUrlMedia(mediaUri); - } - - /** - * Determines the type of media and plays it. - */ - function showUrlMedia(mediaUri) { - if (utils.isSupportedAudio(mediaUri)) - showAudio(mediaUri); - else if (utils.isSupportedImage(mediaUri)) - showImage(mediaUri); - else if (utils.isSupportedVideo(mediaUri)) - showVideo(mediaUri); - else - // TODO: Implement dialog here. - console.log("Can't handle this media, sorry."); - } - - /** - * Shows and give focus to the control bar of the currently visible output - * component. - */ - function showControlBar() { - currentOutput.showControlBar(); - } - - /** - * Shows a video on the media output. - */ - function showVideo(videoUri) { - state = "VIDEO"; - - console.log("Setting media source..."); - mediaPlayer.source = videoUri; - - //console.log("Sending play command..."); - //mediaPlayer.play(); - } - - /** - * Shows an image on the media output. - */ - function showImage(imageUri) { - mediaPlayer.stop(); - state = "IMAGE"; - imageOutput.showImage(imageUri); - } - - /** - * Starts to play the audio. - */ - function showAudio(audioUri) { - state = "VIDEO"; - mediaPlayer.source = audioUri; - //mediaPlayer.play(); - } - - /** - * Method used to "go on" to next media or inside the media. - */ - function goOnMedia() { - currentOutput.goOnMedia(); - } - - /** - * Method to "go back" to prev media or inside the media. - */ - function goBackMedia() { - currentOutput.goBackMedia(); - } - - /** - * Method to rotate the output surface. - */ - function rotateClock() { - currentOutput.rotateClock(); - } - - /** - * Method to rotate the output surface. - */ - function rotateCounter() { - currentOutput.rotateCounter(); - } - - onStateChanged: { - // Disable previous output surface. - currentOutput.enabled = false; - - // Switch. - switch (state) { - case "VIDEO": - currentOutput = videoOutput; - break; - case "IMAGE": - currentOutput = imageOutput; - break; - default: - console.log("Unknown media output status!"); - break; - } - - // Enable the new one. - currentOutput.enabled = true; - } - - states: [ - State { - name: "VIDEO" - PropertyChanges { - target: videoOutput - opacity: 1.0 - } - PropertyChanges { - target: imageOutput - opacity: 0.0 - } - }, - State { - name: "IMAGE" - PropertyChanges { - target: videoOutput - opacity: 0.0 - } - PropertyChanges { - target: imageOutput - opacity: 1.0 - } - } - ] - - transitions: [ - Transition { - from: "VIDEO" - to: "IMAGE" - - NumberAnimation { - target: videoOutput - property: "opacity" - duration: 1000 - easing.type: Easing.InOutQuad - } - - NumberAnimation { - target: imageOutput - property: "opacity" - duration: 1000 - easing.type: Easing.InOutQuad - } - }, - - Transition { - from: "IMAGE" - to: "VIDEO" - - NumberAnimation { - target: videoOutput - property: "opacity" - duration: 1000 - easing.type: Easing.InOutQuad - } - - NumberAnimation { - target: imageOutput - property: "opacity" - duration: 1000 - easing.type: Easing.InOutQuad - } - } - ] + signal controlBarDismissed() + + property var currentOutput: videoOutput + + width: parent.width + height: parent.height + state: "VIDEO" + + // The video output component. + POC_VideoOutput { + id: videoOutput + sourceUrl: mediaPlayer + + onControlBarDismissed: parent.controlBarDismissed() + } + + // The image output. + POC_ImageOutput { + id: imageOutput + opacity: 0.0 + enabled: false + + onControlBarDismissed: parent.controlBarDismissed() + } + + function play() { + mediaPlayer.play() + } + + /** + * Determines the type of media and plays it using the passed path. + */ + function showLocalMedia(mediaUri) { + showUrlMedia(mediaUri); + } + + /** + * Determines the type of media and plays it. + */ + function showUrlMedia(mediaUri) { + if (utils.isSupportedAudio(mediaUri)) + showAudio(mediaUri); + else if (utils.isSupportedImage(mediaUri)) + showImage(mediaUri); + else if (utils.isSupportedVideo(mediaUri)) + showVideo(mediaUri); + else { + console.log("Unrecognized media: assuming video."); + showVideo(mediaUri); + } + } + + /** + * Shows and give focus to the control bar of the currently visible output + * component. + */ + function showControlBar() { + currentOutput.showControlBar(); + } + + /** + * Shows a video on the media output. + */ + function showVideo(videoUri) { + state = "VIDEO"; + + console.log("Setting media source..."); + mediaPlayer.source = videoUri; + } + + /** + * Shows an image on the media output. + */ + function showImage(imageUri) { + mediaPlayer.stop(); + state = "IMAGE"; + imageOutput.showImage(imageUri); + } + + /** + * Starts to play the audio. + */ + function showAudio(audioUri) { + state = "VIDEO"; + mediaPlayer.source = audioUri; + mediaPlayer.play(); + } + + /** + * Method used to "go on" to next media or inside the media. + */ + function goOnMedia() { + currentOutput.goOnMedia(); + } + + /** + * Method to "go back" to prev media or inside the media. + */ + function goBackMedia() { + currentOutput.goBackMedia(); + } + + /** + * Method to rotate the output surface. + */ + function rotateClock() { + currentOutput.rotateClock(); + } + + /** + * Method to rotate the output surface. + */ + function rotateCounter() { + currentOutput.rotateCounter(); + } + + onStateChanged: { + // Disable previous output surface. + currentOutput.enabled = false; + + // Switch. + switch (state) { + case "VIDEO": + currentOutput = videoOutput; + break; + case "IMAGE": + currentOutput = imageOutput; + break; + default: + console.log("Unknown media output status!"); + break; + } + + // Enable the new one. + currentOutput.enabled = true; + } + + states: [ + State { + name: "VIDEO" + PropertyChanges { + target: videoOutput + opacity: 1.0 + } + PropertyChanges { + target: imageOutput + opacity: 0.0 + } + }, + State { + name: "IMAGE" + PropertyChanges { + target: videoOutput + opacity: 0.0 + } + PropertyChanges { + target: imageOutput + opacity: 1.0 + } + } + ] + + transitions: [ + Transition { + from: "VIDEO" + to: "IMAGE" + + NumberAnimation { + target: videoOutput + property: "opacity" + duration: 1000 + easing.type: Easing.InOutQuad + } + + NumberAnimation { + target: imageOutput + property: "opacity" + duration: 1000 + easing.type: Easing.InOutQuad + } + }, + + Transition { + from: "IMAGE" + to: "VIDEO" + + NumberAnimation { + target: videoOutput + property: "opacity" + duration: 1000 + easing.type: Easing.InOutQuad + } + + NumberAnimation { + target: imageOutput + property: "opacity" + duration: 1000 + easing.type: Easing.InOutQuad + } + } + ] } diff --git a/piomxtextures_pocplayer/qml/main.qml b/piomxtextures_pocplayer/qml/main.qml index 39aeec4..fb97f9a 100644 --- a/piomxtextures_pocplayer/qml/main.qml +++ b/piomxtextures_pocplayer/qml/main.qml @@ -108,6 +108,12 @@ Rectangle { onUrlSelected: mediaOutput.showUrlMedia(url) } + AnimatedImage { + anchors.centerIn: parent + source: "qrc:/img/loader.gif" + visible: mediaPlayer.status === MediaPlayer.Buffering + } + // These are shortcuts for common functionalities. Keys.onPressed: { console.log("Main interface is processing the key..."); diff --git a/piomxtextures_pocplayer/qml/main_multipleanim.qml b/piomxtextures_pocplayer/qml/main_multipleanim.qml index b408ed3..8b3ec38 100644 --- a/piomxtextures_pocplayer/qml/main_multipleanim.qml +++ b/piomxtextures_pocplayer/qml/main_multipleanim.qml @@ -34,7 +34,7 @@ Rectangle { Video { id: video1 - x: 0; y: 0; z: 1; width: parent.width; height: parent.height + x: 0; y: 0; z: 0.5; width: parent.width; height: parent.height opacity: 1 fillMode: VideoOutput.Stretch onStopped: play() @@ -70,7 +70,7 @@ Rectangle { logger.debug("Moving 1..."); videoFront.z = 0; - videoBack.z = 1; + videoBack.z = 0.5; videoFront.opacity = 1.0; videoBack.opacity = 1.0; diff --git a/piomxtextures_pocplayer/resources_imgs.qrc b/piomxtextures_pocplayer/resources_imgs.qrc index 1eb5bb0..31223bf 100644 --- a/piomxtextures_pocplayer/resources_imgs.qrc +++ b/piomxtextures_pocplayer/resources_imgs.qrc @@ -18,5 +18,6 @@ img/2_720p.jpg img/3_720p.jpg img/4_720p.jpg + img/loader.gif diff --git a/piomxtextures_pocplayer_widget/main.cpp b/piomxtextures_pocplayer_widget/main.cpp new file mode 100644 index 0000000..7034726 --- /dev/null +++ b/piomxtextures_pocplayer_widget/main.cpp @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include +#include + +#include + +int main(int argc, char *argv[]) +{ + QApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); + QApplication a(argc, argv); + + const QString fileAbsPath = a.arguments().at(1); + qDebug("Opening %s...", qPrintable(fileAbsPath)); + + QMediaPlayer p; + p.setMedia(QMediaContent(QUrl(fileAbsPath))); + + QGraphicsVideoItem* item = new QGraphicsVideoItem; + QGraphicsScene* scene = new QGraphicsScene; + scene->addText("TEST"); + p.setVideoOutput(item); + scene->addItem(item); + scene->addRect(0, 0, 100, 100, QPen(Qt::red), QBrush(Qt::red)); + item->setPos(0, 0); + + //QImage image(1920, 1080, QImage::Format_ARGB32); + //image.fill(Qt::blue); + + //QPainter painter(&image); + //painter.setRenderHint(QPainter::Antialiasing); + //scene->render(&painter); + + QGraphicsView view(scene); + //view.scene()->addItem(item); + view.setViewport(new QOpenGLWidget); + view.show(); + + p.play(); + + return a.exec(); +} diff --git a/piomxtextures_pocplayer_widget/piomxtextures_pocplayer_widget.pro b/piomxtextures_pocplayer_widget/piomxtextures_pocplayer_widget.pro new file mode 100644 index 0000000..64fd561 --- /dev/null +++ b/piomxtextures_pocplayer_widget/piomxtextures_pocplayer_widget.pro @@ -0,0 +1,6 @@ +QT += core gui multimediawidgets opengl + +TARGET = POCPlayerWidget +TEMPLATE = app + +SOURCES += main.cpp diff --git a/piomxtextures_pocplayer_yt/main.cpp b/piomxtextures_pocplayer_yt/main.cpp new file mode 100644 index 0000000..b4168c6 --- /dev/null +++ b/piomxtextures_pocplayer_yt/main.cpp @@ -0,0 +1,57 @@ +/*------------------------------------------------------------------------------ +| includes ++-----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "poc_bridge.h" + +/*------------------------------------------------------------------------------ +| main ++-----------------------------------------------------------------------------*/ +int main(int argc, char** argv) { + qputenv("QT_QPA_EGLFS_FORCE888", "1"); + + QApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); + QApplication a(argc, argv); + + const QStringList args = a.arguments(); + if (args.size() < 2) { + log_err("Video ID is missing."); + return 1; + } + + const QString videoId = args.at(1); + log_info("Starting playback of video ID %s...", qPrintable(videoId)); + + POC_Bridge bridge(videoId); + + QGraphicsWebView* webItem = new QGraphicsWebView; + webItem->page()->mainFrame()->addToJavaScriptWindowObject("bridge", &bridge); + + QOpenGLWidget* glViewport = new QOpenGLWidget; + + QGraphicsView* view = new QGraphicsView; + view->setFrameShape(QFrame::NoFrame); + + view->setRenderHints(QPainter::Antialiasing); + view->setScene(new QGraphicsScene); + view->setViewport(glViewport); + view->showFullScreen(); + + view->scene()->setBackgroundBrush(QBrush(Qt::red)); + view->scene()->setSceneRect(QRectF(0, 0, 1920, 1080)); + view->scene()->addItem(webItem); + + webItem->setUrl(QUrl("qrc:/player.html")); + webItem->setMinimumSize(1920, 1080); + + return a.exec(); +} diff --git a/piomxtextures_pocplayer_yt/piomxtextures_pocplayer_yt.pro b/piomxtextures_pocplayer_yt/piomxtextures_pocplayer_yt.pro new file mode 100644 index 0000000..216f267 --- /dev/null +++ b/piomxtextures_pocplayer_yt/piomxtextures_pocplayer_yt.pro @@ -0,0 +1,15 @@ +QT += core gui webkitwidgets quick + +TARGET = piomxtextures_pocplayer_yt +TEMPLATE = app + +INCLUDEPATH += ../3rdparty/LightLogger + +SOURCES += main.cpp \ + poc_bridge.cpp + +RESOURCES += \ + res.qrc + +HEADERS += \ + poc_bridge.h diff --git a/piomxtextures_pocplayer_yt/player.html b/piomxtextures_pocplayer_yt/player.html new file mode 100644 index 0000000..02a0c1b --- /dev/null +++ b/piomxtextures_pocplayer_yt/player.html @@ -0,0 +1,111 @@ + + + + + -1 + + + + + +
+ + + diff --git a/piomxtextures_pocplayer_yt/poc_bridge.cpp b/piomxtextures_pocplayer_yt/poc_bridge.cpp new file mode 100644 index 0000000..d1a14c1 --- /dev/null +++ b/piomxtextures_pocplayer_yt/poc_bridge.cpp @@ -0,0 +1,25 @@ +/*------------------------------------------------------------------------------ +| includes ++-----------------------------------------------------------------------------*/ +#include + +#include "poc_bridge.h" + +/*------------------------------------------------------------------------------ +| POC_Bridge::POC_Bridge ++-----------------------------------------------------------------------------*/ +POC_Bridge::POC_Bridge(const QString& videoId, QObject* parent) : + QObject(parent), + m_videoId(videoId) +{ + // Do nothing. +} + +/*------------------------------------------------------------------------------ +| POC_Bridge::onPlayerReady ++-----------------------------------------------------------------------------*/ +void POC_Bridge::onPlayerReady() +{ + log_info("YouTube player ready."); + emit playVideoId(m_videoId); +} diff --git a/piomxtextures_pocplayer_yt/poc_bridge.h b/piomxtextures_pocplayer_yt/poc_bridge.h new file mode 100644 index 0000000..3164755 --- /dev/null +++ b/piomxtextures_pocplayer_yt/poc_bridge.h @@ -0,0 +1,27 @@ +#ifndef POC_BRIDGE_H +#define POC_BRIDGE_H + +/*------------------------------------------------------------------------------ +| includes ++-----------------------------------------------------------------------------*/ +#include + +/*------------------------------------------------------------------------------ +| POC_Bridge class ++-----------------------------------------------------------------------------*/ +class POC_Bridge : public QObject +{ + Q_OBJECT +public: + POC_Bridge(const QString& videoId, QObject* parent = 0); + + Q_INVOKABLE void onPlayerReady(); + +signals: + void playVideoId(const QString& videoId); + +private: + QString m_videoId; +}; + +#endif // POC_BRIDGE_H diff --git a/piomxtextures_pocplayer_yt/res.qrc b/piomxtextures_pocplayer_yt/res.qrc new file mode 100644 index 0000000..3ad3000 --- /dev/null +++ b/piomxtextures_pocplayer_yt/res.qrc @@ -0,0 +1,5 @@ + + + player.html + + diff --git a/piomxtextures_qmlutils/piomxtextures_qmlutils.pro b/piomxtextures_qmlutils/piomxtextures_qmlutils.pro index 3d85047..e85b683 100644 --- a/piomxtextures_qmlutils/piomxtextures_qmlutils.pro +++ b/piomxtextures_qmlutils/piomxtextures_qmlutils.pro @@ -28,7 +28,7 @@ DEFINES += VERSION=\\\"$$VERSION\\\" QT += quick qml multimedia CONFIG += qt plugin -CONFIG += -std=c++11 +QMAKE_CXXFLAGS += -std=c++11 INCLUDEPATH += \ $$_PRO_FILE_PWD_/../3rdparty/LightLogger \ diff --git a/piomxtextures_qmlutils/pot_videoprobe.cpp b/piomxtextures_qmlutils/pot_videoprobe.cpp index 00bd491..490f6cf 100644 --- a/piomxtextures_qmlutils/pot_videoprobe.cpp +++ b/piomxtextures_qmlutils/pot_videoprobe.cpp @@ -36,9 +36,6 @@ POT_VideoProbe::POT_VideoProbe(QObject* parent) : QVideoProbe(parent) { // Do nothing. - - connect(this, SIGNAL(videoFrameProbed(QVideoFrame)), - this, SLOT(onVideoFrameProbed(QVideoFrame))); } /*------------------------------------------------------------------------------ @@ -70,11 +67,3 @@ void POT_VideoProbe::setSource(QObject* source) emit sourceChanged(); } - -/*------------------------------------------------------------------------------ -| POT_VideoProbe::onVideoFrameProbed -+-----------------------------------------------------------------------------*/ -void POT_VideoProbe::onVideoFrameProbed(const QVideoFrame &frame) -{ - emit videoFrameDecoded(); -} diff --git a/piomxtextures_qmlutils/pot_videoprobe.h b/piomxtextures_qmlutils/pot_videoprobe.h index df28ba2..18aab31 100644 --- a/piomxtextures_qmlutils/pot_videoprobe.h +++ b/piomxtextures_qmlutils/pot_videoprobe.h @@ -47,10 +47,6 @@ class POT_VideoProbe : public QVideoProbe signals: void sourceChanged(); - void videoFrameDecoded(); - -private slots: - void onVideoFrameProbed(const QVideoFrame& frame); private: QObject* m_source; diff --git a/piomxtextures_qt_driver/mediaplayer/openmaxilplayercontrol.cpp b/piomxtextures_qt_driver/mediaplayer/openmaxilplayercontrol.cpp index 0396894..9b53ab5 100644 --- a/piomxtextures_qt_driver/mediaplayer/openmaxilplayercontrol.cpp +++ b/piomxtextures_qt_driver/mediaplayer/openmaxilplayercontrol.cpp @@ -40,6 +40,8 @@ #include #include +#include + #include #include #include @@ -91,6 +93,10 @@ OpenMAXILPlayerControl::OpenMAXILPlayerControl(QObject *parent) this, SIGNAL(metaDataChanged(QVariantMap))); connect(m_mediaProcessor, SIGNAL(streamLengthChanged(qint64)), this, SIGNAL(durationChanged(qint64))); + connect(m_mediaProcessor, SIGNAL(bufferStatusChanged(int)), + this, SIGNAL(bufferStatusChanged(int))); + connect(m_mediaProcessor, SIGNAL(availablePlaybackRangesChanged(QMediaTimeRange)), + this, SIGNAL(availablePlaybackRangesChanged(QMediaTimeRange))); } /*------------------------------------------------------------------------------ @@ -100,7 +106,7 @@ OpenMAXILPlayerControl::~OpenMAXILPlayerControl() { log_dtor_func; - delete m_mediaProcessor; + m_mediaProcessor->deleteLater(); m_mediaProcessor = NULL; } @@ -111,6 +117,9 @@ void OpenMAXILPlayerControl::play() { logi_debug_func; m_mediaProcessor->play(); + + // FIXME: This should be removed. + emit availablePlaybackRangesChanged(QMediaTimeRange(0, duration())); } /*------------------------------------------------------------------------------ @@ -224,7 +233,7 @@ QMediaTimeRange OpenMAXILPlayerControl::availablePlaybackRanges() const log_debug_func; // TODO: Implement. - return QMediaTimeRange(); + return QMediaTimeRange(0, duration()); } /*------------------------------------------------------------------------------ @@ -235,7 +244,7 @@ int OpenMAXILPlayerControl::bufferStatus() const log_debug_func; // TODO: Implement. - return 0; + return 100; } /*------------------------------------------------------------------------------ @@ -265,8 +274,7 @@ bool OpenMAXILPlayerControl::isSeekable() const { log_debug_func; - // TODO: Implement. - return false; + return m_mediaProcessor->isSeekable(); } /*------------------------------------------------------------------------------ @@ -293,6 +301,7 @@ qreal OpenMAXILPlayerControl::playbackRate() const void OpenMAXILPlayerControl::setPlaybackRate(qreal rate) { log_debug_func; + log_debug("Playback rate: %f.", rate); // TODO: Implement. } diff --git a/piomxtextures_qt_driver/mediaplayer/openmaxilvideorenderercontrol.cpp b/piomxtextures_qt_driver/mediaplayer/openmaxilvideorenderercontrol.cpp index 78ed867..d52958d 100644 --- a/piomxtextures_qt_driver/mediaplayer/openmaxilvideorenderercontrol.cpp +++ b/piomxtextures_qt_driver/mediaplayer/openmaxilvideorenderercontrol.cpp @@ -234,7 +234,7 @@ void OpenMAXILVideoRendererControl::onTexturesReady() ); m_surfaceFormat = new QVideoSurfaceFormat( texture->m_textureSize, - QVideoFrame::Format_RGB565, + QVideoFrame::Format_ARGB32, QAbstractVideoBuffer::GLTextureHandle ); @@ -276,8 +276,15 @@ void OpenMAXILVideoRendererControl::onUpdateTriggered() return; if (UNLIKELY(!m_surface || !m_frame || !m_surfaceFormat)) return; - if (UNLIKELY(!m_surface->isActive() && !m_surface->start(*m_surfaceFormat))) - log_warn("Failed to start surface."); + if (UNLIKELY(!m_surface->isActive() && !m_surface->start(*m_surfaceFormat))) { + log_warn("Failed to start surface: %d.", m_surface->error()); + QList fs = m_surface->supportedPixelFormats(QAbstractVideoBuffer::GLTextureHandle); + foreach (QVideoFrame::PixelFormat f, fs) { + log_warn("Supported format: %d.", f); + } + + return; + } const GLuint t = m_mediaProcessor->m_provider->getNextTexture(); diff --git a/piomxtextures_samples/loader.gif b/piomxtextures_samples/loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..cc70a7a8b3d426c30e76686fac70c0dcd4c70125 GIT binary patch literal 8238 zcmbW6c|278!}n*-IkPWjhBOHchNdh{wkBC-?1V<*vZSmfT96{Cj1RMDH|I4McL~yX!;bg|+TWD*sLFDo~O26dHLjAqN{QVf=`@#Yk-hti``ww~h zY3)0>=MX~aJA}h5Kc(^e>%V^zfm&iP(*5=o1YEA#Ki?Lt@gVHLL`2oQs0nR6*lDE! zK(PrQcocf!jjqshu=~E$S78wg&9YBlbZp%f-FZ6X31%HrS@;O?lU{ioOxm?OK%oN@ zZb&&EcT}B3cEUJlktk_`wWzq`kQPYbu>m~qOa>E|9qDXIK^N>SVp2)DX@WR+By?t+vw27R1Tu1djF8 zmfShbFiV!VxmMbn$x>ayvH7qV*uBo4v6=f326Gja40mpX)dYEgeAedLE^|kklPz&Y zZP=^C(shtVq9_R!ou{Wz9{l4I5>aK=9=YP#k;=zanhbs#rG31#(D=YXqm+mHpO@Gz z6yGQ4z5Ani?Zc|u5giDZJYEv;WoyGmuS?zvSA+)Hl4QvBQ2&b`;UP0E1+Vl;H|Z#- z(b28BYgJwS{Nozmdj<9_4GYhj4p;N+pTRK`Id^ap&CaifBr+qi@ZssvL+A5W$-1`v ztNY_LIngADoo^7dvcL9JxEcfaj9o~7M%-op9q7sqPlebv+%p@Ml>7mk z;!ljsH@#}kSsT8ueVOZ*v#$)Rv<&J$K#_v|3q>&2TtLUB4va}^E6K&Ka%OIx%JENX z2tx~|U2`jLv>IMIVI5be>b0Rzy&ZVZ(HK`><|P*6rB2v?>KIunJsktHfSA}gk_IWs znGms_db%hjgK3kKgVwU9(-?gk?0NkUXS(GU3yT+jlnC}UN0XkvCeFk7K2HfUK5#5vQ~JF3XahVpJ^=CXUiES@cL|@`(s_*V^z438&pk!;I!%c%*X+x_ttod-2McHOLGgv5U4bQZH=k>B5snG{M3jXMO%ddlL2)A^n;*e^&{As(OgwSY6R3Lz1l*rdx>JY}FnZAWar zElN7^^SzGfi2TvH$pl6`OIa_37i+O~RevZAiKB?N$xzJsTW|D+9ZP-@ z6Mdaks$;Cn7pGeN!uF(@(zxzt4ExJxRxjaJwZ|*7h01th&z!G;9f>W@QPrJM4t3Lm zRgKUxlH$zaRj-QAqwFfOj1JL)UxaOH#?6MkXQJElRAd9^iV_8M;2%KyZb`hV1m?=n z+e_0!Sh7;q7qcvb4RFKz`vONIJ$BA+VtMKAN($~kt)t+D?`2$**57(nmv*>w|dqG3Q4hU-2o;O*!&%9|GFf%2h6;PQBVw5&bI9SYh?& z(Q6H>rmgYOpC3+$V+d;;TASWa_xy%d{sN375WguJYayedh)^;cu{z#h{*hB#OqCZe zeC1%(?hW7j#e%QN`?&l=&lk5~->np9@vMF-U!V|c){vfkel!-1RV$Z-3W)l1A}o;@ zTo8<=cqtv{VntkN$p2&3YFUTG&Uk8YuKjA+X6l3#RbxO|Yt+!cDDJ>#FLBBjx03YL zn}0E2B)&4jewALC#VFiGa^yl*ti9q4l+1ui$R^8uKA~Y6Zo{D@$aN;hD}LR}TwMG= z(azr(cJdiSsJ+yI%i%~trJ=SuhK1ISvK}d*OM@mdeK9`0dMUgQ=+<~xiO?3WMP^3yc zQ=Px_oHjj5 zW~1%+okQ)$GLuWlCRQk!gkCFU9D9d9W2Z!T{XFWcREg#4H9tulSH$VN%i6i#^X~PE z;Y<7y+kD&l%g$DWZ-dkUvD`y6Suyd1P*j{~3%x#eB+~1RE1(`)rYh8q8+J4l$uJb}y@6u7_dPyY zF!uf9c+b^Mht!BI+DWLA+j3i|MIoLt4IaK_#HV#{o_6}4XAA#C&hT%JREZQ;U0q8#whiK-h6W4;Dx?sAc1Brw56Driw|c}T)TX2Y^0UoNMeoTpp~8&k)+8OMWpC%P`zT;KjngI;Cu{dRaUt>##%Uz3V3-S;{KBe`K)-sfutrztheVZkn`IJM@YF^t zwN=sCTew31iXt$ z(?yADm*~v8dZX&dU{|C^eCNZWZ+T8J3!#gF zTxhS08P(0zlkhfll13rJ)Zmb{BwPX+7p@5ssQa}}!O^j635f|&Tw-Q^OtuOYmsEn| zdFR6v5%X9sig%#`V_B(8%*9>d;VPg8CJ}{0weaFIp+fN<3Oc3lul)IM{WJ#9c<`Ps z&@UWAfEesNWZG5QB6!kVpI$sqJ>I= zXl-Tl3yoK!Z-d{xumOIInR+Dh*;4*|8JBk^o9%n|f=yl7{r}d_4Kt}f{c5>_!IV^G znZ<;
o)Wb{@>wR`8G}rFfy|@`@mrW&MmrQI1w(t32&>Bksz!<53^*Js#d)DqZS! zzaO{Xs;~LD&F6aoEY7*gmnO`(TvVsmjNelE@IfKPWrIW-#G4rH6aUA9!-@ zd0Xb!Vv5L3@N5N`74N%qWvJgsW6+-qms>*A?~4-BgI^moEm8q`u<_qazxnh03A|r6 zgJlI~K63rzD54DoU8LrC4Db5R>j<|cgiSm$o}XVu!uLGhz18Dq^G0*ZMATDj{sdBA zSLk{)a<=A=C&#D7OffQBiIa~&7{Q3x(Ifvh{i(#~bV@YvVqpLQ{$^ zwp&5l*aI2J*Umn0nqBYQ_T&&Jv>V$&&FznSfbNZJ#Q=d-1811n+q}qr#N+y( ze&B60^*ev6CH|xQ`EH5p9@D;zVymUkIks}49(wo;11lP(``OrY=ud)!wrZMn&1H$^ z?RR>TdbV7pafu&RJ~@66M?3%?4pRjP&N!-<761x1pvf5-VC-5CC^4J6os7xAxa6p! z&y^8)#LO!vN|eDeXLLnjL8e0$f(Vrr^YB;5bvIOqXaYXQgoLi|?TV#PQU*r;$I49r zGvKby6s1W5pfC&67aMC@(Th(=(8Bk3dH{rKh02fk4v=|m;47c8>CcBUH=!^jMM^n^ zQSI`aA>VhF9UpxPl6~0uNbF<`p)8kvc(WN&9E9q}?~%P`2oOaw82Z2Rr*dtKLO~t%ez-wJz#G(Xxa!s|r%z3Ne4Ym;>Y4Z;%E`_c-5-RC@Nf3lm zpXpCaaf$V4PasGac*xdHNs|_*4!8rrXf^DN)gNlsV=_#GfKUAA?UfrJZ$$KO^r3{qFF$PVE7sLKOp1)?T9M<0utG z6!d9{~%yB)nyyVx7@56NHqTrN0z7t`z2k) zam60RHy(LME?um6nWz5`O8DKznGh~J2a%SZ zY>dvoR4B4Sq2f#dej-#QQX!H`xd5JkzELm!JCJ*C-6bxkOrahLy!oJe8Fbvlhz^=M zjDOk*peDv~czx2)5Owm-*qd?cCiI7weXpL+%Z_=mt9I*P=i3G&!~5yb5rVA#yi&;j z0&;m&^4o|6iA!{^f#6s;M;fIO94w9ocWb2kdAygjClwfPMXWH$GJim|LNYDfKXoC_ z^A!fvm86pd6_zo3oG)iz`J-&Ng@!`2?*3#fKWKbsEdi%j;CcIp1|jS1Se5Vm)Xn4i zm+isLD_P=-;>w+MRtw6H@?2}ZY1{TaHH5R*_cfbO>-Pt8-g)=0_p?;puZ_CfuCev+ zK(;g-P>yx!(0IaVkDh>zo{Hw*aD6w?L%^CSS+$SE+@dn9_!m&%EPlPB4#Vijp@j`c zH&<(=B0qebc`}|i3Uj|sc=%m1Q#{qMTJ_$czkpnle`P(88EW>%RD4*BmB8nA(Pl86 z2&_5FbA6PC=rPRIWfa9?I9Lc+XVnq`kQ)Yp1&FvBK zaVuZe0fsbaUAu>gBHt%LEH7G_p{~Iw6#}&)r36WB5uBmbz!Yb0>j-mKkmrdn3I(ld zFLP;GujD{%Y7#eFjl?cXzf$zD48p>jSA!HTV)hh_Ue6-^L*HMfl@-KAlZuDb5@qly zGog4LP9b=?!9T))^ei~pu}QltK-#Q`(0!GiIQ7VgC6_0@cfubR0rK+fS-c zqtnd5gm_8{(}haKn^EGACuajL_(Cq>I4UOF$Liqas_L5BYjxM_8ycH#G`BbbAo>J{ z2xhea$8iufLXSvzaQjANZ||Tk`oYl_!b1qxuG{}W(ug0QozbC)Tkp)GT8)YbVBh<% z-@gC&^It!IEg?X>ymgJJJ?18ZTaz#VK^UAoGjLEuu8@{e^y&*xF0rI3nxsou0%q?S zMW-b!+>?P=sh{U^!5rtMW_4aJq_}V0wLRNpKpIxz>3RzVeT_XiGdOKOr^0P#4K7w> zne%g~8}hLJB3AO{O~>O;Ts~Z}t=7&Fo5bv@yYJF+;Og|0Ax17hT)Xj{!{9`!)hT?SJRdg)0>H(Py%PN4pSFN=! z0`v(6FYR%S_eN`@)nRF1wW=iJ{<1v{U7VaWHQJ&;lqe~L<@m$ZAL)dhDz5CGwSW1( zRmA7>8As0klo5&xZiX^QG9|3DbJ1;N-%SFCd8cWmS0C#hb}x z97q2UaRrF7m6ni{tt5jG(mH^EKmEKTk^OEIV2_tl;!Y&3`-bs?s)$?>%(4|trD+r} zxJbnIFL;Q`r0~+$GJ~hnsMiL#UO(lJ&3HSEN6?Xu2VLm`D@FDck0c}VL3*VBoc7+hnTBFO}`E0aOuL zS{7bATp2tofUtu_dBx`?=W4HMl`-h>vnw%=k+pcLy)XZ~zI3^PH@vs=0t+TTZ_c_n zRAO^X|3zdm@8S7*Q+L&Urs~5N{Tc;v^UhVnwDbKw_92d?-GxUI#!sx4Dc_nKQ=cRB z8_rCQqbr!pTUINdkHP5#jrZNCn|&ZMOHs5pcn;^`grD==eKTVpR});*QAIC-N7@YW zc-o?DEQFJX?vP5v2S;(iFIH$pRi{FCc5e~iW^jTf)Ijq@Ev4^QTOTQWD=pd*dB|fV z4lHc-5r;f!2J*chbl3_s>bCw{H3#h}lsFn7LEb}P7$Qa~F#CM~2FT{4eQN<`lSuGs z5K#nT%zI=N&^wzX5yot>cPv#+s6@plmNSx!aucVLy3#hnDcGoTz-UA63h#uDtK~^? z1Vv#X*2VmrBLUqv$BhZo<<21W@)(E&jNdEq83e^QKky2c4Fg`+YPdN8ijpzBW$>}B z$N*)bDzcC&+>?Wf+QSuuyv}tyvTr+>mpe#j%$)iwe*HAiSK)P*~gkK0F2RkZVIcL1LP^%rp+8Z+pGEiSPJ4W$pSYnB`wY5rO@F1=sH(7A{|HI|@DQvNNV(|3d_ zTMO)NT=QQ=8e?(33EPp7h)OIwvKKMC0x(WM|8&em064EhSBir5=BkTi#N$SC@xU_? zF43LR67gPdj3PGRNez>_F7iP+nhE18Hpj!;sH z#`Se4APDPOg)v5ym6Ne&&4VYA9XHrqh!7DDfS|24_k^?j^cv(#WDN{*i{}6^f;A-v zanjjbAqKHd#S{;%nh8x`h49Pd?)gRsx9i*Z_@cdD!8vFAEiuOf%9it|_Wvi4(d`3V z1Ap7N4zDP8H=yEr1iAG=l0CnnqXZ0WgTsq@_9`a5b7!iPJ&4I6%dW=g>m z2q#Z51>vUXL;^ZRH9Aeo6g)%8VjfLHMS>tDI4dZeR+ewIJYMccU8(#pM{m8^ruKW= zym-q5r1kb*>sF~_Q|=Cd_id@*VcqJXUR<{uflAHP!;STlyGfJO$tT*>S=#t5w}ol_ z!P$qe@zWRdc82)6EO?5M5RFM+tUTA5KvA*%TOoRnjrCFRWHVp{4}g`Nm)IQswNfZ+ z1xl9>r&&bjXe!YCVtdV37w)&^Ol?+XAxbPxm3i?Qrbq#cA?doIvu>co$O5uRuD{}Z z)uS%bvq-Yf>7?VOhN$ipZ(J*FpNCpJO$>NO`;|xY2s!-vyi9oK(-rF9f*v;|+|Kj* zp=;_)Be_n+;;w5>bs1{z)w}HWJ_)^5ELrvZc%d5sfH3q^6 z=EIsW9`9rTEVR2ovQZ03z*?`hT3)DLTsp!N?&3Co)V@d6_`{1>6b7JVdTUPpgd=yU zv}`pwY08D(w^J$KPTmtAi`O4*l;821JAgRRvk=0#aBz8)m&8ykv8Y3h{*&T3{NmXz zr4yq*;y8>~xfK$}G)D-`bP;258f|xCkgDCeo^q5LY%!?ymg1QT@vV{&xUo4du=zC` zaeD2DHk?NO)+9ib4D2mTqKY_B7Eg^EN6_1|c^XGd1u``8Z49x{488A#h3B4gGy5q` on`h3JtIn#Osjn#KA8uTpT|qfp)|@C-w%HVm*z)`I{jcl)0R6+R(f|Me literal 0 HcmV?d00001 diff --git a/piomxtextures_samples/piomxtextures_samples.pro b/piomxtextures_samples/piomxtextures_samples.pro index 4f1303d..4416363 100644 --- a/piomxtextures_samples/piomxtextures_samples.pro +++ b/piomxtextures_samples/piomxtextures_samples.pro @@ -31,4 +31,5 @@ DISTFILES += \ audio_simple.qml \ video_concurrent.qml \ video_loop.qml \ - video_loop_position.qml + video_loop_position.qml \ + webkit_simple.qml diff --git a/piomxtextures_samples/video_probe.qml b/piomxtextures_samples/video_probe.qml new file mode 100644 index 0000000..0a4991b --- /dev/null +++ b/piomxtextures_samples/video_probe.qml @@ -0,0 +1,70 @@ +/* + * Project: PiOmxTextures + * Author: Luca Carlon + * Date: 03.19.2016 + * + * Copyright (c) 2019 Luca Carlon. All rights reserved. + * + * This file is part of PiOmxTextures. + * + * PiOmxTextures is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PiOmxTextures 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PiOmxTextures. If not, see . + */ + +import QtQuick 2.2 +import QtQml 2.0 +import QtQuick.Window 2.1 +import QtMultimedia 5.0 +import PiOmxTexturesQmlUtils 0.1 + +Rectangle { + property string uri + + id: root + objectName: "root" + visible: true + color: "black" + + Component.onCompleted: { + var arguments = Qt.application.arguments; + if (arguments.length < 3) { + console.log("Too few arguments."); + Qt.quit(); + } + + uri = arguments[1]; + } + + VideoOutput { + id: myVideo + anchors.fill: parent + visible: true + source: mediaPlayer + } + + MediaPlayer { + id: mediaPlayer + source: uri + autoPlay: true + + onStopped: { + console.log("Looping...") + mediaPlayer.play() + } + } + + POT_VideoProbe { + source: mediaPlayer + onVideoFrameProbed: console.log("Frame probed!") + } +} diff --git a/piomxtextures_samples/video_simple_buffering.qml b/piomxtextures_samples/video_simple_buffering.qml new file mode 100644 index 0000000..ec61050 --- /dev/null +++ b/piomxtextures_samples/video_simple_buffering.qml @@ -0,0 +1,89 @@ +/* + * Project: PiOmxTextures + * Author: Luca Carlon + * Date: 08.22.2015 + * + * Copyright (c) 2015 Luca Carlon. All rights reserved. + * + * This file is part of PiOmxTextures. + * + * PiOmxTextures is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PiOmxTextures 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PiOmxTextures. If not, see . + */ + +import QtQuick 2.2 +import QtQml 2.0 +import QtQuick.Window 2.1 +import QtMultimedia 5.0 + +/** + * This sample creates a Video surface including a MediaPlayer, plays continuously + * and asks for the current position every 10ms. + */ +Rectangle { + property string uri + + id: root + objectName: "root" + visible: true + color: "black" + + Component.onCompleted: { + var arguments = Qt.application.arguments; + if (arguments.length < 3) { + console.log("Too few arguments."); + Qt.quit(); + } + + uri = arguments[1] + } + + Video { + id: myVideo + anchors.fill: parent + visible: true + + source: uri + autoPlay: true + + onStopped: { + console.log("Stopped."); + myVideo.seek(0); + myVideo.play(); + } + + onStatusChanged: { + console.log("Status changed to: " + status + "."); + } + } + + AnimatedImage { + anchors.centerIn: parent + source: "loader.gif" + visible: myVideo.status == MediaPlayer.Buffering + } + + Timer { + id: videoInterval + interval: 1000 + repeat: true + running: myVideo.playbackState === MediaPlayer.PlayingState + + onTriggered: { + console.log("Requesting position..."); + var position = myVideo.position; + + console.log("Position: " + position + "."); + } + } +} diff --git a/piomxtextures_samples/webkit_simple.qml b/piomxtextures_samples/webkit_simple.qml new file mode 100644 index 0000000..edfb893 --- /dev/null +++ b/piomxtextures_samples/webkit_simple.qml @@ -0,0 +1,41 @@ +/* + * Project: PiOmxTextures + * Author: Luca Carlon + * Date: 10.08.2015 + * + * Copyright (c) 2015 Luca Carlon. All rights reserved. + * + * This file is part of PiOmxTextures. + * + * PiOmxTextures is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PiOmxTextures 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PiOmxTextures. If not, see . + */ + +import QtQuick 2.0 +import QtWebKit 3.0 + +WebView { + id: main + + Component.onCompleted: { + var arguments = Qt.application.arguments; + if (arguments.length < 3) { + console.log("Too few arguments."); + Qt.quit(); + } + + main.url = arguments[2] + } + + url: "http://www.google.com" +} diff --git a/piomxtextures_src/omx_mediaprocessor.cpp b/piomxtextures_src/omx_mediaprocessor.cpp index f91c06f..2ae9b58 100644 --- a/piomxtextures_src/omx_mediaprocessor.cpp +++ b/piomxtextures_src/omx_mediaprocessor.cpp @@ -155,7 +155,7 @@ OMX_MediaProcessor::OMX_MediaProcessor(OMX_EGLBufferProviderSh provider) : m_provider(provider), #define THREADED_GL #ifdef THREADED_GL - m_thread(new QThread), + m_thread(new OMX_QThread), #else m_thread(QOpenGLContext::globalShareContext()->thread()), #endif @@ -205,11 +205,16 @@ OMX_MediaProcessor::OMX_MediaProcessor(OMX_EGLBufferProviderSh provider) : "OMX_MediaProcessor::OMX_MediaStatus"); const int gpu_mem = get_mem_gpu(); - const int min_gpu_mem = 256; + const int min_gpu_mem = 192; if (gpu_mem > 0 && gpu_mem < min_gpu_mem) LOG_WARNING(LOG_TAG, "Only %dM of gpu_mem is configured. Try running" " \"sudo raspi-config\" and ensure that \"memory_split\" has " "a value of %d or greater\n", gpu_mem, min_gpu_mem); + if (!QOpenGLContext::globalShareContext()) { + log_err("Failed to get shared context. Enable it."); + abort(); + } + m_RBP->Initialize(); m_OMX->Initialize(); @@ -221,6 +226,7 @@ OMX_MediaProcessor::OMX_MediaProcessor(OMX_EGLBufferProviderSh provider) : moveToThread(m_thread); m_thread->start(); + setVolume(1, true); INVOKE("init", INVOKE_CONN); } @@ -262,7 +268,7 @@ OMX_MediaProcessor::~OMX_MediaProcessor() +-----------------------------------------------------------------------------*/ QString OMX_MediaProcessor::filename() { - return m_filename; + return m_sourceUrl; } /*------------------------------------------------------------------------------ @@ -307,7 +313,7 @@ bool OMX_MediaProcessor::setFilenameInt(const QString& filename) log_verbose_func; QMutexLocker locker(&m_sendCmd); - if (m_filename == filename) + if (m_sourceUrl == filename) return true; switch (m_state) { @@ -324,15 +330,22 @@ bool OMX_MediaProcessor::setFilenameInt(const QString& filename) } LOG_VERBOSE(LOG_TAG, "Opening %s...", qPrintable(filename)); + if (filename.isEmpty() || filename.isNull() || filename.size() <= 0) { + log_err("Empty media URL."); + m_sourceUrl = QString(); + return false; + } + + m_sourceUrl = filename; // It seems that omxplayer expects path and not local URIs. QUrl url(filename); if (url.isLocalFile() && filename.startsWith("file://")) - m_filename = url.path(); + m_sourceUrl = url.path(); //m_omx_reader = new OMX_Reader; - if (!m_omx_reader->Open(m_filename.toStdString(), true)) { - log_err("Failed to open source %s.", qPrintable(m_filename)); + if (!m_omx_reader->Open(m_sourceUrl.toStdString(), true)) { + log_err("Failed to open source %s.", qPrintable(m_sourceUrl)); return false; } @@ -341,7 +354,11 @@ bool OMX_MediaProcessor::setFilenameInt(const QString& filename) // decides. LOG_VERBOSE(LOG_TAG, "Copy metatada..."); convertMetaData(); + emit metadataChanged(m_metadata); + emit streamLengthChanged(m_omx_reader->GetStreamLength()); + //emit bufferStatusChanged(100); + //emit availablePlaybackRangesChanged(QMediaTimeRange(0, m_omx_reader->GetStreamLength())); // Set the mute property according to current state. m_player_audio->SetMuted(m_muted); @@ -358,7 +375,6 @@ bool OMX_MediaProcessor::setFilenameInt(const QString& filename) m_packetAfterSeek = false; m_seekFlush = false; - LOG_VERBOSE(LOG_TAG, "Initializing OMX clock..."); if (!m_av_clock->OMXInitialize()) return false; @@ -381,16 +397,8 @@ bool OMX_MediaProcessor::setFilenameInt(const QString& filename) m_omx_reader->SetActiveStream(OMXSTREAM_AUDIO, m_audio_index_use); #endif - // Seek on start? -#if 0 - if (m_seek_pos !=0 && m_omx_reader->CanSeek()) { - printf("Seeking start of video to %i seconds\n", m_seek_pos); - m_omx_reader->SeekTime(m_seek_pos * 1000.0f, false, &startpts); // from seconds to DVD_TIME_BASE - } -#endif - if (m_has_video) { - LOG_VERBOSE(LOG_TAG, "Opening video using OMX..."); + log_verbose("Opening video using OMX..."); if (!m_player_video->Open(m_av_clock, *m_videoConfig)) return false; } @@ -416,6 +424,7 @@ bool OMX_MediaProcessor::setFilenameInt(const QString& filename) m_subtitle_index = m_omx_reader->SubtitleStreamCount() - 1; #endif + // omxplayer is doing this twice for some reason. m_omx_reader->GetHints(OMXSTREAM_AUDIO, m_audioConfig->hints); #if 0 @@ -440,13 +449,16 @@ bool OMX_MediaProcessor::setFilenameInt(const QString& filename) else m_audioConfig->device = "omx:hdmi"; - log_verbose("Opening audio using OMX..."); - log_verbose("Using %s output device...", m_audioConfig->device.c_str()); if (m_has_audio) { - if (!m_player_audio->Open(m_av_clock, *m_audioConfig, m_omx_reader)) + log_verbose("Opening audio using OMX..."); + log_verbose("Using %s output device...", m_audioConfig->device.c_str()); + if (!m_player_audio->Open(m_av_clock, *m_audioConfig, m_omx_reader)) { + log_warn("Failed to open audio."); return false; - if (m_has_audio) - m_player_audio->SetCurrentVolume(m_volume, true); + } + + //m_player_audio->SetCurrentVolume(m_volume, true); + //setVolume(1); } setState(STATE_STOPPED); @@ -479,12 +491,16 @@ bool OMX_MediaProcessor::playInt() setMediaStatus(MEDIA_STATUS_LOADED); setState(STATE_PLAYING); - m_av_clock->OMXPause(); - m_av_clock->OMXStateExecute(); - m_av_clock->OMXResume(); + //m_av_clock->OMXPause(); + //m_av_clock->OMXStateExecute(); + //m_av_clock->OMXResume(); + + //m_av_clock->OMXReset(m_has_video, m_has_audio); + //m_av_clock->OMXStateExecute(); LOG_VERBOSE(LOG_TAG, "Starting thread."); QtConcurrent::run(&m_tpool, this, &OMX_MediaProcessor::mediaDecoding); + return true; } default: return false; @@ -644,6 +660,15 @@ bool OMX_MediaProcessor::seek(qint64 position) return true; } +/*------------------------------------------------------------------------------ +| OMX_MediaProcessor::isSeekable ++-----------------------------------------------------------------------------*/ +bool OMX_MediaProcessor::isSeekable() { + if (UNLIKELY(!m_omx_reader)) + return false; + return m_omx_reader->CanSeek(); +} + /*------------------------------------------------------------------------------ | OMX_MediaProcessor::currentPosition +-----------------------------------------------------------------------------*/ @@ -712,32 +737,40 @@ void OMX_MediaProcessor::mediaDecoding() { // See description in the qmakefile. //#define ENABLE_PROFILE_MAIN_LOOP -//#define ENABLE_PAUSE_FOR_BUFFERING +#define ENABLE_PAUSE_FOR_BUFFERING - LOG_VERBOSE(LOG_TAG, "Decoding thread started."); + log_verbose("Decoding thread started."); emit playbackStarted(); // Prealloc. #ifdef ENABLE_PAUSE_FOR_BUFFERING - float stamp = 0; - float audio_pts = 0; - float video_pts = 0; - - float audio_fifo = 0; - float video_fifo = 0; - float threshold = 0; - bool audio_fifo_low = false, video_fifo_low = false, audio_fifo_high = false, video_fifo_high = false; - float m_threshold = 1.0f; //std::min(0.1f, audio_fifo_size * 0.1f); + float stamp = 0; + float audio_pts = 0; + float video_pts = 0; + float audio_fifo = 0; + float video_fifo = 0; + float threshold = 0; + float m_threshold = m_audioConfig->is_live ? 0.7f : 0.2f; + + bool audio_fifo_low = false; + bool video_fifo_low = false; + bool audio_fifo_high = false; + bool video_fifo_high = false; #endif // ENABLE_PAUSE_FOR_BUFFERING - bool sentStarted = false; - double last_seek_pos = 0; + bool sentStarted = true; bool sendEos = false; - double m_last_check_time = 0.0; + + double last_seek_pos = 0; + double last_check_time = 0.0; m_av_clock->OMXReset(m_has_video, m_has_audio); m_av_clock->OMXStateExecute(); - sentStarted = true; + +#ifndef ENABLE_PAUSE_FOR_BUFFERING + // FIXME: This should not be placed here. + setMediaStatus(OMX_MediaStatus::MEDIA_STATUS_BUFFERED); +#endif // ENABLE_PAUSE_FOR_BUFFERING while (!m_pendingStop) { #ifdef ENABLE_PROFILE_MAIN_LOOP @@ -760,9 +793,9 @@ void OMX_MediaProcessor::mediaDecoding() double now = m_av_clock->GetAbsoluteClock(); bool update = false; - if (m_last_check_time == 0.0 || m_last_check_time + DVD_MSEC_TO_TIME(20) <= now) { + if (last_check_time == 0.0 || last_check_time + DVD_MSEC_TO_TIME(20) <= now) { update = true; - m_last_check_time = now; + last_check_time = now; } // If a request is pending then consider done here. @@ -790,11 +823,8 @@ void OMX_MediaProcessor::mediaDecoding() //seek_pos *= 1000.0; - if(m_omx_reader->SeekTime((int)seek_pos, m_incrMs < 0.0f, &startpts)) - { + if (m_omx_reader->SeekTime((int)seek_pos, m_incrMs < 0.0f, &startpts)) { unsigned t = (unsigned)(startpts*1e-6); - //auto dur = m_omx_reader->GetStreamLength() / 1000; - log_info("Seek to: %02d:%02d:%02d", (t/3600), (t/60)%60, t%60); flushStreams(startpts); } @@ -809,9 +839,8 @@ void OMX_MediaProcessor::mediaDecoding() break; } - m_incrMs = 0; - #ifdef ENABLE_PAUSE_FOR_BUFFERING + setMediaStatus(OMX_MediaStatus::MEDIA_STATUS_BUFFERING); m_av_clock->OMXPause(); #else m_av_clock->OMXResume(); @@ -823,9 +852,10 @@ void OMX_MediaProcessor::mediaDecoding() #endif unsigned t = (unsigned)(startpts*1e-6); - LOG_VERBOSE(LOG_TAG, "Seeked to: %02d:%02d:%02d", (t/3600), (t/60)%60, t%60); + log_verbose("Seeked to: %02d:%02d:%02d", (t/3600), (t/60)%60, t%60); m_packetAfterSeek = false; m_seekFlush = false; + m_incrMs = 0; } else if (UNLIKELY(m_packetAfterSeek && TRICKPLAY(m_av_clock->OMXPlaySpeed()))) { double seek_pos = 0; @@ -837,20 +867,18 @@ void OMX_MediaProcessor::mediaDecoding() //seek_pos *= 1000.0; -#if 1 if (m_omx_reader->SeekTime((int)seek_pos, m_av_clock->OMXPlaySpeed() < 0, &startpts)) { ; //FlushStreams(DVD_NOPTS_VALUE); } -#endif // 1 - CLog::Log(LOGDEBUG, "Seeked %.0f %.0f %.0f", DVD_MSEC_TO_TIME(seek_pos), startpts, m_av_clock->OMXMediaTime()); + log_verbose("Seeked %.0f %.0f %.0f", DVD_MSEC_TO_TIME(seek_pos), startpts, m_av_clock->OMXMediaTime()); m_packetAfterSeek = false; } // TODO: Better error handling. if (m_player_audio->Error()) { - LOG_ERROR(LOG_TAG, "Audio player error. emergency exit!"); + log_err("Audio player error. emergency exit!"); break; } @@ -877,6 +905,10 @@ void OMX_MediaProcessor::mediaDecoding() audio_fifo = audio_pts == DVD_NOPTS_VALUE ? 0.0f : audio_pts / DVD_TIME_BASE - stamp * 1e-6; video_fifo = video_pts == DVD_NOPTS_VALUE ? 0.0f : video_pts / DVD_TIME_BASE - stamp * 1e-6; threshold = min(0.1f, (float)m_player_audio->GetCacheTotal()*0.1f); + audio_fifo_low = false; + video_fifo_low = false; + audio_fifo_high = false; + video_fifo_high = false; #endif // ENABLE_PAUSE_FOR_BUFFERING #if 0 @@ -923,14 +955,19 @@ void OMX_MediaProcessor::mediaDecoding() video_fifo_high = !m_has_video || (video_pts != DVD_NOPTS_VALUE && video_fifo > m_threshold); } +#if 0 + log_debug("Normal M:%.0f (A:%.0f V:%.0f) P:%d A:%.2f V:%.2f/T:%.2f (%d,%d,%d,%d) A:%d%% V:%d%% (%.2f,%.2f)\n", stamp, audio_pts, video_pts, m_av_clock->OMXIsPaused(), + audio_pts == DVD_NOPTS_VALUE ? 0.0:audio_fifo, video_pts == DVD_NOPTS_VALUE ? 0.0:video_fifo, m_threshold, audio_fifo_low, video_fifo_low, audio_fifo_high, video_fifo_high, + m_player_audio->GetLevel(), m_player_video->GetLevel(), m_player_audio->GetDelay(), (float)m_player_audio->GetCacheTotal()); +#endif + // Enable this to enable pause for buffering. - if (m_state != STATE_PAUSED && (m_omx_reader->IsEof() || m_omx_pkt || TRICKPLAY(m_av_clock->OMXPlaySpeed()) || (audio_fifo_high && video_fifo_high))) - { - if (m_av_clock->OMXIsPaused()) - { - CLog::Log(LOGDEBUG, "Resume %.2f,%.2f (%d,%d,%d,%d) EOF:%d PKT:%p\n", audio_fifo, video_fifo, audio_fifo_low, video_fifo_low, audio_fifo_high, video_fifo_high, m_omx_reader->IsEof(), m_omx_pkt); - log_verbose("Pausing for buffering..."); - //m_av_clock->OMXStateExecute(); + if (m_state != STATE_PAUSED && (m_omx_reader->IsEof() || m_omx_pkt || TRICKPLAY(m_av_clock->OMXPlaySpeed()) || (audio_fifo_high && video_fifo_high))) { + if (m_av_clock->OMXIsPaused()) { + log_verbose("Resume %.2f,%.2f (%d,%d,%d,%d) EOF:%d PKT:%p\n", + audio_fifo, video_fifo, audio_fifo_low, video_fifo_low, audio_fifo_high, video_fifo_high, m_omx_reader->IsEof(), m_omx_pkt); + + setMediaStatus(OMX_MediaStatus::MEDIA_STATUS_BUFFERED); m_av_clock->OMXResume(); } } @@ -940,9 +977,11 @@ void OMX_MediaProcessor::mediaDecoding() { if (m_state != STATE_PAUSED) m_threshold = std::min(2.0f*m_threshold, 16.0f); - CLog::Log(LOGDEBUG, "Pause %.2f,%.2f (%d,%d,%d,%d) %.2f\n", audio_fifo, video_fifo, audio_fifo_low, video_fifo_low, audio_fifo_high, video_fifo_high, m_threshold); - log_verbose("Buffering completed. Resuming..."); + log_verbose("Pause %.2f,%.2f (%d,%d,%d,%d) %.2f\n", + audio_fifo, video_fifo, audio_fifo_low, video_fifo_low, audio_fifo_high, video_fifo_high, m_threshold); + m_av_clock->OMXPause(); + setMediaStatus(OMX_MediaStatus::MEDIA_STATUS_BUFFERING); } } #endif @@ -950,9 +989,9 @@ void OMX_MediaProcessor::mediaDecoding() if (UNLIKELY(!sentStarted)) { - CLog::Log(LOGDEBUG, "COMXPlayer::HandleMessages - player started RESET"); + log_verbose("COMXPlayer::HandleMessages - player started RESET"); m_av_clock->OMXReset(m_has_video, m_has_audio); - m_av_clock->OMXStateExecute(); + //m_av_clock->OMXStateExecute(); sentStarted = true; } @@ -1056,9 +1095,9 @@ void OMX_MediaProcessor::mediaDecoding() m_incrMs = -(mediaTime ? DVD_TIME_TO_MSEC(mediaTime) : last_seek_pos); m_seekFlush = true; - flushStreams(DVD_NOPTS_VALUE); + //flushStreams(DVD_NOPTS_VALUE); m_provider->flush(); - m_player_video->Reset(); + //m_player_video->Reset(); setState(STATE_STOPPED); emit playbackCompleted(); diff --git a/piomxtextures_src/omx_mediaprocessor.h b/piomxtextures_src/omx_mediaprocessor.h index e7029e4..a3fcf02 100644 --- a/piomxtextures_src/omx_mediaprocessor.h +++ b/piomxtextures_src/omx_mediaprocessor.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -138,6 +139,7 @@ class OMX_MediaProcessor : public QObject bool hasAudio(); bool hasVideo(); + bool isSeekable(); qint64 streamLength(); @@ -167,13 +169,15 @@ public slots: bool seek(qint64 position); signals: + void streamLengthChanged(qint64 length); void metadataChanged(const QVariantMap metadata); void playbackStarted(); void playbackCompleted(); void errorOccurred(OMX_MediaProcessor::OMX_MediaProcessorError error); void stateChanged(OMX_MediaProcessor::OMX_MediaProcessorState state); void mediaStatusChanged(OMX_MediaProcessor::OMX_MediaStatus status); - void streamLengthChanged(qint64 length); + void bufferStatusChanged(int percentage); + void availablePlaybackRangesChanged(QMediaTimeRange ranges); private slots: void init(); @@ -193,8 +197,8 @@ private slots: void flushStreams(double pts); void convertMetaData(); - QThread* m_thread; - QString m_filename; + OMX_QThread* m_thread; + QString m_sourceUrl; AVFormatContext* fmt_ctx; AVStream* streamVideo; diff --git a/piomxtextures_src/omx_omxplayer_logging.cpp b/piomxtextures_src/omx_omxplayer_logging.cpp index 85b38fc..6097bee 100644 --- a/piomxtextures_src/omx_omxplayer_logging.cpp +++ b/piomxtextures_src/omx_omxplayer_logging.cpp @@ -53,6 +53,8 @@ #include "omx_logging.h" +#define ENABLE_OMXPLAYER_LOGS + /*------------------------------------------------------------------------------ | definitions +-----------------------------------------------------------------------------*/ diff --git a/piomxtextures_src/omxplayer_lib/OMXCore.cpp b/piomxtextures_src/omxplayer_lib/OMXCore.cpp index 05cf56f..2fe5274 100644 --- a/piomxtextures_src/omxplayer_lib/OMXCore.cpp +++ b/piomxtextures_src/omxplayer_lib/OMXCore.cpp @@ -46,7 +46,7 @@ #define log_lock log_disabled // lcarlon: temporary implementation. -QMutex COMXCoreComponent::m_mxOmx(QMutex::Recursive); +QSemaphore COMXCoreComponent::m_mxOmx(2); /*------------------------------------------------------------------------------ | COMXCoreComponent::testOmx @@ -55,32 +55,44 @@ bool COMXCoreComponent::testOmx() { // Try to lock and timeout in 1s. log_debug("Testing OpenMAX health..."); - const bool alive = m_mxOmx.tryLock(1000); + const bool alive = m_mxOmx.tryAcquire(); if (alive) - m_mxOmx.unlock(); + m_mxOmx.release(); + + if (alive) { + log_debug("OpenMAX seems healthy :-)"); + return true; + } - if (alive) - return log_debug("OpenMAX seems healthy :-)"); return log_warn("OpenMAX seems dead ;-("); } +#include +//static QElapsedTimer g_elapsedLock; + /*------------------------------------------------------------------------------ | lock_mutex +-----------------------------------------------------------------------------*/ -inline void lock_mutex(QMutex* m) +inline void lock_mutex(QSemaphore* m) { log_lock("Waiting for lock %p...", m); - m->lock(); + m->acquire(); log_lock("Got lock %p...", m); + + //g_elapsedLock.start(); } /*------------------------------------------------------------------------------ | unlock_mutex +-----------------------------------------------------------------------------*/ -inline void unlock_mutex(QMutex* m) +inline void unlock_mutex(QSemaphore* m) { log_lock("Releasing lock %p...", m); - m->unlock(); + m->release(); + + //log_warn("Elpsed: %lld.", g_elapsedLock.elapsed()); + //if (g_elapsedLock.elapsed() > 30) + // log_stacktrace(LC_LOG_INFO, 100); } #endif // OMX_THREAD_UNSAFE @@ -875,7 +887,8 @@ OMX_ERRORTYPE COMXCoreComponent::FreeInputBuffers() WaitForInputDone(1000); pthread_mutex_lock(&m_omx_input_mutex); - assert(m_omx_input_buffers.size() == m_omx_input_avaliable.size()); + if (m_omx_input_buffers.size() != m_omx_input_avaliable.size()) + log_err("m_omx_input_buffers.size() != m_omx_input_avaliable.size()"); m_omx_input_buffers.clear(); @@ -1284,22 +1297,28 @@ OMX_ERRORTYPE COMXCoreComponent::GetConfig(OMX_INDEXTYPE configIndex, OMX_PTR co const #endif // OMX_THREAD_UNSAFE { -#ifdef OMX_THREAD_UNSAFE - // lcarlon - QMutexLocker locker(&m_mxOmx); -#endif // OMX_THREAD_UNSAFE - if(!m_handle) return OMX_ErrorUndefined; OMX_ERRORTYPE omx_err; +#ifdef OMX_THREAD_UNSAFE + // lcarlon + lock_mutex(&m_mxOmx); +#endif // OMX_THREAD_UNSAFE + omx_err = OMX_GetConfig(m_handle, configIndex, configStruct); if(omx_err != OMX_ErrorNone) { CLog::Log(LOGERROR, "COMXCoreComponent::GetConfig - %s failed with omx_err(0x%x)\n", m_componentName.c_str(), omx_err); } + +#ifdef OMX_THREAD_UNSAFE + // lcarlon + unlock_mutex(&m_mxOmx); +#endif // OMX_THREAD_UNSAFE + return omx_err; } diff --git a/piomxtextures_src/omxplayer_lib/OMXCore.h b/piomxtextures_src/omxplayer_lib/OMXCore.h index 85db721..9094dcd 100644 --- a/piomxtextures_src/omxplayer_lib/OMXCore.h +++ b/piomxtextures_src/omxplayer_lib/OMXCore.h @@ -33,10 +33,10 @@ #include -//#define OMX_THREAD_UNSAFE +#define OMX_THREAD_UNSAFE #ifdef OMX_THREAD_UNSAFE -#include +#include #endif // OMX_THREAD_UNSAFE //////////////////////////////////////////////////////////////////////////////////////////// @@ -224,7 +224,7 @@ class COMXCoreComponent bool m_resource_error; #ifdef OMX_THREAD_UNSAFE - static QMutex m_mxOmx; + static QSemaphore m_mxOmx; #endif // OMX_THREAD_UNSAFE // lcarlon: keep during merges. diff --git a/piomxtextures_src/omxplayer_lib/linux/RBP.cpp b/piomxtextures_src/omxplayer_lib/linux/RBP.cpp index 0fc0bbb..9ccf46b 100644 --- a/piomxtextures_src/omxplayer_lib/linux/RBP.cpp +++ b/piomxtextures_src/omxplayer_lib/linux/RBP.cpp @@ -24,6 +24,9 @@ #define CLASSNAME "CRBP" +int CRBP::m_refcount = 0; +QMutex CRBP::m_mutex; + CRBP::CRBP() { m_initialized = false; @@ -38,17 +41,29 @@ CRBP::~CRBP() bool CRBP::Initialize() { + QMutexLocker l(&m_mutex); + if (m_refcount > 0) + return true; + m_initialized = m_DllBcmHost->Load(); if(!m_initialized) return false; + log_info("bcm_host_init"); m_DllBcmHost->bcm_host_init(); + m_refcount++; return true; } void CRBP::Deinitialize() { + QMutexLocker l(&m_mutex); + m_refcount--; + if (m_refcount > 0) + return; + + log_info("bcm_host_deinit"); m_DllBcmHost->bcm_host_deinit(); if(m_initialized) diff --git a/piomxtextures_src/omxplayer_lib/linux/RBP.h b/piomxtextures_src/omxplayer_lib/linux/RBP.h index ed15e0c..2b75170 100644 --- a/piomxtextures_src/omxplayer_lib/linux/RBP.h +++ b/piomxtextures_src/omxplayer_lib/linux/RBP.h @@ -42,6 +42,10 @@ #define HAVE_VMCS_CONFIG #endif +#include + +#include "omx_logging.h" + #include "DllBCM.h" class CRBP @@ -56,6 +60,9 @@ class CRBP private: DllBcmHost *m_DllBcmHost; bool m_initialized; + + static int m_refcount; + static QMutex m_mutex; }; extern CRBP g_RBP; diff --git a/piomxtextures_src/piomxtextures_src.pri b/piomxtextures_src/piomxtextures_src.pri index 516219e..78f9ea4 100644 --- a/piomxtextures_src/piomxtextures_src.pri +++ b/piomxtextures_src/piomxtextures_src.pri @@ -21,7 +21,7 @@ # along with PiOmxTextures. If not, see . # -QT += core core-private gui gui-private opengl quick quick-private +QT += core core-private gui gui-private opengl quick quick-private multimedia SRC=$$PWD SRC_WRAPPER=$$SRC/omx_wrapper diff --git a/piomxtextures_tools/ffmpeg_test.c b/piomxtextures_tools/ffmpeg_test.c new file mode 100644 index 0000000..989c128 --- /dev/null +++ b/piomxtextures_tools/ffmpeg_test.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2014 Stefano Sabatini + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/** + * @file + * libavformat AVIOContext API example. + * + * Make libavformat demuxer access media content through a custom + * AVIOContext read callback. + * @example avio_reading.c + */ +#include +#include +#include +#include + +struct buffer_data { + uint8_t *ptr; + size_t size; ///< size left in the buffer +}; + +static int read_packet(void *opaque, uint8_t *buf, int buf_size) +{ + struct buffer_data *bd = (struct buffer_data *)opaque; + buf_size = FFMIN(buf_size, bd->size); + printf("ptr:%p size:%zu\n", bd->ptr, bd->size); + /* copy internal buffer data to buf */ + memcpy(buf, bd->ptr, buf_size); + bd->ptr += buf_size; + bd->size -= buf_size; + return buf_size; +} + +int test(int argc, char* const argv[]) +{ + AVFormatContext *fmt_ctx = NULL; + AVIOContext *avio_ctx = NULL; + uint8_t *buffer = NULL, *avio_ctx_buffer = NULL; + size_t buffer_size, avio_ctx_buffer_size = 4096; + char *input_filename = NULL; + int ret = 0; + + if (argc != 2) { + fprintf(stderr, "usage: %s input_file\n" + "API example program to show how to read from a custom buffer " + "accessed through AVIOContext.\n", argv[0]); + return 1; + } + + input_filename = argv[1]; + + /* register codecs and formats and other lavf/lavc components*/ + av_register_all(); + av_log_set_level(AV_LOG_INFO); + + if (!(fmt_ctx = avformat_alloc_context())) { + ret = AVERROR(ENOMEM); + goto end; + } + + fmt_ctx->flags |= AVFMT_FLAG_NONBLOCK; + + avio_ctx_buffer = (uint8_t*)av_malloc(avio_ctx_buffer_size); + if (!avio_ctx_buffer) { + ret = AVERROR(ENOMEM); + goto end; + } + + ret = avformat_open_input(&fmt_ctx, input_filename, NULL, NULL); + if (ret < 0) { + fprintf(stderr, "Could not open input\n"); + goto end; + } + + ret = avformat_find_stream_info(fmt_ctx, NULL); + if (ret < 0) { + fprintf(stderr, "Could not find stream information\n"); + goto end; + } + + av_dump_format(fmt_ctx, 0, input_filename, 0); + +end: + avformat_close_input(&fmt_ctx); + /* note: the internal buffer could have changed, and be != avio_ctx_buffer */ + if (avio_ctx) { + av_freep(&avio_ctx->buffer); + av_freep(&avio_ctx); + } + //av_file_unmap(buffer, buffer_size); + if (ret < 0) { + char error[1000]; + char* s = av_make_error_string(error, 1000, ret); + fprintf(stderr, "Error occurred: %s\n", s); + return 1; + } + + return 0; +} + +int main(int argc, char** argv) +{ + char* const argv2[] = {"", argv[1]}; + int i = 0; + for (i = 0; 1; i++) { + fprintf(stderr, "Iteration %d...\n", i); + test(2, argv2); + } + + return 0; +}