Документация
ОС Аврора 5.1.0
Файл примера videosource.cpp
declarative-decoder/videosource.cpp
/****************************************************************************
**
** Copyright (C) 2023 Open Mobile Platform LLC
**
** This file is part of the examples of the QtVideoChat component.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Open Mobile Platform LLC nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "videosource.h"
VideoSource::VideoSource(QObject *parent)
: QObject(parent)
, m_eos(false)
, m_reader()
, m_parser(&m_reader)
, m_sink(nullptr)
{
connect(&m_timer, &QTimer::timeout, this, &VideoSource::pull);
connect(&m_reader, &H264Reader::errorChanged, this, &VideoSource::onReaderErrorChanged);
connect(&m_parser, &H264Parser::videoSettingsChanged,
this, &VideoSource::onVideoSettingsChanged);
}
VideoSource::~VideoSource()
{
if (m_sink)
m_sink->unlink(this);
}
QString VideoSource::path() const
{
return m_source ? m_source->path() : QString();
}
void VideoSource::setPath(const QString &path)
{
qDebug() << path;
m_timer.stop();
if (m_source) {
m_reader.setData(QByteArray());
m_source.clear();
}
if (m_sink && m_sink->isActive())
m_sink->stop();
m_source = QSharedPointer<FileSource>(new FileSource(path));
if (!m_source->open()) {
m_source.clear();
qCritical() << "Couldn't open input file!";
return;
}
m_eos = false;
m_reader.setData(m_source->data());
m_parser.reset();
start();
}
bool VideoSource::addSink(QVCSink *abstractSink)
{
QVCEncodedVideoSink *sink = dynamic_cast<QVCEncodedVideoSink*>(abstractSink);
if (!sink) {
qCritical() << "Invalid video sink";
return false;
}
if (m_sink)
m_sink->unlink(this);
m_sink = sink;
if (m_sink && m_timer.isActive() && !m_encoderSettings.isNull())
m_sink->start(m_encoderSettings);
return true;
}
bool VideoSource::removeSink(QVCSink *sink)
{
Q_ASSERT(m_sink == sink);
m_sink = nullptr;
return true;
}
void VideoSource::sinkActiveChanged(QVCSink *sink, bool active)
{
qDebug() << active;
Q_ASSERT(m_sink == sink);
if (!active && m_eos)
emit stopped();
}
void VideoSource::start()
{
// Имитация прямой трансляции 30 кадров в секунду.
unsigned int interval = 1000 / 30;
const char *framePeriod = getenv("FRAME_PERIOD");
if (framePeriod)
interval = QString(framePeriod).toInt();
m_timer.setInterval(interval);
m_timer.start();
}
void VideoSource::pull()
{
QVCEncodedVideoFrame frame = m_parser.readFrame();
if (frame.isValid()) {
if (m_sink)
m_sink->encodedVideoFrame(frame);
} else {
endOfFile();
}
}
void VideoSource::endOfFile()
{
m_eos = true;
m_timer.stop();
if (m_sink && m_sink->isActive())
m_sink->drain();
}
void VideoSource::onReaderErrorChanged(H264Reader::Error err)
{
qInfo() << err;
}
void VideoSource::onVideoSettingsChanged(const QVideoEncoderSettings &settings)
{
qInfo() << settings.codec() << settings.resolution();
m_encoderSettings = settings;
if (m_sink) {
if (m_sink->isActive())
m_sink->stop();
m_sink->start(settings);
}
}