first commit
This commit is contained in:
249
project/fm_viewer/fav/AVDemuxer.h
Normal file
249
project/fm_viewer/fav/AVDemuxer.h
Normal file
@@ -0,0 +1,249 @@
|
||||
/******************************************************************************
|
||||
QtAV: Media play library based on Qt and FFmpeg
|
||||
Copyright (C) 2012-2016 Wang Bin <wbsecg1@gmail.com>
|
||||
|
||||
* This file is part of QtAV
|
||||
|
||||
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 QAV_DEMUXER_H
|
||||
#define QAV_DEMUXER_H
|
||||
|
||||
#include "AVError.h"
|
||||
#include "Packet.h"
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QScopedPointer>
|
||||
|
||||
struct AVFormatContext;
|
||||
struct AVCodecContext;
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QIODevice;
|
||||
QT_END_NAMESPACE
|
||||
// TODO: force codec name. clean code
|
||||
namespace FAV {
|
||||
class AVError;
|
||||
class MediaIO;
|
||||
class Q_AV_EXPORT AVDemuxer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum StreamType { //TODO: move to common MediaType
|
||||
AudioStream,
|
||||
VideoStream,
|
||||
#if !(DO_NOT_USE_SUBTITLE)
|
||||
SubtitleStream,
|
||||
#endif
|
||||
};
|
||||
static const QStringList& supportedFormats();
|
||||
static const QStringList& supportedExtensions();
|
||||
/// Supported ffmpeg/libav input protocols(not complete). A static string list
|
||||
static const QStringList& supportedProtocols();
|
||||
|
||||
AVDemuxer(QObject *parent = 0);
|
||||
~AVDemuxer();
|
||||
|
||||
int playerID;
|
||||
#if (REAR_SYNC_FRONT)
|
||||
double rear_delay;
|
||||
#endif
|
||||
|
||||
qint64 _lastDuration;
|
||||
#if (FIXED_FPS_DURATION)
|
||||
qint64 durationFixed;
|
||||
qint32 frameCount;
|
||||
#if (FORCE_BREAK_EOF)
|
||||
qint64 endFilePosition; // 시간(DTS/PTS)으로 EOF 처리 불가능함 -> 파일 포지션으로 처리
|
||||
#endif // FORCE_BREAK_EOF
|
||||
#if (PREVENT_OVER_DURATION_RENDER)
|
||||
qint64 originalDuraiont; // VideoThread 에 전달하여 원 재생시간 이상의 경우 DRAW 하지 않도록 변경
|
||||
#endif // PREVENT_OVER_DURATION_RENDER
|
||||
#endif //FIXED_FPS_DURATION
|
||||
|
||||
qint32 realVideoStreamCount; ///!< 실제(프레임이 존재하는) 비디오 스트림 개수
|
||||
|
||||
#if (PLAY_SYNC_FIX2)
|
||||
qint64 frameDuration; // 각 프레임당 길이(SEEK 및 SLIDER BAR 계산시 durationFixed - frameDuration 으로 사용)
|
||||
#endif // PLAY_SYNC_FIX2
|
||||
|
||||
MediaStatus mediaStatus() const;
|
||||
bool atEnd() const;
|
||||
QString fileName() const;
|
||||
QIODevice* ioDevice() const;
|
||||
/// not null for QIODevice, custom protocols
|
||||
MediaIO* mediaIO() const;
|
||||
/*!
|
||||
* \brief setMedia
|
||||
* \return whether the media source is changed
|
||||
*/
|
||||
bool setMedia(const QString& fileName);
|
||||
bool setMedia(QIODevice* dev);
|
||||
bool setMedia(MediaIO* in);
|
||||
/*!
|
||||
* \brief setFormat
|
||||
* Force the input format. Useful if input stream is a raw video stream(fmt="rawvideo).
|
||||
* formatForced() is reset if media changed. So you have to call setFormat() for every media
|
||||
* you want to force the format.
|
||||
* If AVFormatContext.format_whitelist contains only 1 format, then that format will be forced.
|
||||
* For example, setOptions({"format_whitelist": "rawvideo"})
|
||||
*/
|
||||
void setFormat(const QString& fmt);
|
||||
QString formatForced() const;
|
||||
bool load();
|
||||
bool unload();
|
||||
bool isLoaded() const;
|
||||
/*!
|
||||
* \brief readFrame
|
||||
* Read a packet from 1 of the streams. use packet() to get the result packet. packet() returns last valid packet.
|
||||
* So do not use packet() if readFrame() failed.
|
||||
* Call readFrame() and seek() in the same thread.
|
||||
* \return true if no error. false if error occurs, eof reaches, interrupted by user or time out(getInterruptTimeout())
|
||||
*/
|
||||
bool readFrame(); // TODO: rename int readPacket(), return stream number
|
||||
/*!
|
||||
* \brief packet
|
||||
* return the packet read by demuxer. packet is invalid if readFrame() returns false.
|
||||
*/
|
||||
Packet packet() const;
|
||||
/*!
|
||||
* \brief stream
|
||||
* Current readFrame() readed stream index.
|
||||
*/
|
||||
int stream() const;
|
||||
|
||||
bool isSeekable() const; // TODO: change in unload?
|
||||
void setSeekUnit(SeekUnit unit);
|
||||
SeekUnit seekUnit() const;
|
||||
void setSeekType(SeekType target);
|
||||
SeekType seekType() const;
|
||||
/*!
|
||||
* \brief seek
|
||||
* seek to a given position. Only support timestamp seek now.
|
||||
* Experiment: if pos is out of range (>duration()), do nothing unless a seekable and variableSize MediaIO is used.
|
||||
* \return false if fail
|
||||
*/
|
||||
bool seek(qint64 pos); //pos: ms
|
||||
/*!
|
||||
* \brief seek
|
||||
* Percentage seek. duration() must be >0LL
|
||||
* \param q [0, 1]
|
||||
* TODO: what if duration() is not valid but size is known?
|
||||
*/
|
||||
bool seek(qreal q);
|
||||
AVFormatContext* formatContext();
|
||||
QString formatName() const;
|
||||
QString formatLongName() const;
|
||||
// TODO: rename startPosition()
|
||||
qint64 startTime() const; //ms, AVFormatContext::start_time/1000
|
||||
qint64 duration() const; //ms, AVFormatContext::duration/1000
|
||||
qint64 startTimeUs() const; //us, AVFormatContext::start_time
|
||||
qint64 durationUs() const; //us, AVFormatContext::duration
|
||||
qint64 durationUSAudio() const; // Audio duration
|
||||
//total bit rate
|
||||
int bitRate() const; //AVFormatContext::bit_rate
|
||||
qreal frameRate() const; //deprecated AVStream::avg_frame_rate
|
||||
// if stream is -1, return the current video(or audio if no video) stream.
|
||||
// TODO: audio/videoFrames?
|
||||
qint64 frames(int stream = -1) const; //AVFormatContext::nb_frames
|
||||
bool hasAttacedPicture() const;
|
||||
/*!
|
||||
* \brief setStreamIndex
|
||||
* Set stream by index in stream list. call it after loaded.
|
||||
* Stream/index will not change in next load() unless media source changed
|
||||
* index < 0 is invalid
|
||||
*/
|
||||
bool setStreamIndex(StreamType st, int index);
|
||||
// current open stream
|
||||
int currentStream(StreamType st) const;
|
||||
QList<int> streams(StreamType st) const;
|
||||
// TODO: stream(StreamType), streams(StreamType)
|
||||
// current open stream
|
||||
int audioStream() const;
|
||||
QList<int> audioStreams() const;
|
||||
int videoStream() const;
|
||||
QList<int> videoStreams() const;
|
||||
int subtitleStream() const;
|
||||
QList<int> subtitleStreams() const;
|
||||
//codec. stream < 0: the stream going to play (or the stream set by setStreamIndex())
|
||||
AVCodecContext* audioCodecContext(int stream = -1) const;
|
||||
AVCodecContext* videoCodecContext(int stream = -1) const;
|
||||
AVCodecContext* subtitleCodecContext(int stream = -1) const;
|
||||
/**
|
||||
* @brief getInterruptTimeout return the interrupt timeout
|
||||
*/
|
||||
qint64 getInterruptTimeout() const;
|
||||
/**
|
||||
* @brief setInterruptTimeout set the interrupt timeout
|
||||
* @param timeout in ms
|
||||
*/
|
||||
void setInterruptTimeout(qint64 timeout);
|
||||
bool isInterruptOnTimeout() const;
|
||||
void setInterruptOnTimeout(bool value);
|
||||
/**
|
||||
* @brief getInterruptStatus return the interrupt status.
|
||||
* \return -1: interrupted by user
|
||||
* 0: not interrupted
|
||||
* >0: timeout value of AVError::ErrorCode
|
||||
*/
|
||||
int getInterruptStatus() const;
|
||||
/**
|
||||
* @brief setInterruptStatus set the interrupt status
|
||||
* @param interrupt <0: abort current operation like loading and reading packets.
|
||||
* 0: no interrupt
|
||||
*/
|
||||
void setInterruptStatus(int interrupt);
|
||||
/*!
|
||||
* \brief setOptions
|
||||
* libav's AVDictionary. we can ignore the flags used in av_dict_xxx because we can use hash api.
|
||||
* empty value does nothing to current context if it is open, but will change AVDictionary options to null in next open.
|
||||
* AVDictionary is used in avformat_open_input() and will not change unless user call setOptions()
|
||||
* If an option is not found
|
||||
*/
|
||||
void setOptions(const QVariantHash &dict);
|
||||
QVariantHash options() const;
|
||||
Q_SIGNALS:
|
||||
void unloaded();
|
||||
void userInterrupted(); // NO direct connection because it's emit before interrupted happens
|
||||
void loaded();
|
||||
// emit when the first frame is read
|
||||
void started();
|
||||
void finished(); //end of file
|
||||
void error(const FAV::AVError& e); //explictly use FAV::AVError in connection for Qt4 syntax
|
||||
void mediaStatusChanged(FAV::MediaStatus status);
|
||||
void seekableChanged();
|
||||
#if (FIXED_FPS_DURATION)
|
||||
void mediaEnded();
|
||||
#endif
|
||||
|
||||
private:
|
||||
void setMediaStatus(MediaStatus status);
|
||||
// error code (errorCode) and message (msg) may be modified internally
|
||||
void handleError(int averr, AVError::ErrorCode* errorCode, QString& msg);
|
||||
|
||||
class Private;
|
||||
QScopedPointer<Private> d;
|
||||
class InterruptHandler;
|
||||
friend class InterruptHandler;
|
||||
|
||||
#if (FIXED_FPS_DURATION)
|
||||
|
||||
void _loadDuration();
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
} //namespace FAV
|
||||
#endif // QAV_DEMUXER_H
|
||||
Reference in New Issue
Block a user