1 /*
2 * Strawberry Music Player
3 * This file was part of Clementine.
4 * Copyright 2010, David Sansome <me@davidsansome.com>
5 * Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
6 *
7 * Strawberry is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * Strawberry is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22 #ifndef TRANSCODER_H
23 #define TRANSCODER_H
24
25 #include "config.h"
26
27 #include <memory>
28 #include <glib.h>
29 #include <glib-object.h>
30 #include <gst/gst.h>
31
32 #include <QObject>
33 #include <QList>
34 #include <QMap>
35 #include <QMetaType>
36 #include <QSet>
37 #include <QString>
38 #include <QEvent>
39
40 #include "core/song.h"
41
42 struct TranscoderPreset {
TranscoderPresetTranscoderPreset43 explicit TranscoderPreset() : filetype_(Song::FileType_Unknown) {}
44 TranscoderPreset(const Song::FileType filetype, const QString &name, const QString &extension, const QString &codec_mimetype, const QString &muxer_mimetype_ = QString());
45
46 Song::FileType filetype_;
47 QString name_;
48 QString extension_;
49 QString codec_mimetype_;
50 QString muxer_mimetype_;
51 };
Q_DECLARE_METATYPE(TranscoderPreset)52 Q_DECLARE_METATYPE(TranscoderPreset)
53
54 class Transcoder : public QObject {
55 Q_OBJECT
56
57 public:
58 explicit Transcoder(QObject *parent = nullptr, const QString &settings_postfix = "");
59
60 static TranscoderPreset PresetForFileType(const Song::FileType filetype);
61 static QList<TranscoderPreset> GetAllPresets();
62 static Song::FileType PickBestFormat(const QList<Song::FileType> &supported);
63
64 int max_threads() const { return max_threads_; }
65 void set_max_threads(int count) { max_threads_ = count; }
66
67 static QString GetFile(const QString &input, const TranscoderPreset &preset, const QString &output = QString());
68 void AddJob(const QString &input, const TranscoderPreset &preset, const QString &output);
69
70 QMap<QString, float> GetProgress() const;
71 int QueuedJobsCount() const { return queued_jobs_.count(); }
72
73 public slots:
74 void Start();
75 void Cancel();
76
77 signals:
78 void JobComplete(QString input, QString output, bool success);
79 void LogLine(QString message);
80 void AllJobsComplete();
81
82 protected:
83 bool event(QEvent *e) override;
84
85 private:
86 // The description of a file to transcode - lives in the main thread.
87 struct Job {
88 QString input;
89 QString output;
90 TranscoderPreset preset;
91 };
92
93 // State held by a job and shared across gstreamer callbacks - lives in the job's thread.
94 struct JobState {
95 explicit JobState(const Job &job, Transcoder *parent)
96 : job_(job),
97 parent_(parent),
98 pipeline_(nullptr),
99 convert_element_(nullptr) {}
100 ~JobState();
101
102 void PostFinished(const bool success);
103 void ReportError(GstMessage *msg) const;
104
105 Job job_;
106 Transcoder *parent_;
107 GstElement *pipeline_;
108 GstElement *convert_element_;
109 private:
110 Q_DISABLE_COPY(JobState)
111 };
112
113 // Event passed from a GStreamer callback to the Transcoder when a job finishes.
114 struct JobFinishedEvent : public QEvent {
115 explicit JobFinishedEvent(JobState *state, bool success);
116
117 static int sEventType;
118
119 JobState *state_;
120 bool success_;
121 private:
122 Q_DISABLE_COPY(JobFinishedEvent)
123 };
124
125 enum StartJobStatus {
126 StartedSuccessfully,
127 FailedToStart,
128 NoMoreJobs,
129 AllThreadsBusy,
130 };
131
132 StartJobStatus MaybeStartNextJob();
133 bool StartJob(const Job &job);
134
135 GstElement *CreateElement(const QString &factory_name, GstElement *bin = nullptr, const QString &name = QString());
136 GstElement *CreateElementForMimeType(const QString &element_type, const QString &mime_type, GstElement *bin = nullptr);
137 void SetElementProperties(const QString &name, GObject *object);
138
139 static void NewPadCallback(GstElement*, GstPad *pad, gpointer data);
140 static GstBusSyncReply BusCallbackSync(GstBus*, GstMessage *msg, gpointer data);
141
142 private:
143 typedef QList<std::shared_ptr<JobState>> JobStateList;
144
145 int max_threads_;
146 QList<Job> queued_jobs_;
147 JobStateList current_jobs_;
148 QString settings_postfix_;
149 };
150
151 #endif // TRANSCODER_H
152