/
mpeg2fix.h
296 lines (258 loc) · 8.93 KB
/
mpeg2fix.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
// POSIX
#include <pthread.h>
// C++
#include <cstdlib>
#include "libmythbase/mythconfig.h"
extern "C"
{
//AVFormat/AVCodec
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
//libmpeg2
#if CONFIG_LIBMPEG2EXTERNAL
#include <mpeg2dec/mpeg2.h>
#else
#include "libmythmpeg2/mpeg2.h"
#endif
}
//replex
#include "external/replex/multiplex.h"
#include "external/replex/ringbuffer.h"
// Qt
#include <QMap>
#include <QList>
#include <QQueue>
#include <QStringList>
#include <QDateTime>
// MythTV
#include "libmythbase/programtypes.h"
#include "libmythtv/mythavutil.h"
// MythTranscode
#include "transcodedefs.h"
enum MPFListType {
MPF_TYPE_CUTLIST = 0,
MPF_TYPE_SAVELIST,
};
class MPEG2frame
{
public:
explicit MPEG2frame(int size);
~MPEG2frame();
void ensure_size(int size) const;
void set_pkt(AVPacket *newpkt) const;
AVPacket *m_pkt {nullptr};
bool m_isSequence {false};
bool m_isGop {false};
uint8_t *m_framePos {nullptr};
uint8_t *m_gopPos {nullptr};
mpeg2_sequence_t m_mpeg2_seq;
mpeg2_gop_t m_mpeg2_gop;
mpeg2_picture_t m_mpeg2_pic;
};
struct poq_idx_t {
int64_t newPTS;
int64_t pos_pts;
int framenum;
bool type;
};
class PTSOffsetQueue
{
public:
PTSOffsetQueue(int vidid, QList<int> keys, int64_t initPTS);
void SetNextPTS(int64_t newPTS, int64_t atPTS);
void SetNextPos(int64_t newPTS, AVPacket *pkt);
int64_t Get(int idx, AVPacket *pkt);
int64_t UpdateOrigPTS(int idx, int64_t &origPTS, AVPacket *pkt);
private:
QMap<int, QList<poq_idx_t> > m_offset;
QMap<int, QList<poq_idx_t> > m_orig;
QList<int> m_keyList;
int m_vidId;
};
//container for all multiplex related variables
using RingbufferArray = std::array<ringbuffer,N_AUDIO>;
using ExtTypeIntArray = std::array<int,N_AUDIO>;
using AudioFrameArray = std::array<audio_frame_t,N_AUDIO>;
class MPEG2replex
{
public:
MPEG2replex() = default;
~MPEG2replex();
void Start();
int WaitBuffers();
int m_done {0};
QString m_outfile;
int m_otype {0};
ringbuffer m_vrBuf {};
RingbufferArray m_extrbuf {};
ringbuffer m_indexVrbuf {};
RingbufferArray m_indexExtrbuf {};
int m_extCount {0};
ExtTypeIntArray m_exttype {0};
ExtTypeIntArray m_exttypcnt {0};
pthread_mutex_t m_mutex {};
pthread_cond_t m_cond {};
AudioFrameArray m_extframe {};
sequence_t m_seq_head {};
private:
multiplex_t *m_mplex {nullptr};
};
using FrameList = QList<MPEG2frame *>;
using FrameQueue = QQueue<MPEG2frame *>;
using FrameMap = QMap<int, FrameList *>;
class MPEG2fixup
{
public:
MPEG2fixup(const QString &inf, const QString &outf,
frm_dir_map_t *deleteMap, const char *fmt, bool norp,
bool fixPTS, int maxf, bool showprog, int otype,
void (*update_func)(float) = nullptr, int (*check_func)() = nullptr);
~MPEG2fixup();
int Start();
void AddRangeList(const QStringList& rangelist, int type);
static void ShowRangeMap(frm_dir_map_t *mapPtr, QString msg);
int BuildKeyframeIndex(const QString &file, frm_pos_map_t &posMap, frm_pos_map_t &durMap);
void SetAllAudio(bool keep) { m_allAudio = keep; }
static void dec2x33(int64_t *pts1, int64_t pts2);
static void inc2x33(int64_t *pts1, int64_t pts2);
static int64_t udiff2x33(int64_t pts1, int64_t pts2);
static int64_t diff2x33(int64_t pts1, int64_t pts2);
static int64_t add2x33(int64_t pts1, int64_t pts2);
static int cmp2x33(int64_t pts1, int64_t pts2);
protected:
static void *ReplexStart(void *data);
MPEG2replex m_rx;
private:
static int FindMPEG2Header(const uint8_t *buf, int size, uint8_t code);
void InitReplex();
void FrameInfo(MPEG2frame *f);
int AddFrame(MPEG2frame *f);
bool InitAV(const QString& inputfile, const char *type, int64_t offset);
void ScanAudio();
int ProcessVideo(MPEG2frame *vf, mpeg2dec_t *dec);
void WriteFrame(const QString& filename, MPEG2frame *f);
void WriteFrame(const QString& filename, AVPacket *pkt);
static void WriteYUV(const QString& filename, const mpeg2_info_t *info);
static void WriteData(const QString& filename, uint8_t *data, int size);
bool BuildFrame(AVPacket *pkt, const QString& fname);
MPEG2frame *GetPoolFrame(AVPacket *pkt);
MPEG2frame *GetPoolFrame(MPEG2frame *f);
int GetFrame(AVPacket *pkt);
bool FindStart();
static void SetRepeat(MPEG2frame *vf, int nb_fields, bool topff);
static void SetRepeat(uint8_t *ptr, int size, int fields, bool topff);
MPEG2frame *FindFrameNum(int frameNum);
void RenumberFrames(int start_pos, int delta);
void StoreSecondary();
int PlaybackSecondary();
MPEG2frame *DecodeToFrame(int frameNum, int skip_reset);
int ConvertToI(FrameList *orderedFrames, int headPos);
int InsertFrame(int frameNum, int64_t deltaPTS,
int64_t ptsIncrement, int64_t initPTS);
void AddSequence(MPEG2frame *frame1, MPEG2frame *frame2);
static FrameList ReorderDTStoPTS(FrameList *dtsOrder, int pos);
void InitialPTSFixup(MPEG2frame *curFrame, int64_t &origvPTS,
int64_t &PTSdiscrep, int numframes, bool fix) const;
static void SetFrameNum(uint8_t *ptr, int num);
static int GetFrameNum(const MPEG2frame *frame)
{
return frame->m_mpeg2_pic.temporal_reference;
}
static int GetFrameTypeN(const MPEG2frame *frame)
{
return frame->m_mpeg2_pic.flags & PIC_MASK_CODING_TYPE;
}
static char GetFrameTypeT(const MPEG2frame *frame)
{
int type = GetFrameTypeN(frame);
return (type == 1 ? 'I' :
(type == 2 ? 'P' : (type == 3 ? 'B' : 'X')));
}
static int GetNbFields(const MPEG2frame *frame)
{
return frame->m_mpeg2_pic.nb_fields;
}
int GetStreamType(int id) const
{
return (m_inputFC->streams[id]->codecpar->codec_id == AV_CODEC_ID_AC3) ?
AV_CODEC_ID_AC3 : AV_CODEC_ID_MP2;
}
AVCodecContext *getCodecContext(uint id)
{
if (id >= m_inputFC->nb_streams)
return nullptr;
return m_codecMap.GetCodecContext(m_inputFC->streams[id]);
}
AVCodecParserContext *getCodecParserContext(uint id)
{
if (id >= m_inputFC->nb_streams)
return nullptr;
return av_stream_get_parser(m_inputFC->streams[id]);
}
static void dumpList(FrameList *list);
int (*m_checkAbort)() {nullptr};
void (*m_updateStatus)(float percent_done) {nullptr};
FrameList m_vSecondary;
bool m_useSecondary {false};
FrameList m_vFrame;
FrameMap m_aFrame;
FrameQueue m_framePool;
FrameQueue m_unreadFrames;
int m_displayFrame {0};
mpeg2dec_t *m_headerDecoder {nullptr};
mpeg2dec_t *m_imgDecoder {nullptr};
frm_dir_map_t m_delMap;
frm_dir_map_t m_saveMap;
pthread_t m_thread {};
MythCodecMap m_codecMap {};
AVFormatContext *m_inputFC {nullptr};
AVFrame *m_picture {nullptr};
int m_vidId {-1};
int m_extCount {0};
QMap <int, int> m_audMap;
int64_t m_ptsIncrement {0};
bool m_mkvFile {false};
bool m_discard {false};
//control options
bool m_noRepeat;
bool m_fixPts;
int m_maxFrames;
QString m_infile;
const char *m_format {nullptr};
bool m_allAudio {false};
//complete?
bool m_fileEnd {false};
bool m_realFileEnd {false};
//progress indicators
QDateTime m_statusTime;
bool m_showProgress {false};
uint64_t m_fileSize {0};
int m_frameNum {0};
int m_statusUpdateTime {5};
uint64_t m_lastWrittenPos {0};
};
#ifdef NO_MYTH
#include <QDateTime>
#include <iostream>
extern int verboseMask;
#undef LOG
#define LOG(mask,level,args...) \
do { \
if ((verboseMask & mask) != 0) \
{ \
cout << args << endl; \
} \
} while (0)
// Be sure to keep these the same as in libmythbase/exitcodes.h or expect
// odd behavior eventually
#define GENERIC_EXIT_OK 0
#define GENERIC_EXIT_NOT_OK 128
#define GENERIC_EXIT_WRITE_FRAME_ERROR 149
#define GENERIC_EXIT_DEADLOCK 150
#else
#include "libmythbase/exitcodes.h"
#include "libmyth/mythcontext.h"
#endif
/*
* vim:ts=4:sw=4:ai:et:si:sts=4
*/