9#include <unordered_map>
21#include <libavformat/avformat.h>
22#include <libavcodec/avcodec.h>
23#include <libavutil/error.h>
24#include <libswresample/swresample.h>
25#include <libavutil/imgutils.h>
45 std::unordered_map<std::string, std::string> dict;
48 explicit StreamInfo(AVStream *stream) : index(stream->index) {
49 AVDictionaryEntry *tag =
nullptr;
50 while ((tag = av_dict_get(stream->metadata,
"", tag, AV_DICT_IGNORE_SUFFIX))) {
51 dict[tag->key] = tag->value;
53 duration =
static_cast<double>(stream->duration) * av_q2d(stream->time_base);
60 if (
auto iter = dict.find(
"language"); iter != dict.cend()) {
61 str.append(iter->second.c_str());
64 auto minutes =
static_cast<int>(duration) / 60;
65 auto seconds = duration - minutes * 60;
66 if (minutes > 0) {
str.append(QString::number(minutes)).append(
"m"); }
67 str.append(QString::number(seconds,
'f', 1).append(
"s"));
71 [[nodiscard]]
int getIndex()
const {
return index; }
90 auto surfix = fn.substr(fn.rfind(
'.')+1);
91 if (surfix ==
"mp3" || surfix ==
"wav")
93 if (avformat_open_input(&
fmtCtx, fn.c_str(),
nullptr,
nullptr) < 0) {
94 throw std::runtime_error(
"Cannot open input file.");
96 if (avformat_find_stream_info(
fmtCtx,
nullptr) < 0) {
97 throw std::runtime_error(
"Cannot find any stream in file.");
168 std::atomic<bool> interrupt =
true;
169 AVPacket *packet =
nullptr;
173 const std::string &fn,
177 QObject *parent =
nullptr
178 ) :
DemuxDispatcherBase(fn, parent), m_audioStreamIndex(audioStreamIndex), m_videoStreamIndex(videoStreamIndex) {
179 packet = av_packet_alloc();
181 auto *stream =
fmtCtx->streams[i];
182 if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
183 description.m_videoStreamsIndex.emplace_back(i);
184 }
else if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
185 description.m_audioStreamsIndex.emplace_back(i);
188 description.streamInfos.emplace_back(stream);
192 if (description.m_audioStreamsIndex.empty()) {
194 throw std::runtime_error(
"Cannot find audio stream.");
196 if (m_audioStreamIndex ==
200 description.audioDuration = m_audioDecoder->
duration();
203 videoQueue = audioQueue->
twins(
"VideoQueue", 16);
206 qDebug() <<
"audio only";
207 if (!description.m_videoStreamsIndex.empty())
208 m_videoStreamIndex = description.m_videoStreamsIndex.front();
213 if (m_videoStreamIndex ==
217 description.videoDuration = videoDecoder->
duration();
222 qDebug() <<
"Destroy decode dispatcher " <<
filename.c_str();
226 delete m_audioDecoder;
228 if (packet) { av_packet_free(&packet); }
237 qDebug() <<
"Queue close.";
241 videoQueue->
clear([](AVFrame *frame) { av_frame_free(&frame); });
242 audioQueue->
clear([](AVFrame *frame) { av_frame_free(&frame); });
250 if (interrupt.exchange(
false)) {
253 qDebug() <<
"Queue stateResume.";
263 void seek(qreal secs)
override {
267 qDebug() <<
"a Seek:" << secs;
268 int ret = av_seek_frame(
fmtCtx, -1,
static_cast<int64_t
>(secs * AV_TIME_BASE), AVSEEK_FLAG_BACKWARD);
271 if (ret != 0) { qWarning() <<
"Error av_seek_frame:" <<
ffmpegErrToString(ret); }
278 PONY_THREAD_SAFE
int skipPicture(
const std::function<
bool(qreal)> &predicate)
override {
279 return videoDecoder->
skip(predicate);
286 PONY_THREAD_SAFE
int skipSample(
const std::function<
bool(qreal)> &predicate)
override {
287 return m_audioDecoder->
skip(predicate);
301 delete m_audioDecoder;
302 m_audioStreamIndex = description.m_audioStreamsIndex[
static_cast<size_t>(i)];
303 auto stream =
fmtCtx->streams[m_audioStreamIndex];
311 ret.reserve(
static_cast<qsizetype
>(description.m_audioStreamsIndex.size()));
312 for (
auto &&i: description.m_audioStreamsIndex) {
313 ret.emplace_back(description.streamInfos[i].getFriendName());
321 if (i == m_audioStreamIndex) {
return; }
322 delete m_audioDecoder;
323 m_audioStreamIndex = i;
356 int ret = av_read_frame(
fmtCtx, packet);
358 if (
static_cast<StreamIndex>(packet->stream_index) == m_videoStreamIndex) {
359 videoDecoder->
accept(packet, interrupt);
360 }
else if (
static_cast<StreamIndex>(packet->stream_index) == m_audioStreamIndex) {
361 m_audioDecoder->
accept(packet, interrupt);
364 videoQueue->
push(
nullptr);
365 audioQueue->
push(
nullptr);
366 av_packet_unref(packet);
371 av_packet_unref(packet);
401 const qreal interval = 5.0;
403 AVStream *videoStream{};
404 AVStream *audioStream{};
410 std::atomic<bool> interrupt =
true;
411 AVPacket *packet =
nullptr;
416 QObject *parent =
nullptr
418 packet = av_packet_alloc();
420 auto *stream =
fmtCtx->streams[i];
421 if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
422 description.m_videoStreamsIndex.emplace_back(i);
423 }
else if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
424 description.m_audioStreamsIndex.emplace_back(i);
427 description.streamInfos.emplace_back(stream);
431 if (description.m_audioStreamsIndex.empty()) {
432 throw std::runtime_error(
"Cannot find audio stream.");
434 if (m_audioStreamIndex ==
440 description.audioDuration = m_audioDecoder->
duration();
443 videoQueue = audioQueue->
twins(
"VideoQueue", 200);
446 qDebug() <<
"audio only";
447 if (!description.m_videoStreamsIndex.empty())
448 m_videoStreamIndex = description.m_videoStreamsIndex.front();
452 primary = m_audioDecoder;
454 if (m_videoStreamIndex ==
458 primary = videoDecoder;
460 description.videoDuration = videoDecoder->
duration();
463 Qt::QueuedConnection);
467 qDebug() <<
"Destroy decode dispatcher " <<
filename.c_str();
471 delete m_audioDecoder;
473 if (packet) { av_packet_free(&packet); }
482 qDebug() <<
"Queue close.";
485 PONY_THREAD_SAFE
void flush()
override {
486 auto freeFunc = [](AVFrame *frame) {
487 if (frame) av_frame_free(&frame);
489 videoQueue->
clear(freeFunc);
490 audioQueue->
clear(freeFunc);
503 qDebug() <<
"Queue stateResume.";
512 void
seek(qreal secs)
override {
518 qDebug() <<
"a Seek:" << secs;
519 secs = fmax(secs, 0.0);
522 int ret = av_seek_frame(
fmtCtx, -1,
static_cast<int64_t
>((secs - interval) * AV_TIME_BASE),
523 AVSEEK_FLAG_BACKWARD);
524 if (ret != 0) { qWarning() <<
"Error av_seek_frame:" <<
ffmpegErrToString(ret); }
557 delete m_audioDecoder;
558 m_audioStreamIndex = description.m_audioStreamsIndex[
static_cast<size_t>(i)];
559 auto stream =
fmtCtx->streams[m_audioStreamIndex];
565 primary = m_audioDecoder;
572 ret.reserve(
static_cast<qsizetype
>(description.m_audioStreamsIndex.size()));
573 for (
auto &&i: description.m_audioStreamsIndex) {
574 ret.emplace_back(description.streamInfos[i].getFriendName());
581 if (i == m_audioStreamIndex) {
return; }
582 delete m_audioDecoder;
583 m_audioStreamIndex = i;
589 primary = m_audioDecoder;
598 int ret = av_read_frame(
fmtCtx, packet);
600 if (
static_cast<StreamIndex>(packet->stream_index) == m_videoStreamIndex) {
601 videoDecoder->
accept(packet, interrupt);
602 }
else if (
static_cast<StreamIndex>(packet->stream_index) == m_audioStreamIndex) {
603 m_audioDecoder->
accept(packet, interrupt);
607 qDebug() <<
"reverse: reach eof";
611 static_cast<int64_t
>((description.audioDuration - 2 * interval) * AV_TIME_BASE),
612 AVSEEK_FLAG_BACKWARD);
613 videoDecoder->
setStart(description.audioDuration - interval);
614 m_audioDecoder->
setStart(description.audioDuration - interval);
618 av_packet_unref(packet);
627 static_cast<int64_t
>((next - interval) * AV_TIME_BASE),
628 AVSEEK_FLAG_BACKWARD);
629 }
else if (next == 0) {
631 av_packet_unref(packet);
632 videoQueue->
push(
nullptr);
633 audioQueue->
push(
nullptr);
634 qDebug() <<
"reverse: reach starting pointing";
Definition: frame.hpp:145
解码器调度器, 将Packet分配给解码器进一步解码成Frame 这个类是RAII的
Definition: dispatcher.hpp:151
PONY_THREAD_SAFE VideoFrameRef getPicture() override
Definition: dispatcher.hpp:274
qreal getAudionLength() const
Definition: dispatcher.hpp:292
void stateResume() override
Definition: dispatcher.hpp:249
PONY_THREAD_SAFE qreal frontPicture() override
Definition: dispatcher.hpp:276
PONY_THREAD_SAFE AudioFrame getSample() override
Definition: dispatcher.hpp:282
PONY_THREAD_SAFE int skipPicture(const std::function< bool(qreal)> &predicate) override
Definition: dispatcher.hpp:278
QStringList getTracks()
Definition: dispatcher.hpp:309
void setAudioIndex(StreamIndex i)
Definition: dispatcher.hpp:320
bool hasVideo() override
Definition: dispatcher.hpp:329
PonyAudioFormat getAudioInputFormat() override
Definition: dispatcher.hpp:339
std::vector< StreamIndex > m_audioStreamsIndex
Definition: dispatcher.hpp:158
PONY_THREAD_SAFE qreal frontSample() override
Definition: dispatcher.hpp:284
void setEnableAudio(bool enable) override
Definition: dispatcher.hpp:335
PONY_THREAD_SAFE int skipSample(const std::function< bool(qreal)> &predicate) override
Definition: dispatcher.hpp:286
std::vector< StreamInfo > streamInfos
Definition: dispatcher.hpp:159
void signalStartWorker(QPrivateSignal)
void setAudioOutputFormat(PonyAudioFormat format) override
Definition: dispatcher.hpp:343
DecodeDispatcher(const std::string &fn, PonyPlayer::OpenFileResultType &result, StreamIndex audioStreamIndex=DEFAULT_STREAM_INDEX, StreamIndex videoStreamIndex=DEFAULT_STREAM_INDEX, QObject *parent=nullptr)
Definition: dispatcher.hpp:172
qreal videoDuration
Definition: dispatcher.hpp:155
qreal getVideoLength() const
Definition: dispatcher.hpp:296
void seek(qreal secs) override
Definition: dispatcher.hpp:263
void setTrack(int i) override
Definition: dispatcher.hpp:300
void statePause() override
Definition: dispatcher.hpp:234
~DecodeDispatcher() override
Definition: dispatcher.hpp:221
void flush() override
Definition: dispatcher.hpp:240
void test_onWork() override
Definition: dispatcher.hpp:347
std::vector< StreamIndex > m_videoStreamsIndex
Definition: dispatcher.hpp:157
qreal audioDuration
Definition: dispatcher.hpp:156
Definition: forward.hpp:89
Definition: forward.hpp:151
Definition: dispatcher.hpp:81
virtual PONY_THREAD_SAFE qreal frontSample()
Definition: dispatcher.hpp:130
virtual void statePause()
Definition: dispatcher.hpp:108
bool isAudio
Definition: dispatcher.hpp:87
const std::string filename
Definition: dispatcher.hpp:84
~DemuxDispatcherBase() override
Definition: dispatcher.hpp:101
virtual void setTrack(int i)
Definition: dispatcher.hpp:134
virtual PONY_THREAD_SAFE VideoFrameRef getPicture()
Definition: dispatcher.hpp:122
virtual void seek(qreal secs)
Definition: dispatcher.hpp:120
virtual int skipPicture(const std::function< bool(qreal)> &function)
Definition: dispatcher.hpp:126
DemuxDispatcherBase(const std::string &fn, QObject *parent)
Definition: dispatcher.hpp:89
virtual void test_onWork()=0
virtual void setAudioOutputFormat(PonyAudioFormat format)=0
virtual void stateResume()
Definition: dispatcher.hpp:116
virtual PonyAudioFormat getAudioInputFormat()=0
AVFormatContext * fmtCtx
Definition: dispatcher.hpp:86
virtual void flush()
Definition: dispatcher.hpp:112
virtual int skipSample(const std::function< bool(qreal)> &function)
Definition: dispatcher.hpp:132
virtual PONY_THREAD_SAFE qreal frontPicture()
Definition: dispatcher.hpp:124
virtual void setEnableAudio(bool enable)
Definition: dispatcher.hpp:138
virtual PONY_THREAD_SAFE AudioFrame getSample()
Definition: dispatcher.hpp:128
virtual bool hasVideo()
Definition: dispatcher.hpp:136
Definition: decoders.hpp:22
virtual bool accept(AVPacket *pkt, std::atomic< bool > &interrupt)=0
virtual void setFollower(IDemuxDecoder *follower)
Definition: decoders.hpp:84
virtual VideoFrameRef getPicture()=0
virtual void setEnable(bool b)=0
virtual qreal viewFront()=0
virtual void setStart(qreal secs)
Definition: decoders.hpp:94
virtual PonyAudioFormat getInputFormat()=0
virtual void flushFFmpegBuffers()=0
virtual int skip(const std::function< bool(qreal)> &predicate)=0
virtual void clearFrameStack()
Definition: decoders.hpp:92
virtual double duration()=0
virtual AudioFrame getSample()=0
virtual qreal nextSegment()
Definition: decoders.hpp:96
virtual void setOutputFormat(const PonyAudioFormat &format)=0
反向解码器调度器
Definition: dispatcher.hpp:386
void setTrack(int i) override
Definition: dispatcher.hpp:556
std::vector< StreamIndex > m_audioStreamsIndex
Definition: dispatcher.hpp:394
std::vector< StreamIndex > m_videoStreamsIndex
Definition: dispatcher.hpp:393
bool hasVideo() override
Definition: dispatcher.hpp:547
void seek(qreal secs) override
Definition: dispatcher.hpp:512
PONY_THREAD_SAFE void stateResume() override
Definition: dispatcher.hpp:499
PONY_THREAD_SAFE VideoFrameRef getPicture() override
Definition: dispatcher.hpp:527
void setAudioOutputFormat(PonyAudioFormat format) override
Definition: dispatcher.hpp:543
PONY_THREAD_SAFE qreal frontSample() override
Definition: dispatcher.hpp:533
void setEnableAudio(bool enable) override
Definition: dispatcher.hpp:537
qreal audioDuration
Definition: dispatcher.hpp:392
PONY_THREAD_SAFE AudioFrame getSample() override
Definition: dispatcher.hpp:531
void setAudioIndex(StreamIndex i)
Definition: dispatcher.hpp:580
PONY_THREAD_SAFE void statePause() override
Definition: dispatcher.hpp:479
void signalStartWorker(QPrivateSignal)
~ReverseDecodeDispatcher() override
Definition: dispatcher.hpp:466
PONY_THREAD_SAFE qreal frontPicture() override
Definition: dispatcher.hpp:529
ReverseDecodeDispatcher(const std::string &fn, QObject *parent=nullptr)
Definition: dispatcher.hpp:415
qreal videoDuration
Definition: dispatcher.hpp:391
PonyAudioFormat getAudioInputFormat() override
Definition: dispatcher.hpp:539
std::vector< StreamInfo > streamInfos
Definition: dispatcher.hpp:395
QStringList getTracks()
Definition: dispatcher.hpp:570
PONY_THREAD_SAFE void flush() override
Definition: dispatcher.hpp:485
void test_onWork() override
Definition: dispatcher.hpp:551
Definition: backward.hpp:189
Definition: backward.hpp:155
Definition: dispatcher.hpp:42
int getIndex() const
Definition: dispatcher.hpp:71
QString getFriendName() const
Definition: dispatcher.hpp:58
qreal getDuration() const
Definition: dispatcher.hpp:56
StreamInfo(AVStream *stream)
Definition: dispatcher.hpp:48
联动队列. 用于单生产者多队列, 单消费者通信.
Definition: twins_queue.hpp:17
void open()
Definition: twins_queue.hpp:95
bool push(const T item)
Definition: twins_queue.hpp:101
void setEnable(bool b)
Definition: twins_queue.hpp:61
TwinsBlockQueue< T > * twins(const std::string &name, size_t prefer)
Definition: twins_queue.hpp:54
void close()
Definition: twins_queue.hpp:74
void clear(const std::function< void(T)> &freeFunc)
Definition: twins_queue.hpp:83
虚拟视频播放, 用于视频纯音频文件.
Definition: virtual.hpp:11
constexpr const StreamIndex DEFAULT_STREAM_INDEX
Definition: dispatcher.hpp:76
unsigned int StreamIndex
Definition: dispatcher.hpp:75
const int ERROR_EOF
Definition: helper.hpp:14
QString ffmpegErrToString(int err)
Definition: helper.hpp:21
Definition: audioformat.hpp:155
OpenFileResultType
Definition: dispatcher.hpp:32
@ VIDEO
打开的文件为视频文件
Definition: dispatcher.hpp:34
@ FAILED
打开文件失败
Definition: dispatcher.hpp:33
@ AUDIO
打开的文件为音频文件
Definition: dispatcher.hpp:35
constexpr PonyThread MAIN
Definition: ponyplayer.h:47
constexpr PonyThread DECODER
Definition: ponyplayer.h:46
constexpr PonyThread FRAME
Definition: ponyplayer.h:50
str
Definition: setup.py:37
#define INCLUDE_FFMPEG_END
Definition: ponyplayer.h:26
#define PONY_GUARD_BY(...)
Definition: ponyplayer.h:89
#define PONY_THREAD_AFFINITY(thread)
Definition: ponyplayer.h:95
#define NOT_IMPLEMENT_YET
Definition: ponyplayer.h:39