PonyPlayer
dispatcher.hpp
浏览该文件的文档.
1//
2// Created by ColorsWind on 2022/4/30.
3// Adapted from demuxer v1 by kurisu on 2022/4/16.
4//
5#pragma once
6
7#include <QtCore>
8#include <QTimer>
9#include <unordered_map>
10#include <vector>
11#include "ponyplayer.h"
12#include "helper.hpp"
13#include "frame.hpp"
14#include "twins_queue.hpp"
15#include "forward.hpp"
16#include "backward.hpp"
17#include "audioformat.hpp"
18#include "virtual.hpp"
19
20INCLUDE_FFMPEG_BEGIN
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>
27
28//#define IGNORE_VIDEO_FRAME
29
30namespace PonyPlayer {
31 Q_NAMESPACE
35 AUDIO
36 };
37
38 Q_ENUM_NS(OpenFileResultType)
39}
40
41
43private:
44 int index;
45 std::unordered_map<std::string, std::string> dict;
46 qreal duration;
47public:
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;
52 }
53 duration = static_cast<double>(stream->duration) * av_q2d(stream->time_base);
54 }
55
56 [[nodiscard]] qreal getDuration() const { return duration; }
57
58 [[nodiscard]] QString getFriendName() const {
59 QString str;
60 if (auto iter = dict.find("language"); iter != dict.cend()) {
61 str.append(iter->second.c_str());
62 str.append(" | ");
63 }
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"));
68 return str;
69 }
70
71 [[nodiscard]] int getIndex() const { return index; }
72
73};
74
75typedef unsigned int StreamIndex;
76const constexpr StreamIndex DEFAULT_STREAM_INDEX = std::numeric_limits<StreamIndex>::max();
77
81class DemuxDispatcherBase : public QObject {
82Q_OBJECT
83public:
84 const std::string filename;
85protected:
86 AVFormatContext *fmtCtx = nullptr;
87 bool isAudio = false;
88
89 explicit DemuxDispatcherBase(const std::string &fn, QObject *parent) : QObject(parent), filename(fn) {
90 auto surfix = fn.substr(fn.rfind('.')+1);
91 if (surfix == "mp3" || surfix == "wav")
92 isAudio = true;
93 if (avformat_open_input(&fmtCtx, fn.c_str(), nullptr, nullptr) < 0) {
94 throw std::runtime_error("Cannot open input file.");
95 }
96 if (avformat_find_stream_info(fmtCtx, nullptr) < 0) {
97 throw std::runtime_error("Cannot find any stream in file.");
98 }
99 }
100
102 if (fmtCtx) { avformat_close_input(&fmtCtx); }
103 }
104
105public:
107
109
111
112 virtual void flush() {NOT_IMPLEMENT_YET}
113
115
117
119
120 virtual void seek(qreal secs) {NOT_IMPLEMENT_YET}
121
122 PONY_THREAD_SAFE virtual VideoFrameRef getPicture() {NOT_IMPLEMENT_YET}
123
124 PONY_THREAD_SAFE virtual qreal frontPicture() {NOT_IMPLEMENT_YET}
125
126 virtual int skipPicture(const std::function<bool(qreal)> &function) {NOT_IMPLEMENT_YET}
127
128 PONY_THREAD_SAFE virtual AudioFrame getSample() {NOT_IMPLEMENT_YET}
129
130 PONY_THREAD_SAFE virtual qreal frontSample() {NOT_IMPLEMENT_YET}
131
132 virtual int skipSample(const std::function<bool(qreal)> &function) {NOT_IMPLEMENT_YET}
133
134 virtual void setTrack(int i) {NOT_IMPLEMENT_YET}
135
137
138 virtual void setEnableAudio(bool enable) {NOT_IMPLEMENT_YET}
139
141
142 virtual void setAudioOutputFormat(PonyAudioFormat format) = 0;
143
144 virtual void test_onWork() = 0;
145};
146
152Q_OBJECT
153private:
154 struct {
155 qreal videoDuration = std::numeric_limits<qreal>::quiet_NaN();
156 qreal audioDuration = std::numeric_limits<qreal>::quiet_NaN();
157 std::vector<StreamIndex> m_videoStreamsIndex;
158 std::vector<StreamIndex> m_audioStreamsIndex;
159 std::vector<StreamInfo> streamInfos;
160 } description;
161 TwinsBlockQueue<AVFrame *> *videoQueue;
162 TwinsBlockQueue<AVFrame *> *audioQueue;
163 StreamIndex m_audioStreamIndex;
164 StreamIndex m_videoStreamIndex;
165 IDemuxDecoder *m_audioDecoder;
166 IDemuxDecoder *videoDecoder;
167
168 std::atomic<bool> interrupt = true;
169 AVPacket *packet = nullptr;
170
171public:
173 const std::string &fn,
175 StreamIndex audioStreamIndex = DEFAULT_STREAM_INDEX,
176 StreamIndex videoStreamIndex = DEFAULT_STREAM_INDEX,
177 QObject *parent = nullptr
178 ) : DemuxDispatcherBase(fn, parent), m_audioStreamIndex(audioStreamIndex), m_videoStreamIndex(videoStreamIndex) {
179 packet = av_packet_alloc();
180 for (StreamIndex i = 0; i < fmtCtx->nb_streams; ++i) {
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);
186 }
187 StreamInfo info(stream);
188 description.streamInfos.emplace_back(stream);
189 }
190
191 // audio
192 if (description.m_audioStreamsIndex.empty()) {
194 throw std::runtime_error("Cannot find audio stream.");
195 }
196 if (m_audioStreamIndex ==
197 DEFAULT_STREAM_INDEX) { m_audioStreamIndex = description.m_audioStreamsIndex.front(); }
198 audioQueue = new TwinsBlockQueue<AVFrame *>("AudioQueue", 16);
199 m_audioDecoder = new DecoderImpl<Audio>(fmtCtx->streams[m_audioStreamIndex], audioQueue);
200 description.audioDuration = m_audioDecoder->duration();
201
202 // video
203 videoQueue = audioQueue->twins("VideoQueue", 16);
204 if (isAudio) {
205 // no video
206 qDebug() << "audio only";
207 if (!description.m_videoStreamsIndex.empty())
208 m_videoStreamIndex = description.m_videoStreamsIndex.front();
209 videoDecoder = new VirtualVideoDecoder(description.audioDuration);
211 } else {
213 if (m_videoStreamIndex ==
214 DEFAULT_STREAM_INDEX) { m_videoStreamIndex = description.m_videoStreamsIndex.front(); }
215 videoDecoder = new DecoderImpl<Video>(fmtCtx->streams[m_videoStreamIndex], videoQueue);
216 }
217 description.videoDuration = videoDecoder->duration();
218 connect(this, &DecodeDispatcher::signalStartWorker, this, &DecodeDispatcher::onWork, Qt::QueuedConnection);
219 }
220
221 ~DecodeDispatcher() override {
222 qDebug() << "Destroy decode dispatcher " << filename.c_str();
224 delete audioQueue;
225 delete videoQueue;
226 delete m_audioDecoder;
227 delete videoDecoder;
228 if (packet) { av_packet_free(&packet); }
229 }
230
234 void statePause() override {
235 interrupt = true;
236 videoQueue->close();
237 qDebug() << "Queue close.";
238 }
239
240 void flush() override {
241 videoQueue->clear([](AVFrame *frame) { av_frame_free(&frame); });
242 audioQueue->clear([](AVFrame *frame) { av_frame_free(&frame); });
243 }
244
245
249 void stateResume() override {
250 if (interrupt.exchange(false)) {
251 videoQueue->open();
252 emit signalStartWorker(QPrivateSignal());
253 qDebug() << "Queue stateResume.";
254 }
255 // ignore when already start
256
257 }
258
263 void seek(qreal secs) override {
264 // case 1: currently decoding, interrupt
265 // case 2: not decoding, seek
266 interrupt = true;
267 qDebug() << "a Seek:" << secs;
268 int ret = av_seek_frame(fmtCtx, -1, static_cast<int64_t>(secs * AV_TIME_BASE), AVSEEK_FLAG_BACKWARD);
269 if (m_audioDecoder) { m_audioDecoder->flushFFmpegBuffers(); }
270 if (videoDecoder) { videoDecoder->flushFFmpegBuffers(); }
271 if (ret != 0) { qWarning() << "Error av_seek_frame:" << ffmpegErrToString(ret); }
272 }
273
274 PONY_THREAD_SAFE VideoFrameRef getPicture() override { return videoDecoder->getPicture(); }
275
276 PONY_THREAD_SAFE qreal frontPicture() override { return videoDecoder->viewFront(); }
277
278 PONY_THREAD_SAFE int skipPicture(const std::function<bool(qreal)> &predicate) override {
279 return videoDecoder->skip(predicate);
280 }
281
282 PONY_THREAD_SAFE AudioFrame getSample() override { return m_audioDecoder->getSample(); }
283
284 PONY_THREAD_SAFE qreal frontSample() override { return m_audioDecoder->viewFront(); }
285
286 PONY_THREAD_SAFE int skipSample(const std::function<bool(qreal)> &predicate) override {
287 return m_audioDecoder->skip(predicate);
288 }
289
291
292 [[nodiscard]] qreal getAudionLength() const { return description.audioDuration; }
293
295
296 [[nodiscard]] qreal getVideoLength() const { return description.videoDuration; }
297
299
300 void setTrack(int i) override {
301 delete m_audioDecoder;
302 m_audioStreamIndex = description.m_audioStreamsIndex[static_cast<size_t>(i)];
303 auto stream = fmtCtx->streams[m_audioStreamIndex];
304 m_audioDecoder = new DecoderImpl<Audio>(stream, audioQueue);
305 }
306
308
309 QStringList getTracks() {
310 QStringList ret;
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());
314 }
315 return ret;
316 }
317
319
321 if (i == m_audioStreamIndex) { return; }
322 delete m_audioDecoder;
323 m_audioStreamIndex = i;
324 m_audioDecoder = new DecoderImpl<Audio>(fmtCtx->streams[m_audioStreamIndex], audioQueue);
325 }
326
328
329 bool hasVideo() override {
330 return !isAudio;
331 }
332
334
335 void setEnableAudio(bool enable) override {
336 m_audioDecoder->setEnable(enable);
337 }
338
340 return m_audioDecoder->getInputFormat();
341 }
342
343 void setAudioOutputFormat(PonyAudioFormat format) override {
344 m_audioDecoder->setOutputFormat(format);
345 }
346
347 void test_onWork() override {
348 onWork();
349 }
350
351private slots:
352
353 void onWork() {
354 videoQueue->open();
355 while (!interrupt) {
356 int ret = av_read_frame(fmtCtx, packet);
357 if (ret == 0) {
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);
362 }
363 } else if (ret == ERROR_EOF) {
364 videoQueue->push(nullptr);
365 audioQueue->push(nullptr);
366 av_packet_unref(packet);
367 break;
368 } else {
369 qWarning() << "Error av_read_frame:" << ffmpegErrToString(ret);
370 }
371 av_packet_unref(packet);
372 }
373 interrupt = true;
374 };
375
376
377signals:
378
379 void signalStartWorker(QPrivateSignal);
380};
381
387Q_OBJECT
389private:
390 struct {
391 qreal videoDuration = std::numeric_limits<qreal>::quiet_NaN();
392 qreal audioDuration = std::numeric_limits<qreal>::quiet_NaN();
393 std::vector<StreamIndex> m_videoStreamsIndex;
394 std::vector<StreamIndex> m_audioStreamsIndex;
395 std::vector<StreamInfo> streamInfos;
396 } description;
397
398 StreamIndex m_audioStreamIndex;
399 StreamIndex m_videoStreamIndex;
400
401 const qreal interval = 5.0;
402
403 AVStream *videoStream{};
404 AVStream *audioStream{};
405
406 IDemuxDecoder *videoDecoder;
407 IDemuxDecoder *m_audioDecoder;
408 IDemuxDecoder *primary;
409
410 std::atomic<bool> interrupt = true;
411 AVPacket *packet = nullptr;
412 TwinsBlockQueue<AVFrame *> *videoQueue;
413 TwinsBlockQueue<AVFrame *> *audioQueue;
414public:
415 explicit ReverseDecodeDispatcher(const std::string &fn,
416 QObject *parent = nullptr
417 ) : DemuxDispatcherBase(fn, parent), m_audioStreamIndex(DEFAULT_STREAM_INDEX), m_videoStreamIndex(DEFAULT_STREAM_INDEX) {
418 packet = av_packet_alloc();
419 for (StreamIndex i = 0; i < fmtCtx->nb_streams; ++i) {
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);
425 }
426 StreamInfo info(stream);
427 description.streamInfos.emplace_back(stream);
428 }
429
430 // audio
431 if (description.m_audioStreamsIndex.empty()) {
432 throw std::runtime_error("Cannot find audio stream.");
433 }
434 if (m_audioStreamIndex ==
435 DEFAULT_STREAM_INDEX) { m_audioStreamIndex = description.m_audioStreamsIndex.front(); }
436
437 audioQueue = new TwinsBlockQueue<AVFrame *>("AudioQueue", 200);
438
439 m_audioDecoder = new ReverseDecoderImpl<Audio>(fmtCtx->streams[m_audioStreamIndex], audioQueue);
440 description.audioDuration = m_audioDecoder->duration();
441
442 // video
443 videoQueue = audioQueue->twins("VideoQueue", 200);
444 if (isAudio) {
445 // no video
446 qDebug() << "audio only";
447 if (!description.m_videoStreamsIndex.empty())
448 m_videoStreamIndex = description.m_videoStreamsIndex.front();
449 videoDecoder = new VirtualVideoDecoder(description.audioDuration);
450 videoQueue->setEnable(false);
451 m_audioDecoder->setFollower(m_audioDecoder);
452 primary = m_audioDecoder;
453 } else {
454 if (m_videoStreamIndex ==
455 DEFAULT_STREAM_INDEX) { m_videoStreamIndex = description.m_videoStreamsIndex.front(); }
456 videoDecoder = new ReverseDecoderImpl<Video>(fmtCtx->streams[m_videoStreamIndex], videoQueue);
457 videoDecoder->setFollower(m_audioDecoder);
458 primary = videoDecoder;
459 }
460 description.videoDuration = videoDecoder->duration();
461
462 connect(this, &ReverseDecodeDispatcher::signalStartWorker, this, &ReverseDecodeDispatcher::onWork,
463 Qt::QueuedConnection);
464 }
465
467 qDebug() << "Destroy decode dispatcher " << filename.c_str();
469 delete audioQueue;
470 delete videoQueue;
471 delete m_audioDecoder;
472 delete videoDecoder;
473 if (packet) { av_packet_free(&packet); }
474 }
475
479 PONY_THREAD_SAFE void statePause() override {
480 interrupt = true;
481 videoQueue->close();
482 qDebug() << "Queue close.";
483 }
484
485 PONY_THREAD_SAFE void flush() override {
486 auto freeFunc = [](AVFrame *frame) {
487 if (frame) av_frame_free(&frame);
488 };
489 videoQueue->clear(freeFunc);
490 audioQueue->clear(freeFunc);
491 videoDecoder->clearFrameStack();
492 m_audioDecoder->clearFrameStack();
493 }
494
495
499 PONY_THREAD_SAFE void stateResume() override {
500 interrupt = false;
501 videoQueue->open();
502 emit signalStartWorker(QPrivateSignal());
503 qDebug() << "Queue stateResume.";
504 }
505
511
512 void seek(qreal secs) override {
513 // case 1: currently decoding, interrupt
514 // case 2: not decoding, seek
515 interrupt = true;
516 videoDecoder->flushFFmpegBuffers();
517 m_audioDecoder->flushFFmpegBuffers();
518 qDebug() << "a Seek:" << secs;
519 secs = fmax(secs, 0.0);
520 videoDecoder->setStart(secs);
521 m_audioDecoder->setStart(secs);
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); }
525 }
526
527 PONY_THREAD_SAFE VideoFrameRef getPicture() override { return videoDecoder->getPicture(); }
528
529 PONY_THREAD_SAFE qreal frontPicture() override { return videoDecoder->viewFront(); }
530
531 PONY_THREAD_SAFE AudioFrame getSample() override { return m_audioDecoder->getSample(); }
532
533 PONY_THREAD_SAFE qreal frontSample() override {NOT_IMPLEMENT_YET}
534
536
537 void setEnableAudio(bool enable) override { m_audioDecoder->setEnable(enable); }
538
539 PonyAudioFormat getAudioInputFormat() override { // TODO: IMPLEMENT LATER
540 return m_audioDecoder->getInputFormat();
541 }
542
543 void setAudioOutputFormat(PonyAudioFormat format) override { // TODO: IMPLEMENT LATER
544 m_audioDecoder->setOutputFormat(format);
545 }
546
547 bool hasVideo() override {
548 return !isAudio;
549 }
550
551 void test_onWork() override {
552 onWork();
553 }
554
556 void setTrack(int i) override {
557 delete m_audioDecoder;
558 m_audioStreamIndex = description.m_audioStreamsIndex[static_cast<size_t>(i)];
559 auto stream = fmtCtx->streams[m_audioStreamIndex];
560 m_audioDecoder = new ReverseDecoderImpl<Audio>(stream, audioQueue);
561 if (hasVideo())
562 videoDecoder->setFollower(m_audioDecoder);
563 else {
564 m_audioDecoder->setFollower(m_audioDecoder);
565 primary = m_audioDecoder;
566 }
567 }
568
570 QStringList getTracks() {
571 QStringList ret;
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());
575 }
576 return ret;
577 }
578
581 if (i == m_audioStreamIndex) { return; }
582 delete m_audioDecoder;
583 m_audioStreamIndex = i;
584 m_audioDecoder = new ReverseDecoderImpl<Audio>(fmtCtx->streams[m_audioStreamIndex], audioQueue);
585 if (hasVideo())
586 videoDecoder->setFollower(m_audioDecoder);
587 else {
588 m_audioDecoder->setFollower(m_audioDecoder);
589 primary = m_audioDecoder;
590 }
591 }
592
593private slots:
594
595 void onWork() {
596 videoQueue->open();
597 while (!interrupt) {
598 int ret = av_read_frame(fmtCtx, packet);
599 if (ret == 0) {
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);
604 }
605 } else if (ret == ERROR_EOF) {
606 //std::cerr << "reverse reach eof" << std::endl;
607 qDebug() << "reverse: reach eof";
608 videoDecoder->flushFFmpegBuffers();
609 m_audioDecoder->flushFFmpegBuffers();
610 av_seek_frame(fmtCtx, -1,
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);
615 } else {
616 qWarning() << "Error av_read_frame:" << ffmpegErrToString(ret);
617 }
618 av_packet_unref(packet);
619 auto next = primary->nextSegment();
620 if (next > 0) {
621 //std::cerr << "next: " << next << std::endl;
622 videoDecoder->setStart(next);
623 m_audioDecoder->setStart(next);
624 videoDecoder->flushFFmpegBuffers();
625 m_audioDecoder->flushFFmpegBuffers();
626 av_seek_frame(fmtCtx, -1,
627 static_cast<int64_t>((next - interval) * AV_TIME_BASE),
628 AVSEEK_FLAG_BACKWARD);
629 } else if (next == 0) {
630 //std::cerr << "reverse: finish" << std::endl;
631 av_packet_unref(packet);
632 videoQueue->push(nullptr);
633 audioQueue->push(nullptr);
634 qDebug() << "reverse: reach starting pointing";
635 break;
636 }
637 }
638 interrupt = true;
639 };
640
641signals:
642
643 void signalStartWorker(QPrivateSignal);
644};
645
646
647
648
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: audioformat.hpp:97
反向解码器调度器
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: frame.hpp:47
虚拟视频播放, 用于视频纯音频文件.
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