MythTV  master
NuppelVideoRecorder.h
Go to the documentation of this file.
1 #ifndef NUPPELVIDEORECORDER
2 #define NUPPELVIDEORECORDER
3 
4 // C headers
5 #include <sys/time.h>
6 #ifdef MMX
7 #undef MMX
8 #define MMXBLAH
9 #endif
10 #include <lame/lame.h>
11 #ifdef MMXBLAH
12 #define MMX
13 #endif
14 
15 // C++ std headers
16 #include <cstdint>
17 #include <ctime>
18 #include <vector>
19 
20 // Qt headers
21 #include <QString>
22 
23 // MythTV headers
24 #include "libmythbase/mthread.h"
25 #include "libmythbase/mythconfig.h"
27 #include "libmythtv/format.h"
28 #include "libmythtv/mythframe.h"
29 #include "libmythtv/mythtvexp.h"
30 
31 #include "lzo/lzo1x.h"
32 #include "v4lrecorder.h"
33 
34 #undef HAVE_AV_CONFIG_H
35 extern "C" {
36 #include "libavcodec/avcodec.h"
37 }
38 
39 static constexpr int8_t KEYFRAMEDIST { 30 };
40 
41 struct video_audio;
42 class RTjpeg;
43 class MythMediaBuffer;
44 class ChannelBase;
45 class AudioInput;
47 
48 class NVRWriteThread : public MThread
49 {
50  public:
51  explicit NVRWriteThread(NuppelVideoRecorder *parent) :
52  MThread("NVRWrite"), m_parent(parent) {}
53  ~NVRWriteThread() override { wait(); m_parent = nullptr; }
54  void run(void) override; // MThread
55  private:
57 };
58 
59 class NVRAudioThread : public MThread
60 {
61  public:
62  explicit NVRAudioThread(NuppelVideoRecorder *parent) :
63  MThread("NVRAudio"), m_parent(parent) {}
64  ~NVRAudioThread() override { wait(); m_parent = nullptr; }
65  void run(void) override; // MThread
66  private:
68 };
69 
71 {
72  friend class NVRWriteThread;
73  friend class NVRAudioThread;
74  public:
75  NuppelVideoRecorder(TVRec *rec, ChannelBase *channel);
76  ~NuppelVideoRecorder() override;
77 
78  void SetOption(const QString &opt, int value) override; // DTVRecorder
79  void SetOption(const QString &name, const QString &value) override; // DTVRecorder
80 
82  const QString &videodev,
83  const QString &audiodev,
84  const QString &vbidev) override; // DTVRecorder
85 
86  void Initialize(void) override; // DTVRecorder
87  void run(void) override; // RecorderBase
88 
89  void Pause(bool clear = true) override; // RecorderBase
90  bool IsPaused(bool holding_lock = false) const override; // RecorderBase
91 
92  bool IsRecording(void) override; // RecorderBase
93 
94  long long GetFramesWritten(void) override; // DTVRecorder
95 
96  bool Open(void);
97  int GetVideoFd(void) override; // DTVRecorder
98  void Reset(void) override; // DTVRecorder
99 
100  void SetVideoFilters(QString &filters) override; // DTVRecorder
101  void SetTranscoding(bool value) { m_transcoding = value; };
102 
103  void ResetForNewFile(void) override; // DTVRecorder
104  void FinishRecording(void) override; // DTVRecorder
105  void StartNewFile(void) override; // RecorderBase
106 
107  // reencode stuff
108  void StreamAllocate(void);
109  void WriteHeader(void);
110  void WriteSeekTable(void);
111  void WriteKeyFrameAdjustTable(
112  const std::vector<struct kfatable_entry> &kfa_table);
113  void UpdateSeekTable(int frame_num, long offset = 0);
114 
115  bool SetupAVCodecVideo(void);
116  void SetupRTjpeg(void);
117  int AudioInit(bool skipdevice = false);
118  void SetVideoAspect(float newAspect) {m_videoAspect = newAspect; };
119  void WriteVideo(MythVideoFrame *frame, bool skipsync = false,
120  bool forcekey = false);
121  void WriteAudio(unsigned char *buf, int fnum, std::chrono::milliseconds timecode);
122  void WriteText(unsigned char *buf, int len, std::chrono::milliseconds timecode, int pagenr);
123 
124  void SetNewVideoParams(double newaspect);
125 
126  protected:
127  void doWriteThread(void);
128  void doAudioThread(void);
129 
130  private:
131  inline void WriteFrameheader(rtframeheader *fh);
132 
133  void WriteFileHeader(void);
134 
135  void InitBuffers(void);
136  void ResizeVideoBuffers(void);
137 
138  bool MJPEGInit(void);
139 
140  void KillChildren(void);
141 
142  void BufferIt(unsigned char *buf, int len = -1, bool forcekey = false);
143 
144  int CreateNuppelFile(void);
145 
146  void ProbeV4L2(void);
147  bool SetFormatV4L2(void);
148  void DoV4L2(void);
149 
150  void FormatTT(struct VBIData *vbidata) override; // V4LRecorder
151  void FormatCC(uint code1, uint code2) override; // V4LRecorder
152  void AddTextData(unsigned char *buf, int len, std::chrono::milliseconds timecode, char type) override; // CC608Input
153 
154  void UpdateResolutions(void);
155 
156  int m_fd {-1}; // v4l input file handle
157  signed char *m_strm {nullptr};
158  unsigned int m_lf {0};
159  int m_tf {0};
160  int m_m1 {0};
161  int m_m2 {0};
162  int m_q {255};
163  int m_width {352};
164  int m_height {240};
165  int m_pipMode {0};
166  int m_compression {1};
167  bool m_compressAudio {true};
168  AudioInput *m_audioDevice {nullptr};
169  unsigned long long m_audioBytes {0};
170  int m_audioChannels {2};
171  int m_audioBits {16};
172  int m_audioBytesPerSample {m_audioChannels * m_audioBits / 8};
173  int m_audioSampleRate {44100}; // rate we request from sounddevice
174  int m_effectiveDsp {0}; // actual measured rate
175 
176  int m_useBttv {1};
177  float m_videoAspect {1.33333F};
178 
179  bool m_transcoding {false};
180 
181  int m_mp3Quality {3};
182  char *m_mp3Buf {nullptr};
183  int m_mp3BufSize {0};
184  lame_global_flags *m_gf {nullptr};
185 
186  RTjpeg *m_rtjc {nullptr};
187 
188  static constexpr size_t kOutLen {1024*1024 + 1024*1024 / 64 + 16 + 3};
189  std::array<lzo_byte,kOutLen> m_out {};
190 
191  alignas(8) std::array<uint8_t,LZO1X_1_MEM_COMPRESS> __LZO_MMODEL m_wrkmem {0} ;
192 
193  std::vector<struct vidbuffertype *> m_videoBuffer;
194  std::vector<struct audbuffertype *> m_audioBuffer;
195  std::vector<struct txtbuffertype *> m_textBuffer;
196 
197  int m_actVideoEncode {0};
198  int m_actVideoBuffer {0};
199 
200  int m_actAudioEncode {0};
201  int m_actAudioBuffer {0};
202  long long m_actAudioSample {0};
203 
204  int m_actTextEncode {0};
205  int m_actTextBuffer {0};
206 
207  int m_videoBufferCount {0};
208  int m_audioBufferCount {0};
209  int m_textBufferCount {0};
210 
211  long m_videoBufferSize {0};
212  long m_audioBufferSize {0};
213  long m_textBufferSize {0};
214 
215  struct timeval m_stm {0,0};
216 
217  NVRWriteThread *m_writeThread {nullptr};
218  NVRAudioThread *m_audioThread {nullptr};
219 
220  bool m_recording {false};
221 
222  int m_keyframeDist {KEYFRAMEDIST};
223  std::vector<struct seektable_entry> *m_seekTable {nullptr};
224  long long m_lastPositionMapPos {0};
225 
226  long long m_extendedDataOffset {0};
227 
228  long long m_framesWritten {0};
229 
230  bool m_livetv {false};
231  bool m_writePaused {false};
232  bool m_audioPaused {false};
233  bool m_mainPaused {false};
234 
235  double m_frameRateMultiplier {1.0};
236  double m_heightMultiplier {1.0};
237 
238  int m_lastBlock {0};
239  std::chrono::milliseconds m_firstTc {0ms};
240  std::chrono::milliseconds m_oldTc {0ms};
241  int m_startNum {0};
242  int m_frameOfGop {0};
243  int m_lastTimecode {0};
244  int m_audioBehind {0};
245 
246  bool m_useAvCodec {false};
247 
248  const AVCodec *m_mpaVidCodec {nullptr};
249  AVCodecContext *m_mpaVidCtx {nullptr};
250 
251  int m_targetBitRate {2200};
252  int m_scaleBitRate {1};
253  int m_maxQuality {2};
254  int m_minQuality {31};
255  int m_qualDiff {3};
256  int m_mp4Opts {0};
257  int m_mbDecision {FF_MB_DECISION_SIMPLE};
259  int m_encodingThreadCount {1};
260 
261  VideoFrameType m_inPixFmt {FMT_YV12};
262  AVPixelFormat m_pictureFormat {AV_PIX_FMT_YUV420P};
263 #ifdef USING_V4L2
264  uint32_t m_v4l2PixelFormat {0};
265 #endif
266  int m_wOut {0};
267  int m_hOut {0};
268 
269  bool m_hardwareEncode {false};
270  int m_hmjpgQuality {80};
271  int m_hmjpgHDecimation {2};
272  int m_hmjpgVDecimation {2};
273  int m_hmjpgMaxW {640};
274 
275  bool m_clearTimeOnPause {false};
276 
277  bool m_usingV4l2 {false};
278  int m_channelFd {-1};
279 
280  ChannelBase *m_channelObj {nullptr};
281 
282  bool m_skipBtAudio {false};
283 
284 #ifdef USING_V4L2
285  bool m_correctBttv {false};
286 #endif
287 
288  int m_volume {100};
289 
290  CC608Decoder *m_ccd {nullptr};
291 
292  bool m_go7007 {false};
293  bool m_resetCapture {false};
294 };
295 
296 #endif
rtframeheader
Definition: format.h:34
NVRWriteThread::NVRWriteThread
NVRWriteThread(NuppelVideoRecorder *parent)
Definition: NuppelVideoRecorder.h:51
DTVRecorder::GetVideoFd
int GetVideoFd(void) override
Returns file descriptor of recorder device.
Definition: dtvrecorder.h:53
NVRWriteThread::~NVRWriteThread
~NVRWriteThread() override
Definition: NuppelVideoRecorder.h:53
NuppelVideoRecorder::m_videoBuffer
std::vector< struct vidbuffertype * > m_videoBuffer
Definition: NuppelVideoRecorder.h:193
DTVRecorder::ResetForNewFile
void ResetForNewFile(void) override
Definition: dtvrecorder.cpp:140
V4LRecorder
Abstract base class for Video4Linux based recorders.
Definition: v4lrecorder.h:25
MThread::wait
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:300
DTVRecorder::SetVideoFilters
void SetVideoFilters(QString &) override
Tells recorder which filters to use.
Definition: dtvrecorder.h:51
NuppelVideoRecorder::m_textBuffer
std::vector< struct txtbuffertype * > m_textBuffer
Definition: NuppelVideoRecorder.h:195
mythtvexp.h
CC608Decoder
Definition: cc608decoder.h:49
format.h
DTVRecorder::SetOptionsFromProfile
void SetOptionsFromProfile(RecordingProfile *profile, const QString &videodev, const QString &audiodev, const QString &vbidev) override
Sets basic recorder options.
Definition: dtvrecorder.cpp:112
DTVRecorder::Reset
void Reset(void) override
Reset the recorder to the startup state.
Definition: dtvrecorder.cpp:204
MythMediaBuffer
Definition: mythmediabuffer.h:50
mythframe.h
CC608Input
Definition: cc608decoder.h:26
NVRWriteThread::run
void run(void) override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: NuppelVideoRecorder.cpp:83
DTVRecorder::FinishRecording
void FinishRecording(void) override
Flushes the ringbuffer, and if this is not a live LiveTV recording saves the position map and filesiz...
Definition: dtvrecorder.cpp:126
RecorderBase::Pause
virtual void Pause(bool clear=true)
Pause tells recorder to pause, it should not block.
Definition: recorderbase.cpp:263
NVRWriteThread
Definition: NuppelVideoRecorder.h:48
KEYFRAMEDIST
static constexpr int8_t KEYFRAMEDIST
Definition: NuppelVideoRecorder.h:39
V4LRecorder::SetOption
void SetOption(const QString &name, const QString &value) override
Set an specific option.
Definition: v4lrecorder.cpp:56
NuppelVideoRecorder::m_audioBuffer
std::vector< struct audbuffertype * > m_audioBuffer
Definition: NuppelVideoRecorder.h:194
NVRAudioThread::~NVRAudioThread
~NVRAudioThread() override
Definition: NuppelVideoRecorder.h:64
NuppelVideoRecorder::SetVideoAspect
void SetVideoAspect(float newAspect)
Definition: NuppelVideoRecorder.h:118
NVRAudioThread
Definition: NuppelVideoRecorder.h:59
AudioInput
Definition: audioinput.h:27
cc608decoder.h
NVRAudioThread::m_parent
NuppelVideoRecorder * m_parent
Definition: NuppelVideoRecorder.h:67
ChannelBase
Abstract class providing a generic interface to tuning hardware.
Definition: channelbase.h:31
hardwareprofile.scan.profile
profile
Definition: scan.py:97
FMT_YV12
@ FMT_YV12
Definition: mythframe.h:24
v4lrecorder.h
NVRWriteThread::m_parent
NuppelVideoRecorder * m_parent
Definition: NuppelVideoRecorder.h:56
DTVRecorder::GetFramesWritten
long long GetFramesWritten(void) override
Returns number of frames written to disk.
Definition: dtvrecorder.h:48
DTVRecorder::Initialize
void Initialize(void) override
This is called between SetOptionsFromProfile() and run() to initialize any devices,...
Definition: dtvrecorder.h:52
clear
static void clear(SettingsMap &cache, SettingsMap &overrides, const QString &myKey)
Definition: mythdb.cpp:897
MConcurrent::run
void run(const QString &name, Class *object, void(Class::*fn)())
Definition: mconcurrent.h:137
RecorderBase::IsRecording
virtual bool IsRecording(void)
Tells whether the StartRecorder() loop is running.
Definition: recorderbase.cpp:243
NVRAudioThread::run
void run(void) override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: NuppelVideoRecorder.cpp:90
uint
unsigned int uint
Definition: compat.h:81
CC608Input::AddTextData
virtual void AddTextData(unsigned char *buf, int len, std::chrono::milliseconds timecode, char type)=0
MTV_PUBLIC
#define MTV_PUBLIC
Definition: mythtvexp.h:15
RTjpeg
Definition: RTjpegN.h:53
NVRAudioThread::NVRAudioThread
NVRAudioThread(NuppelVideoRecorder *parent)
Definition: NuppelVideoRecorder.h:62
RecorderBase::StartNewFile
virtual void StartNewFile(void)
Definition: recorderbase.h:275
VBIData
Definition: v4lrecorder.h:17
NuppelVideoRecorder::m_stm
Definition: NuppelVideoRecorder.h:215
TVRec
This is the coordinating class of the Recorder Subsystem.
Definition: tv_rec.h:142
MThread
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:48
mthread.h
V4LRecorder::FormatCC
virtual void FormatCC(uint, uint)
Definition: v4lrecorder.h:44
VideoFrameType
VideoFrameType
Definition: mythframe.h:20
V4LRecorder::FormatTT
virtual void FormatTT(struct VBIData *)
Definition: v4lrecorder.h:43
RecordingProfile
Definition: recordingprofile.h:41
MythVideoFrame
Definition: mythframe.h:88
NuppelVideoRecorder::SetTranscoding
void SetTranscoding(bool value)
Definition: NuppelVideoRecorder.h:101
RecorderBase::IsPaused
virtual bool IsPaused(bool holding_lock=false) const
Returns true iff recorder is paused.
Definition: recorderbase.cpp:281
NuppelVideoRecorder
Definition: NuppelVideoRecorder.h:70