276 lines
9.9 KiB
C++
276 lines
9.9 KiB
C++
/******************************************************************************
|
|
QtAV: Multimedia framework based on Qt and FFmpeg
|
|
Copyright (C) 2012-2016 Wang Bin <wbsecg1@gmail.com>
|
|
|
|
* This file is part of QtAV (from 2014)
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 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
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
******************************************************************************/
|
|
#ifndef QTAV_SUBTITLE_H
|
|
#define QTAV_SUBTITLE_H
|
|
#include "SubImage.h>
|
|
#include <QtCore/QObject>
|
|
#include <QtCore/QStringList>
|
|
#include <QtCore/QUrl>
|
|
#include <QtGui/QImage>
|
|
/*
|
|
* to avoid read error, subtitle size > 10*1024*1024 will be ignored.
|
|
*/
|
|
namespace FAV {
|
|
|
|
#if !(DO_NOT_USE_SUBTITLE)
|
|
|
|
class Q_AV_EXPORT SubtitleFrame
|
|
{
|
|
public:
|
|
SubtitleFrame() :
|
|
begin(0)
|
|
, end(0)
|
|
{}
|
|
// valied: begin < end
|
|
bool isValid() const { return begin < end;}
|
|
operator bool() const { return isValid();}
|
|
bool operator !() const { return !isValid();}
|
|
inline bool operator <(const SubtitleFrame& f) const { return end < f.end;}
|
|
inline bool operator <(qreal t) const { return end < t;}
|
|
qreal begin;
|
|
qreal end;
|
|
QString text; //plain text. always valid
|
|
};
|
|
|
|
class Q_AV_EXPORT Subtitle : public QObject
|
|
{
|
|
Q_OBJECT
|
|
Q_PROPERTY(QByteArray codec READ codec WRITE setCodec NOTIFY codecChanged)
|
|
// QList<SubtitleProcessorId>
|
|
Q_PROPERTY(QStringList engines READ engines WRITE setEngines NOTIFY enginesChanged)
|
|
Q_PROPERTY(QString engine READ engine NOTIFY engineChanged)
|
|
Q_PROPERTY(bool fuzzyMatch READ fuzzyMatch WRITE setFuzzyMatch NOTIFY fuzzyMatchChanged)
|
|
Q_PROPERTY(QByteArray rawData READ rawData WRITE setRawData NOTIFY rawDataChanged)
|
|
Q_PROPERTY(QString fileName READ fileName WRITE setFileName NOTIFY fileNameChanged)
|
|
Q_PROPERTY(QStringList dirs READ dirs WRITE setDirs NOTIFY dirsChanged)
|
|
Q_PROPERTY(QStringList suffixes READ suffixes WRITE setSuffixes NOTIFY suffixesChanged)
|
|
Q_PROPERTY(QStringList supportedSuffixes READ supportedSuffixes NOTIFY supportedSuffixesChanged)
|
|
Q_PROPERTY(qreal timestamp READ timestamp WRITE setTimestamp)
|
|
Q_PROPERTY(qreal delay READ delay WRITE setDelay NOTIFY delayChanged)
|
|
Q_PROPERTY(QString text READ getText)
|
|
Q_PROPERTY(bool loaded READ isLoaded)
|
|
Q_PROPERTY(bool canRender READ canRender NOTIFY canRenderChanged)
|
|
// font properties for libass engine
|
|
Q_PROPERTY(QString fontFile READ fontFile WRITE setFontFile NOTIFY fontFileChanged)
|
|
Q_PROPERTY(QString fontsDir READ fontsDir WRITE setFontsDir NOTIFY fontsDirChanged)
|
|
Q_PROPERTY(bool fontFileForced READ isFontFileForced WRITE setFontFileForced NOTIFY fontFileForcedChanged)
|
|
public:
|
|
explicit Subtitle(QObject *parent = 0);
|
|
virtual ~Subtitle();
|
|
/*!
|
|
* \brief setCodec
|
|
* set subtitle encoding that supported by QTextCodec. You have to call load() to manually reload the subtitle with given codec
|
|
* \param value codec name. see QTextCodec.availableCodecs(). Empty value means using the default codec in QTextCodec
|
|
* If linked with libchardet(https://github.com/cnangel/libchardet) or can dynamically load it,
|
|
* set value of "AutoDetect" to detect the charset of subtitle
|
|
*/
|
|
void setCodec(const QByteArray& value);
|
|
QByteArray codec() const;
|
|
/*!
|
|
* \brief isValid
|
|
* indicate whether the subtitle can be found and processed
|
|
* \return
|
|
*/
|
|
bool isLoaded() const;
|
|
/*!
|
|
* \brief setEngines
|
|
* Set subtitle processor engine names, in priority order. When loading a subtitle, use the engines
|
|
* one by one until a usable engine is found.
|
|
* \param value
|
|
*/
|
|
void setEngines(const QStringList& value);
|
|
QStringList engines() const;
|
|
/*!
|
|
* \brief engine
|
|
* \return The engine in use for current subtitle
|
|
*/
|
|
QString engine() const;
|
|
void setFuzzyMatch(bool value);
|
|
bool fuzzyMatch() const;
|
|
void setRawData(const QByteArray& data);
|
|
QByteArray rawData() const;
|
|
/*!
|
|
* \brief setFileName
|
|
* the given name will be in the 1st place to try to open(if using fuzzy match). then files in suffixes() order
|
|
* or in processor's supported suffixes order
|
|
* \param name
|
|
*/
|
|
void setFileName(const QString& name);
|
|
QString fileName() const;
|
|
/*!
|
|
* \brief setDirs
|
|
* Set subtitle search directories. Video's dir will always be added.
|
|
*/
|
|
void setDirs(const QStringList& value);
|
|
QStringList dirs() const;
|
|
/*!
|
|
* \brief supportedFormats
|
|
* the suffix names supported by all engines. for example ["ass", "ssa"]
|
|
* \return
|
|
*/
|
|
QStringList supportedSuffixes() const;
|
|
/*!
|
|
* \brief setSuffixes
|
|
* default is using SubtitleProcessor. Empty equals default value. But suffixes() will return empty.
|
|
*/
|
|
void setSuffixes(const QStringList& value);
|
|
QStringList suffixes() const;
|
|
|
|
qreal timestamp() const;
|
|
/*!
|
|
* \brief delay
|
|
* unit: second
|
|
* The subtitle from getText() and getImage() is at the time: timestamp() + delay()
|
|
* \return
|
|
*/
|
|
qreal delay() const;
|
|
void setDelay(qreal value);
|
|
/*!
|
|
* \brief canRender
|
|
* wether current processor supports rendering. Check before getImage()
|
|
* \return
|
|
*/
|
|
bool canRender() const;
|
|
// call setTimestamp before getText/Image
|
|
//plain text. separated by '\n' if more more than 1 text rects found
|
|
QString getText() const;
|
|
/*!
|
|
* \brief getImage
|
|
* Get a subtitle image with given (video) frame size. The result image size usually smaller than
|
|
* given frame size because subtitle are lines of text. The boundingRect indicates the actual
|
|
* image position and size relative to given size.
|
|
* The result image format is QImage::Format_ARGB32
|
|
* \return empty image if no image, or subtitle processor does not support renderering
|
|
*/
|
|
QImage getImage(int width, int height, QRect* boundingRect = 0);
|
|
SubImageSet getSubImages(int width, int height, QRect* boundingRect = 0);
|
|
// used for embedded subtitles.
|
|
/*!
|
|
* \brief processHeader
|
|
* Always called if switch to a new internal subtitle stream. But header data can be empty
|
|
* Used by libass to set style etc.
|
|
*/
|
|
bool processHeader(const QByteArray &codec, const QByteArray& data);
|
|
// ffmpeg decodes subtitle lines and call processLine. if AVPacket contains plain text, no decoding is ok
|
|
bool processLine(const QByteArray& data, qreal pts = -1, qreal duration = 0);
|
|
|
|
QString fontFile() const;
|
|
void setFontFile(const QString& value);
|
|
/*!
|
|
* \brief fontsDir
|
|
* Not tested for dwrite provider. FontConfig can work.
|
|
*/
|
|
QString fontsDir() const;
|
|
void setFontsDir(const QString& value);
|
|
bool isFontFileForced() const;
|
|
void setFontFileForced(bool value);
|
|
public Q_SLOTS:
|
|
/*!
|
|
* \brief start
|
|
* start to process the whole subtitle content in a thread
|
|
*/
|
|
void load();
|
|
void loadAsync();
|
|
void setTimestamp(qreal t);
|
|
Q_SIGNALS:
|
|
// TODO: also add to AVPlayer?
|
|
/// empty path if load from raw data
|
|
void loaded(const QString& path = QString());
|
|
void canRenderChanged();
|
|
void codecChanged();
|
|
void enginesChanged();
|
|
void fuzzyMatchChanged();
|
|
/*!
|
|
* \brief contentChanged
|
|
* emitted when text content changed.
|
|
*/
|
|
void contentChanged();
|
|
void rawDataChanged();
|
|
void fileNameChanged();
|
|
void dirsChanged();
|
|
void suffixesChanged();
|
|
void supportedSuffixesChanged();
|
|
void engineChanged();
|
|
void delayChanged();
|
|
void fontFileChanged();
|
|
void fontsDirChanged();
|
|
void fontFileForcedChanged();
|
|
private:
|
|
void checkCapability();
|
|
class Private;
|
|
Private *priv;
|
|
};
|
|
|
|
// internal use
|
|
class Q_AV_EXPORT SubtitleAPIProxy {
|
|
public:
|
|
SubtitleAPIProxy(QObject* obj);
|
|
void setSubtitle(Subtitle *sub);
|
|
// API from Subtitle
|
|
/*!
|
|
* \brief setCodec
|
|
* set subtitle encoding that supported by QTextCodec. subtitle will be reloaded
|
|
* \param value codec name. see QTextCodec.availableCodecs(). Empty value means using the default codec in QTextCodec
|
|
*/
|
|
void setCodec(const QByteArray& value);
|
|
QByteArray codec() const;
|
|
bool isLoaded() const;
|
|
void setEngines(const QStringList& value);
|
|
QStringList engines() const;
|
|
QString engine() const;
|
|
void setFuzzyMatch(bool value);
|
|
bool fuzzyMatch() const;
|
|
//always use exact file path by setFile(). file name is used internally
|
|
//void setFileName(const QString& name);
|
|
//QString fileName() const;
|
|
void setDirs(const QStringList& value);
|
|
QStringList dirs() const;
|
|
QStringList supportedSuffixes() const;
|
|
void setSuffixes(const QStringList& value);
|
|
QStringList suffixes() const;
|
|
bool canRender() const; // TODO: rename to capability()
|
|
qreal delay() const;
|
|
void setDelay(qreal value);
|
|
|
|
QString fontFile() const;
|
|
void setFontFile(const QString& value);
|
|
QString fontsDir() const;
|
|
void setFontsDir(const QString& value);
|
|
bool isFontFileForced() const;
|
|
void setFontFileForced(bool value);
|
|
|
|
// API from PlayerSubtitle
|
|
/*
|
|
void setFile(const QString& file);
|
|
QString file() const;
|
|
void setAutoLoad(bool value);
|
|
bool autoLoad() const;
|
|
*/
|
|
private:
|
|
QObject *m_obj;
|
|
Subtitle *m_s;
|
|
};
|
|
|
|
#endif // #if !(DO_NOT_USE_SUBTITLE)
|
|
|
|
} //namespace FAV
|
|
#endif // QTAV_SUBTITLE_H
|