Документация
ОС Аврора 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);
    }
}

Мы используем cookies для персонализации сайта и его более удобного использования. Вы можете запретить cookies в настройках браузера.

Пожалуйста ознакомьтесь с политикой использования cookies.