MythTV  master
transcode.cpp
Go to the documentation of this file.
1 // C++
2 #include <cmath>
3 #include <fcntl.h>
4 #include <iostream>
5 #include <memory>
6 #include <unistd.h> // for unlink()
7 
8 // Qt
9 #include <QList>
10 #include <QMap>
11 #include <QMutex>
12 #include <QMutexLocker>
13 #include <QRegularExpression>
14 #include <QStringList>
15 #include <QWaitCondition>
16 #include <QtAlgorithms>
17 
18 // MythTV
19 #include "libmythbase/mythconfig.h"
20 
22 #include "libmythbase/exitcodes.h"
25 #include "libmythbase/mythdbcon.h"
29 #include "libmythtv/deletemap.h"
31 #include "libmythtv/jobqueue.h"
32 #include "libmythtv/mythavutil.h"
34 #include "libmythtv/tvremoteutil.h"
35 
36 // MythTranscode
37 #include "audioreencodebuffer.h"
38 #include "cutter.h"
39 #include "mythtranscodeplayer.h"
40 #include "transcode.h"
41 #include "videodecodebuffer.h"
42 
43 extern "C" {
44 #include "libavcodec/avcodec.h"
45 #include "libswscale/swscale.h"
46 }
47 
48 #define LOC QString("Transcode: ")
49 
51  m_proginfo(pginfo),
52  m_recProfile(new RecordingProfile("Transcoders"))
53 {
54 }
55 
57 {
58  SetPlayerContext(nullptr);
59  delete m_outBuffer;
60  delete m_fifow;
61  delete m_recProfile;
62 }
63 
64 bool Transcode::GetProfile(const QString& profileName, const QString& encodingType,
65  int height, int frameRate)
66 {
67  if (profileName.toLower() == "autodetect")
68  {
69  if (height == 1088)
70  height = 1080;
71 
72  QString autoProfileName = QObject::tr("Autodetect from %1").arg(height);
73  if (frameRate == 25 || frameRate == 30)
74  autoProfileName += "i";
75  if (frameRate == 50 || frameRate == 60)
76  autoProfileName += "p";
77 
78  bool result = false;
79  LOG(VB_GENERAL, LOG_NOTICE,
80  QString("Transcode: Looking for autodetect profile: %1")
81  .arg(autoProfileName));
82  result = m_recProfile->loadByGroup(autoProfileName, "Transcoders");
83 
84  if (!result && encodingType == "MPEG-2")
85  {
86  result = m_recProfile->loadByGroup("MPEG2", "Transcoders");
87  autoProfileName = "MPEG2";
88  }
89  if (!result && (encodingType == "MPEG-4" || encodingType == "RTjpeg"))
90  {
91  result = m_recProfile->loadByGroup("RTjpeg/MPEG4",
92  "Transcoders");
93  autoProfileName = "RTjpeg/MPEG4";
94  }
95  if (!result)
96  {
97  LOG(VB_GENERAL, LOG_ERR,
98  QString("Transcode: Couldn't find profile for : %1")
99  .arg(encodingType));
100 
101  return false;
102  }
103 
104  LOG(VB_GENERAL, LOG_NOTICE,
105  QString("Transcode: Using autodetect profile: %1")
106  .arg(autoProfileName));
107  }
108  else
109  {
110  bool isNum = false;
111  int profileID = profileName.toInt(&isNum);
112  // If a bad profile is specified, there will be trouble
113  if (isNum && profileID > 0)
114  m_recProfile->loadByID(profileID);
115  else if (!m_recProfile->loadByGroup(profileName, "Transcoders"))
116  {
117  LOG(VB_GENERAL, LOG_ERR, QString("Couldn't find profile #: %1")
118  .arg(profileName));
119  return false;
120  }
121  }
122  return true;
123 }
124 
126 {
127  if (player_ctx == m_ctx)
128  return;
129 
130  delete m_ctx;
131  m_ctx = player_ctx;
132 }
133 
134 int Transcode::TranscodeFile(const QString &inputname,
135  const QString &outputname,
136  [[maybe_unused]] const QString &profileName,
137  bool honorCutList, bool framecontrol,
138  int jobID, const QString& fifodir,
139  bool fifo_info, bool cleanCut,
140  frm_dir_map_t &deleteMap,
141  int AudioTrackNo,
142  bool passthru)
143 {
144  QDateTime curtime = MythDate::current();
145  QDateTime statustime = curtime;
146  int audioFrame = 0;
147  std::unique_ptr<Cutter> cutter = nullptr;
148  std::unique_ptr<MythAVFormatWriter> avfw = nullptr;
149  std::unique_ptr<MythAVFormatWriter> avfw2 = nullptr;
150  std::unique_ptr<HTTPLiveStream> hls = nullptr;
151  int hlsSegmentSize = 0;
152  int hlsSegmentFrames = 0;
153 
154  if (jobID >= 0)
155  JobQueue::ChangeJobComment(jobID, "0% " + QObject::tr("Completed"));
156 
157  if (m_hlsMode)
158  {
159  m_avfMode = true;
160 
161  if (m_hlsStreamID != -1)
162  {
163  hls = std::make_unique<HTTPLiveStream>(m_hlsStreamID);
165  hls->UpdateStatusMessage("Transcoding Starting");
166  m_cmdWidth = hls->GetWidth();
167  m_cmdHeight = hls->GetHeight();
168  m_cmdBitrate = hls->GetBitrate();
170  }
171  }
172 
173  if (!m_avfMode)
174  {
175  LOG(VB_GENERAL, LOG_ERR,
176  "AVFormat mode not set.");
177  return REENCODE_ERROR;
178  }
179 
180  // Input setup
181  auto *player_ctx = new PlayerContext(kTranscoderInUseID);
182  player_ctx->SetPlayingInfo(m_proginfo);
183  MythMediaBuffer *rb = (hls && (m_hlsStreamID != -1)) ?
184  MythMediaBuffer::Create(hls->GetSourceFile(), false, false) :
185  MythMediaBuffer::Create(inputname, false, false);
186  if (!rb || !rb->GetLastError().isEmpty())
187  {
188  LOG(VB_GENERAL, LOG_ERR,
189  QString("Transcoding aborted, error: '%1'")
190  .arg(rb? rb->GetLastError() : ""));
191  delete player_ctx;
192  return REENCODE_ERROR;
193  }
194  player_ctx->SetRingBuffer(rb);
195  player_ctx->SetPlayer(new MythTranscodePlayer(player_ctx, static_cast<PlayerFlags>(kVideoIsNull | kNoITV)));
196  SetPlayerContext(player_ctx);
197  auto * player = dynamic_cast<MythTranscodePlayer*>(GetPlayer());
198  if (player == nullptr)
199  {
200  LOG(VB_GENERAL, LOG_ERR,
201  QString("Transcoding aborted, failed to retrieve MythPlayer object"));
202  return REENCODE_ERROR;
203  }
204  if (m_proginfo->GetRecordingEndTime() > curtime)
205  {
206  player_ctx->SetRecorder(RemoteGetExistingRecorder(m_proginfo));
207  player->SetWatchingRecording(true);
208  }
209 
210  if (m_showProgress)
211  {
212  statustime = statustime.addSecs(5);
213  }
214 
215  AudioOutput *audioOutput = new AudioReencodeBuffer(FORMAT_NONE, 0,
216  passthru);
217  AudioReencodeBuffer *arb = ((AudioReencodeBuffer*)audioOutput);
218  player->GetAudio()->SetAudioOutput(audioOutput);
219  player->SetTranscoding(true);
220 
221  if (player->OpenFile() < 0)
222  {
223  LOG(VB_GENERAL, LOG_ERR, "Transcoding aborted, error opening file.");
224  SetPlayerContext(nullptr);
225  return REENCODE_ERROR;
226  }
227 
228  if (AudioTrackNo > -1)
229  {
230  LOG(VB_GENERAL, LOG_INFO,
231  QString("Set audiotrack number to %1").arg(AudioTrackNo));
232  player->GetDecoder()->SetTrack(kTrackTypeAudio, AudioTrackNo);
233  }
234 
235  long long total_frame_count = player->GetTotalFrameCount();
236  long long new_frame_count = total_frame_count;
237  if (honorCutList && m_proginfo)
238  {
239  LOG(VB_GENERAL, LOG_INFO, "Honoring the cutlist while transcoding");
240 
241  frm_dir_map_t::const_iterator it;
242  QString cutStr;
243  long long lastStart = 0;
244 
245  if (deleteMap.empty())
246  m_proginfo->QueryCutList(deleteMap);
247 
248  for (it = deleteMap.cbegin(); it != deleteMap.cend(); ++it)
249  {
250  if (*it)
251  {
252  if (!cutStr.isEmpty())
253  cutStr += ",";
254  cutStr += QString("%1-").arg((long)it.key());
255  lastStart = it.key();
256  }
257  else
258  {
259  if (cutStr.isEmpty())
260  cutStr += "0-";
261  cutStr += QString("%1").arg((long)it.key());
262  new_frame_count -= (it.key() - lastStart);
263  }
264  }
265  if (cutStr.isEmpty())
266  cutStr = "Is Empty";
267  else if (cutStr.endsWith('-') && (total_frame_count > lastStart))
268  {
269  new_frame_count -= (total_frame_count - lastStart);
270  cutStr += QString("%1").arg(total_frame_count);
271  }
272  LOG(VB_GENERAL, LOG_INFO, QString("Cutlist : %1").arg(cutStr));
273  LOG(VB_GENERAL, LOG_INFO, QString("Original Length: %1 frames")
274  .arg((long)total_frame_count));
275  LOG(VB_GENERAL, LOG_INFO, QString("New Length : %1 frames")
276  .arg((long)new_frame_count));
277 
278  if ((m_proginfo->QueryIsEditing()) ||
280  {
281  LOG(VB_GENERAL, LOG_INFO, "Transcoding aborted, cutlist changed");
282  SetPlayerContext(nullptr);
284  }
286  curtime = curtime.addSecs(60);
287  }
288 
289  player->GetAudio()->ReinitAudio();
290 
291  QString vidsetting = nullptr;
292 
293  QSize buf_size = player->GetVideoBufferSize();
294  int video_width = buf_size.width();
295  int video_height = buf_size.height();
296 
297  if (video_height == 1088) {
298  LOG(VB_GENERAL, LOG_NOTICE,
299  "Found video height of 1088. This is unusual and "
300  "more than likely the video is actually 1080 so mythtranscode "
301  "will treat it as such.");
302  }
303 
304  DecoderBase* dec = player->GetDecoder();
305  float video_aspect = dec ? dec->GetVideoAspect() : 4.0F / 3.0F;
306  float video_frame_rate = player->GetFrameRate();
307  int newWidth = video_width;
308  int newHeight = video_height;
309  bool halfFramerate = false;
310  bool skippedLastFrame = false;
311 
312  if (m_avfMode)
313  {
314  newWidth = m_cmdWidth;
315  newHeight = m_cmdHeight;
316 
317  // Absolutely no purpose is served by scaling video up beyond it's
318  // original resolution, quality is degraded, transcoding is
319  // slower and in future we may wish to scale bitrate according to
320  // resolution, so it would also waste bandwidth (when streaming)
321  //
322  // This change could be said to apply for all transcoding, but for now
323  // we're limiting it to HLS where it's uncontroversial
324  if (m_hlsMode)
325  {
326 // if (newWidth > video_width)
327 // newWidth = video_width;
328  if (newHeight > video_height)
329  {
330  newHeight = video_height;
331  newWidth = 0;
332  }
333  }
334 
335  // TODO: is this necessary? It got commented out, but may still be
336  // needed.
337  // int actualHeight = (video_height == 1088 ? 1080 : video_height);
338 
339  // If height or width are 0, then we need to calculate them
340  if (newHeight == 0 && newWidth > 0)
341  newHeight = (int)(1.0F * newWidth / video_aspect);
342  else if (newWidth == 0 && newHeight > 0)
343  newWidth = (int)(1.0F * newHeight * video_aspect);
344  else if (newWidth == 0 && newHeight == 0)
345  {
346  newHeight = 480;
347  newWidth = (int)(1.0F * 480 * video_aspect);
348  if (newWidth > 640)
349  {
350  newWidth = 640;
351  newHeight = (int)(1.0F * 640 / video_aspect);
352  }
353  }
354 
355  // make sure dimensions are valid for MPEG codecs
356  newHeight = (newHeight + 15) & ~0xF;
357  newWidth = (newWidth + 15) & ~0xF;
358 
359  avfw = std::make_unique<MythAVFormatWriter>();
360  if (!avfw)
361  {
362  LOG(VB_GENERAL, LOG_ERR,
363  "Transcoding aborted, error creating AVFormatWriter.");
364  SetPlayerContext(nullptr);
365  return REENCODE_ERROR;
366  }
367 
369  avfw->SetHeight(newHeight);
370  avfw->SetWidth(newWidth);
371  avfw->SetAspect(video_aspect);
373  avfw->SetAudioChannels(arb->m_channels);
375  avfw->SetAudioFormat(FORMAT_S16);
376 
377  if (m_hlsMode)
378  {
379 
380  if (m_hlsStreamID == -1)
381  {
382  hls = std::make_unique<HTTPLiveStream>(inputname, newWidth, newHeight,
384  m_hlsMaxSegments, 0, 0);
385 
386  m_hlsStreamID = hls->GetStreamID();
387  if (!hls || m_hlsStreamID == -1)
388  {
389  LOG(VB_GENERAL, LOG_ERR, "Unable to create new stream");
390  SetPlayerContext(nullptr);
391  return REENCODE_ERROR;
392  }
393  }
394 
395  int segmentSize = hls->GetSegmentSize();
396 
397  LOG(VB_GENERAL, LOG_NOTICE,
398  QString("HLS: Using segment size of %1 seconds")
399  .arg(segmentSize));
400 
402  {
403  int audioOnlyBitrate = hls->GetAudioOnlyBitrate();
404 
405  avfw2 = std::make_unique<MythAVFormatWriter>();
406  avfw2->SetContainer("mpegts");
407  avfw2->SetAudioCodec("aac");
408  avfw2->SetAudioBitrate(audioOnlyBitrate);
409  avfw2->SetAudioChannels(arb->m_channels);
410  avfw2->SetAudioFrameRate(arb->m_eff_audiorate);
411  avfw2->SetAudioFormat(FORMAT_S16);
412  }
413 
414  avfw->SetContainer("mpegts");
415  avfw->SetVideoCodec("libx264");
416  avfw->SetAudioCodec("aac");
418  hls->UpdateStatusMessage("Transcoding Starting");
419  hls->UpdateSizeInfo(newWidth, newHeight, video_width, video_height);
420 
421  if (!hls->InitForWrite())
422  {
423  LOG(VB_GENERAL, LOG_ERR, "hls->InitForWrite() failed");
424  SetPlayerContext(nullptr);
425  return REENCODE_ERROR;
426  }
427 
428  if (video_frame_rate > 30)
429  {
430  halfFramerate = true;
431  avfw->SetFramerate(video_frame_rate/2);
432 
433  if (avfw2)
434  avfw2->SetFramerate(video_frame_rate/2);
435 
436  hlsSegmentSize = (int)(segmentSize * video_frame_rate / 2);
437  }
438  else
439  {
440  avfw->SetFramerate(video_frame_rate);
441 
442  if (avfw2)
443  avfw2->SetFramerate(video_frame_rate);
444 
445  hlsSegmentSize = (int)(segmentSize * video_frame_rate);
446  }
447 
448  avfw->SetKeyFrameDist(30);
449  if (avfw2)
450  avfw2->SetKeyFrameDist(30);
451 
452  hls->AddSegment();
453  avfw->SetFilename(hls->GetCurrentFilename());
454  if (avfw2)
455  avfw2->SetFilename(hls->GetCurrentFilename(true));
456  }
457  else
458  {
462  avfw->SetFilename(outputname);
463  avfw->SetFramerate(video_frame_rate);
464  avfw->SetKeyFrameDist(30);
465  }
466 
467  int threads = gCoreContext->GetNumSetting("HTTPLiveStreamThreads", 2);
468  QString preset = gCoreContext->GetSetting("HTTPLiveStreamPreset", "veryfast");
469  QString tune = gCoreContext->GetSetting("HTTPLiveStreamTune", "film");
470 
471  LOG(VB_GENERAL, LOG_NOTICE,
472  QString("x264 HLS using: %1 threads, '%2' profile and '%3' tune")
473  .arg(QString::number(threads), preset, tune));
474 
475  avfw->SetThreadCount(threads);
476  avfw->SetEncodingPreset(preset);
477  avfw->SetEncodingTune(tune);
478 
479  if (avfw2)
480  avfw2->SetThreadCount(1);
481 
482  if (!avfw->Init())
483  {
484  LOG(VB_GENERAL, LOG_ERR, "avfw->Init() failed");
485  SetPlayerContext(nullptr);
486  return REENCODE_ERROR;
487  }
488 
489  if (!avfw->OpenFile())
490  {
491  LOG(VB_GENERAL, LOG_ERR, "avfw->OpenFile() failed");
492  SetPlayerContext(nullptr);
493  return REENCODE_ERROR;
494  }
495 
496  if (avfw2 && !avfw2->Init())
497  {
498  LOG(VB_GENERAL, LOG_ERR, "avfw2->Init() failed");
499  SetPlayerContext(nullptr);
500  return REENCODE_ERROR;
501  }
502 
503  if (avfw2 && !avfw2->OpenFile())
504  {
505  LOG(VB_GENERAL, LOG_ERR, "avfw2->OpenFile() failed");
506  SetPlayerContext(nullptr);
507  return REENCODE_ERROR;
508  }
509 
510  arb->m_audioFrameSize = avfw->GetAudioFrameSize() * arb->m_channels * 2;
511  }
512 
513  if (honorCutList && !deleteMap.empty())
514  {
515  if (cleanCut)
516  {
517  // Have the player seek only part of the way
518  // through a cut, and then use the cutter to
519  // discard the rest
520  cutter = std::make_unique<Cutter>();
521  cutter->SetCutList(deleteMap, m_ctx);
522  player->SetCutList(cutter->AdjustedCutList());
523  }
524  else
525  {
526  // Have the player apply the cut list
527  player->SetCutList(deleteMap);
528  }
529  }
530 
531  player->InitForTranscode();
532  if (player->IsErrored())
533  {
534  LOG(VB_GENERAL, LOG_ERR,
535  "Unable to initialize MythPlayer for Transcode");
536  SetPlayerContext(nullptr);
537  return REENCODE_ERROR;
538  }
539 
540  // must come after InitForTranscode - which creates the VideoOutput instance
541  if (m_hlsMode && player->GetVideoOutput())
542  player->GetVideoOutput()->SetDeinterlacing(true, false, DEINT_CPU | DEINT_MEDIUM);
543 
544  MythVideoFrame frame;
545  // Do not use padding when compressing to RTjpeg or when in fifomode.
546  // The RTjpeg compressor doesn't know how to handle strides different to
547  // video width.
548  bool nonAligned = vidsetting == "RTjpeg" || !fifodir.isEmpty();
549  bool rescale = (video_width != newWidth) || (video_height != newHeight) || nonAligned;
550 
551  if (rescale)
552  {
553  if (nonAligned)
554  {
555  // Set a stride identical to actual width, to ease fifo post-conversion process.
556  // 1080i/p video is actually 1088 because of the 16x16 blocks so
557  // we have to fudge the output size here. nuvexport knows how to handle
558  // this and as of right now it is the only app that uses the fifo ability.
559  size_t newSize = MythVideoFrame::GetBufferSize(FMT_YV12,
560  video_width, video_height == 1080 ? 1088 : video_height, 0 /* aligned */);
561  uint8_t* newbuffer = MythVideoFrame::GetAlignedBuffer(newSize);
562  if (!newbuffer)
563  return REENCODE_ERROR;
564  frame.Init(FMT_YV12, newbuffer, newSize, video_width, video_height, nullptr, 0);
565  }
566  else
567  {
568  frame.Init(FMT_YV12, newWidth, newHeight);
569  }
570  }
571 
572  if (!fifodir.isEmpty())
573  {
574  AudioPlayer *aplayer = player->GetAudio();
575  const char *audio_codec_name {nullptr};
576 
577  switch(aplayer->GetCodec())
578  {
579  case AV_CODEC_ID_AC3:
580  audio_codec_name = "ac3";
581  break;
582  case AV_CODEC_ID_EAC3:
583  audio_codec_name = "eac3";
584  break;
585  case AV_CODEC_ID_DTS:
586  audio_codec_name = "dts";
587  break;
588  case AV_CODEC_ID_TRUEHD:
589  audio_codec_name = "truehd";
590  break;
591  case AV_CODEC_ID_MP3:
592  audio_codec_name = "mp3";
593  break;
594  case AV_CODEC_ID_MP2:
595  audio_codec_name = "mp2";
596  break;
597  case AV_CODEC_ID_AAC:
598  audio_codec_name = "aac";
599  break;
600  case AV_CODEC_ID_AAC_LATM:
601  audio_codec_name = "aac_latm";
602  break;
603  default:
604  audio_codec_name = "unknown";
605  }
606 
607  if (!arb->m_passthru)
608  audio_codec_name = "raw";
609 
610  // If cutlist is used then get info on first uncut frame
611  if (honorCutList && fifo_info)
612  {
613  bool is_key = false;
614  int did_ff = 0;
615  player->TranscodeGetNextFrame(did_ff, is_key, true);
616 
617  QSize buf_size2 = player->GetVideoBufferSize();
618  video_width = buf_size2.width();
619  video_height = buf_size2.height();
620  video_aspect = player->GetVideoAspect();
621  video_frame_rate = player->GetFrameRate();
622  }
623 
624  // Display details of the format of the fifo data.
625  LOG(VB_GENERAL, LOG_INFO,
626  QString("FifoVideoWidth %1").arg(video_width));
627  LOG(VB_GENERAL, LOG_INFO,
628  QString("FifoVideoHeight %1").arg(video_height));
629  LOG(VB_GENERAL, LOG_INFO,
630  QString("FifoVideoAspectRatio %1").arg(video_aspect));
631  LOG(VB_GENERAL, LOG_INFO,
632  QString("FifoVideoFrameRate %1").arg(video_frame_rate));
633  LOG(VB_GENERAL, LOG_INFO,
634  QString("FifoAudioFormat %1").arg(audio_codec_name));
635  LOG(VB_GENERAL, LOG_INFO,
636  QString("FifoAudioChannels %1").arg(arb->m_channels));
637  LOG(VB_GENERAL, LOG_INFO,
638  QString("FifoAudioSampleRate %1").arg(arb->m_eff_audiorate));
639 
640  if(fifo_info)
641  {
642  // Request was for just the format of fifo data, not for
643  // the actual transcode, so stop here.
644  unlink(outputname.toLocal8Bit().constData());
645  SetPlayerContext(nullptr);
646  return REENCODE_OK;
647  }
648 
649  QString audfifo = fifodir + QString("/audout");
650  QString vidfifo = fifodir + QString("/vidout");
651  int audio_size = arb->m_eff_audiorate * arb->m_bytes_per_frame;
652  // framecontrol is true if we want to enforce fifo sync.
653  if (framecontrol)
654  LOG(VB_GENERAL, LOG_INFO, "Enforcing sync on fifos");
655  m_fifow = new MythFIFOWriter(2, framecontrol);
656 
657  if (!m_fifow->FIFOInit(0, QString("video"), vidfifo, frame.m_bufferSize, 50) ||
658  !m_fifow->FIFOInit(1, QString("audio"), audfifo, audio_size, 25))
659  {
660  LOG(VB_GENERAL, LOG_ERR,
661  "Error initializing fifo writer. Aborting");
662  unlink(outputname.toLocal8Bit().constData());
663  SetPlayerContext(nullptr);
664  return REENCODE_ERROR;
665  }
666  LOG(VB_GENERAL, LOG_INFO,
667  QString("Video %1x%2@%3fps Audio rate: %4")
668  .arg(video_width).arg(video_height)
669  .arg(video_frame_rate)
670  .arg(arb->m_eff_audiorate));
671  LOG(VB_GENERAL, LOG_INFO, "Created fifos. Waiting for connection.");
672  }
673 
674  frm_dir_map_t::iterator dm_iter;
675 
676  int did_ff = 0;
677 
678  long curFrameNum = 0;
679  frame.m_frameNumber = 1;
680  long totalAudio = 0;
681  int dropvideo = 0;
682  // timecode of the last read video frame in input time
683  std::chrono::milliseconds lasttimecode = 0ms;
684  // timecode of the last write video frame in input or output time
685  std::chrono::milliseconds lastWrittenTime = 0ms;
686  // delta between the same video frame in input and output due to applying the cut list
687  std::chrono::milliseconds timecodeOffset = 0ms;
688 
689  float rateTimeConv = arb->m_eff_audiorate / 1000.0F;
690  float vidFrameTime = 1000.0F / video_frame_rate;
691  auto vidFrameTimeMs = millisecondsFromFloat(vidFrameTime);
692  int wait_recover = 0;
693  MythVideoOutput *videoOutput = player->GetVideoOutput();
694  bool is_key = false;
695  AVFrame imageIn;
696  AVFrame imageOut;
697  struct SwsContext *scontext = nullptr;
698 
699  if (m_fifow)
700  LOG(VB_GENERAL, LOG_INFO, "Dumping Video and Audio data to fifos");
701  else if (m_hlsMode)
702  LOG(VB_GENERAL, LOG_INFO, "Transcoding for HTTP Live Streaming");
703  else if (m_avfMode)
704  LOG(VB_GENERAL, LOG_INFO, "Transcoding to libavformat container");
705  else
706  LOG(VB_GENERAL, LOG_INFO, "Transcoding Video and Audio");
707 
708  auto *videoBuffer =
709  new VideoDecodeBuffer(player, videoOutput, honorCutList);
710  MThreadPool::globalInstance()->start(videoBuffer, "VideoDecodeBuffer");
711 
712  QElapsedTimer flagTime;
713  flagTime.start();
714 
715  if (cutter)
716  cutter->Activate(vidFrameTime * rateTimeConv, total_frame_count);
717 
718  bool stopSignalled = false;
719  MythVideoFrame *lastDecode = nullptr;
720 
721  if (hls)
722  {
724  hls->UpdateStatusMessage("Transcoding");
725  }
726 
727  while ((!stopSignalled) &&
728  (lastDecode = videoBuffer->GetFrame(did_ff, is_key)))
729  {
730  float new_aspect = lastDecode->m_aspect;
731 
732  if (cutter)
733  cutter->NewFrame(lastDecode->m_frameNumber);
734 
735 // frame timecode is on input time base
736  frame.m_timecode = lastDecode->m_timecode;
737 
738  // if the timecode jumps backwards just use the last frame's timecode plus the duration of a frame
739  if (frame.m_timecode < lasttimecode)
740  frame.m_timecode = lasttimecode + vidFrameTimeMs;
741 
742  if (m_fifow)
743  {
744  MythAVUtil::FillAVFrame(&imageIn, lastDecode);
745  MythAVUtil::FillAVFrame(&imageOut, &frame);
746 
747  scontext = sws_getCachedContext(scontext,
748  lastDecode->m_width, lastDecode->m_height, MythAVUtil::FrameTypeToPixelFormat(lastDecode->m_type),
750  SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);
751  // Typically, wee aren't rescaling per say, we're just correcting the stride set by the decoder.
752  // However, it allows to properly handle recordings that see their resolution change half-way.
753  sws_scale(scontext, imageIn.data, imageIn.linesize, 0,
754  lastDecode->m_height, imageOut.data, imageOut.linesize);
755 
756  totalAudio += arb->GetSamples(frame.m_timecode);
757  std::chrono::milliseconds audbufTime = millisecondsFromFloat(totalAudio / rateTimeConv);
758  std::chrono::milliseconds auddelta = frame.m_timecode - audbufTime;
759  std::chrono::milliseconds vidTime = millisecondsFromFloat(curFrameNum * vidFrameTime);
760  std::chrono::milliseconds viddelta = frame.m_timecode - vidTime;
761  std::chrono::milliseconds delta = viddelta - auddelta;
762  std::chrono::milliseconds absdelta = std::chrono::abs(delta);
763  if (absdelta < 500ms && absdelta >= vidFrameTimeMs)
764  {
765  QString msg = QString("Audio is %1ms %2 video at # %3: "
766  "auddelta=%4, viddelta=%5")
767  .arg(absdelta.count())
768  .arg(((delta > 0ms) ? "ahead of" : "behind"))
769  .arg((int)curFrameNum)
770  .arg(auddelta.count())
771  .arg(viddelta.count());
772  LOG(VB_GENERAL, LOG_INFO, msg);
773  dropvideo = (delta > 0ms) ? 1 : -1;
774  wait_recover = 0;
775  }
776  else if (delta >= 500ms && delta < 10s)
777  {
778  if (wait_recover == 0)
779  {
780  dropvideo = 5;
781  wait_recover = 6;
782  }
783  else if (wait_recover == 1)
784  {
785  // Video is badly lagging. Try to catch up.
786  int count = 0;
787  while (delta > vidFrameTimeMs)
788  {
789  if (!cutter || !cutter->InhibitDummyFrame())
790  m_fifow->FIFOWrite(0, frame.m_buffer, frame.m_bufferSize);
791 
792  count++;
793  delta -= vidFrameTimeMs;
794  }
795  QString msg = QString("Added %1 blank video frames")
796  .arg(count);
797  LOG(VB_GENERAL, LOG_INFO, msg);
798  curFrameNum += count;
799  dropvideo = 0;
800  wait_recover = 0;
801  }
802  else
803  {
804  wait_recover--;
805  }
806  }
807  else
808  {
809  dropvideo = 0;
810  wait_recover = 0;
811  }
812 
813 #if 0
814  int buflen = (int)(arb->audiobuffer_len / rateTimeConv);
815  LOG(VB_GENERAL, LOG_DEBUG,
816  QString("%1: video time: %2 audio time: %3 "
817  "buf: %4 exp: %5 delta: %6")
818  .arg(curFrameNum) .arg(frame.m_timecode.count())
819  .arg(arb->last_audiotime) .arg(buflen) .arg(audbufTime.count())
820  .arg(delta.count()));
821 #endif
822  AudioBuffer *ab = nullptr;
823  while ((ab = arb->GetData(frame.m_timecode)) != nullptr)
824  {
825  if (!cutter ||
826  !cutter->InhibitUseAudioFrames(ab->m_frames, &totalAudio))
827  m_fifow->FIFOWrite(1, ab->data(), ab->size());
828 
829  delete ab;
830  }
831 
832  if (dropvideo < 0)
833  {
834  if (cutter && cutter->InhibitDropFrame())
835  m_fifow->FIFOWrite(0, frame.m_buffer, frame.m_bufferSize);
836 
837  LOG(VB_GENERAL, LOG_INFO, "Dropping video frame");
838  dropvideo++;
839  curFrameNum--;
840  }
841  else
842  {
843  if (!cutter || !cutter->InhibitUseVideoFrame())
844  m_fifow->FIFOWrite(0, frame.m_buffer, frame.m_bufferSize);
845 
846  if (dropvideo)
847  {
848  if (!cutter || !cutter->InhibitDummyFrame())
849  m_fifow->FIFOWrite(0, frame.m_buffer, frame.m_bufferSize);
850 
851  curFrameNum++;
852  dropvideo--;
853  }
854  }
855  videoOutput->DoneDisplayingFrame(lastDecode);
856  player->GetCC608Reader()->FlushTxtBuffers();
857  lasttimecode = frame.m_timecode;
858  }
859  else
860  {
861  if (did_ff == 1)
862  {
863  did_ff = 2;
864  timecodeOffset += (frame.m_timecode - lasttimecode -
865  millisecondsFromFloat(vidFrameTime));
866  }
867 
868  if (video_aspect != new_aspect)
869  {
870  video_aspect = new_aspect;
871  }
872 
873 
874  QSize buf_size4 = player->GetVideoBufferSize();
875 
876  if (video_width != buf_size4.width() ||
877  video_height != buf_size4.height())
878  {
879  video_width = buf_size4.width();
880  video_height = buf_size4.height();
881 
882  LOG(VB_GENERAL, LOG_INFO,
883  QString("Resizing from %1x%2 to %3x%4")
884  .arg(video_width).arg(video_height)
885  .arg(newWidth).arg(newHeight));
886  }
887 
888  if (rescale)
889  {
890  MythAVUtil::FillAVFrame(&imageIn, lastDecode);
891  MythAVUtil::FillAVFrame(&imageOut, &frame);
892 
893  int bottomBand = (lastDecode->m_height == 1088) ? 8 : 0;
894  scontext = sws_getCachedContext(scontext,
895  lastDecode->m_width, lastDecode->m_height, MythAVUtil::FrameTypeToPixelFormat(lastDecode->m_type),
897  SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);
898 
899  sws_scale(scontext, imageIn.data, imageIn.linesize, 0,
900  lastDecode->m_height - bottomBand,
901  imageOut.data, imageOut.linesize);
902  }
903 
904  // audio is fully decoded, so we need to reencode it
905  AudioBuffer *ab = nullptr;
906  while ((ab = arb->GetData(lastWrittenTime)) != nullptr)
907  {
908  auto *buf = (unsigned char *)ab->data();
909  if (m_avfMode)
910  {
911  if (did_ff != 1)
912  {
913  std::chrono::milliseconds tc = ab->m_time - timecodeOffset;
914  avfw->WriteAudioFrame(buf, audioFrame, tc);
915 
916  if (avfw2)
917  {
918  if ((avfw2->GetTimecodeOffset() == -1ms) &&
919  (avfw->GetTimecodeOffset() != -1ms))
920  {
921  avfw2->SetTimecodeOffset(
922  avfw->GetTimecodeOffset());
923  }
924 
925  tc = ab->m_time - timecodeOffset;
926  avfw2->WriteAudioFrame(buf, audioFrame, tc);
927  }
928 
929  ++audioFrame;
930  }
931  }
932  delete ab;
933  }
934 
935  if (!m_avfMode)
936  {
937  LOG(VB_GENERAL, LOG_ERR,
938  "AVFormat mode not set.");
939  return REENCODE_ERROR;
940  }
941  lasttimecode = frame.m_timecode;
942  frame.m_timecode -= timecodeOffset;
943 
944  if (m_avfMode)
945  {
946  if (halfFramerate && !skippedLastFrame)
947  {
948  skippedLastFrame = true;
949  }
950  else
951  {
952  skippedLastFrame = false;
953 
954  if ((hls) &&
955  (avfw->GetFramesWritten()) &&
956  (hlsSegmentFrames > hlsSegmentSize) &&
957  (avfw->NextFrameIsKeyFrame()))
958  {
959  hls->AddSegment();
960  avfw->ReOpen(hls->GetCurrentFilename());
961 
962  if (avfw2)
963  avfw2->ReOpen(hls->GetCurrentFilename(true));
964 
965  hlsSegmentFrames = 0;
966  }
967 
968  if (avfw->WriteVideoFrame(rescale ? &frame : lastDecode) > 0)
969  {
970  lastWrittenTime = frame.m_timecode + timecodeOffset;
971  if (hls)
972  ++hlsSegmentFrames;
973  }
974 
975  }
976  }
977  }
978  if (MythDate::current() > statustime)
979  {
980  if (m_showProgress)
981  {
982  LOG(VB_GENERAL, LOG_INFO,
983  QString("Processed: %1 of %2 frames(%3 seconds)").
984  arg(curFrameNum).arg((long)total_frame_count).
985  arg((long)(curFrameNum / video_frame_rate)));
986  }
987 
988  if (hls && hls->CheckStop())
989  {
991  stopSignalled = true;
992  }
993 
994  statustime = MythDate::current().addSecs(5);
995  }
996  if (MythDate::current() > curtime)
997  {
998  if (honorCutList && m_proginfo && !m_avfMode &&
1000  {
1001  LOG(VB_GENERAL, LOG_NOTICE,
1002  "Transcoding aborted, cutlist updated");
1003 
1004  unlink(outputname.toLocal8Bit().constData());
1005  SetPlayerContext(nullptr);
1006  if (videoBuffer)
1007  videoBuffer->stop();
1008  return REENCODE_CUTLIST_CHANGE;
1009  }
1010 
1011  if ((jobID >= 0) || (VERBOSE_LEVEL_CHECK(VB_GENERAL, LOG_INFO)))
1012  {
1014  {
1015  LOG(VB_GENERAL, LOG_NOTICE,
1016  "Transcoding STOPped by JobQueue");
1017 
1018  unlink(outputname.toLocal8Bit().constData());
1019  SetPlayerContext(nullptr);
1020  if (videoBuffer)
1021  videoBuffer->stop();
1022  if (hls)
1023  {
1025  hls->UpdateStatusMessage("Transcoding Stopped");
1026  }
1027  return REENCODE_STOPPED;
1028  }
1029 
1030  float flagFPS = 0.0;
1031  float elapsed = flagTime.elapsed() / 1000.0;
1032  if (elapsed != 0.0F)
1033  flagFPS = curFrameNum / elapsed;
1034 
1035  total_frame_count = player->GetCurrentFrameCount();
1036  int percentage = curFrameNum * 100 / total_frame_count;
1037 
1038  if (hls)
1039  hls->UpdatePercentComplete(percentage);
1040 
1041  if (jobID >= 0)
1042  {
1044  QObject::tr("%1% Completed @ %2 fps.")
1045  .arg(percentage).arg(flagFPS));
1046  }
1047  else
1048  {
1049  LOG(VB_GENERAL, LOG_INFO,
1050  QString("mythtranscode: %1% Completed @ %2 fps.")
1051  .arg(percentage).arg(flagFPS));
1052  }
1053 
1054  }
1055  curtime = MythDate::current().addSecs(20);
1056  }
1057 
1058  curFrameNum++;
1059  frame.m_frameNumber = 1 + (curFrameNum << 1);
1060 
1061  player->DiscardVideoFrame(lastDecode);
1062  }
1063 
1064  sws_freeContext(scontext);
1065 
1066  if (!m_fifow)
1067  {
1068  if (avfw)
1069  avfw->CloseFile();
1070 
1071  if (avfw2)
1072  avfw2->CloseFile();
1073 
1074  if (!m_avfMode && m_proginfo)
1075  {
1080  }
1081  } else {
1082  m_fifow->FIFODrain();
1083  }
1084 
1085  if (hls)
1086  {
1087  if (!stopSignalled)
1088  {
1090  hls->UpdateStatusMessage("Transcoding Completed");
1091  hls->UpdatePercentComplete(100);
1092  }
1093  else
1094  {
1096  hls->UpdateStatusMessage("Transcoding Stopped");
1097  }
1098  }
1099 
1100  if (videoBuffer)
1101  videoBuffer->stop();
1102 
1103  SetPlayerContext(nullptr);
1104 
1105  return REENCODE_OK;
1106 }
1107 
1108 /* vim: set expandtab tabstop=4 shiftwidth=4: */
1109 
HTTPLiveStream::GetSourceFile
QString GetSourceFile(void) const
Definition: httplivestream.h:40
JobQueue::GetJobCmd
static enum JobCmds GetJobCmd(int jobID)
Definition: jobqueue.cpp:1465
MythMediaWriter::SetTimecodeOffset
void SetTimecodeOffset(std::chrono::milliseconds Offset)
Definition: mythmediawriter.cpp:99
HTTPLiveStream::GetWidth
uint16_t GetWidth(void) const
Definition: httplivestream.h:34
Cutter::Activate
void Activate(float v2a, int64_t total)
Definition: cutter.cpp:63
HTTPLiveStream::CheckStop
bool CheckStop(void)
Definition: httplivestream.cpp:799
MythMediaWriter::SetAudioFrameRate
void SetAudioFrameRate(int Rate)
Definition: mythmediawriter.cpp:84
Transcode::m_cmdContainer
QString m_cmdContainer
Definition: transcode.h:63
Cutter::InhibitDummyFrame
bool InhibitDummyFrame(void)
Definition: cutter.cpp:155
RemoteGetExistingRecorder
RemoteEncoder * RemoteGetExistingRecorder(const ProgramInfo *pginfo)
Definition: tvremoteutil.cpp:313
MARK_KEYFRAME
@ MARK_KEYFRAME
Definition: programtypes.h:61
HTTPLiveStream::GetCurrentFilename
QString GetCurrentFilename(bool audioOnly=false, bool encoded=false) const
Definition: httplivestream.cpp:202
MythVideoOutput
Definition: mythvideoout.h:35
deletemap.h
Transcode::m_fifow
MythFIFOWriter * m_fifow
Definition: transcode.h:55
HTTPLiveStream::UpdateSizeInfo
bool UpdateSizeInfo(uint16_t width, uint16_t height, uint16_t srcwidth, uint16_t srcheight)
Definition: httplivestream.cpp:528
AudioReencodeBuffer
This class is to act as a fake audio output device to store the data for reencoding.
Definition: audioreencodebuffer.h:31
AudioPlayer
Definition: audioplayer.h:22
MARK_GOP_START
@ MARK_GOP_START
Definition: programtypes.h:60
Transcode::m_outBuffer
MythMediaBuffer * m_outBuffer
Definition: transcode.h:54
MythAVFormatWriter::ReOpen
bool ReOpen(const QString &Filename)
Definition: mythavformatwriter.cpp:411
AudioReencodeBuffer::m_eff_audiorate
int m_eff_audiorate
Definition: audioreencodebuffer.h:73
FORMAT_S16
@ FORMAT_S16
Definition: audiooutputsettings.h:27
MythMediaWriter::SetVideoCodec
void SetVideoCodec(const QString &Codec)
Definition: mythmediawriter.cpp:34
kHLSStatusRunning
@ kHLSStatusRunning
Definition: httplivestream.h:12
kHLSStatusCompleted
@ kHLSStatusCompleted
Definition: httplivestream.h:13
RecordingProfile::loadByGroup
virtual bool loadByGroup(const QString &name, const QString &group)
Definition: recordingprofile.cpp:1550
MythMediaWriter::SetAudioCodec
void SetAudioCodec(const QString &Codec)
Definition: mythmediawriter.cpp:69
Transcode::m_recProfile
RecordingProfile * m_recProfile
Definition: transcode.h:51
cutter.h
Transcode::Transcode
Transcode(ProgramInfo *pginfo)
Definition: transcode.cpp:50
VERBOSE_LEVEL_CHECK
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
Definition: mythlogging.h:29
mythdbcon.h
MythMediaWriter::SetAudioChannels
void SetAudioChannels(int Channels)
Definition: mythmediawriter.cpp:79
frm_dir_map_t
QMap< uint64_t, MarkTypes > frm_dir_map_t
Frame # -> Mark map.
Definition: programtypes.h:117
MythMediaWriter::GetFramesWritten
long long GetFramesWritten(void) const
Definition: mythmediawriter.cpp:114
MythVideoFrame::m_width
int m_width
Definition: mythframe.h:120
Transcode::m_cmdAudioBitrate
int m_cmdAudioBitrate
Definition: transcode.h:69
MythMediaBuffer
Definition: mythmediabuffer.h:59
RecordingProfile::loadByID
virtual void loadByID(int id)
Definition: recordingprofile.cpp:1456
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythFIFOWriter
Definition: mythfifowriter.h:31
kHLSStatusStopped
@ kHLSStatusStopped
Definition: httplivestream.h:16
MythVideoFrame::Init
void Init(VideoFrameType Type, int Width, int Height, const VideoFrameTypes *RenderFormats=nullptr)
Definition: mythframe.cpp:42
httplivestream.h
kHLSStatusStopping
@ kHLSStatusStopping
Definition: httplivestream.h:15
PlayerFlags
PlayerFlags
Definition: mythplayer.h:64
HTTPLiveStream::UpdateStatus
bool UpdateStatus(HTTPLiveStreamStatus status)
Definition: httplivestream.cpp:579
MARK_UPDATED_CUT
@ MARK_UPDATED_CUT
Definition: programtypes.h:52
ProgramInfo::GetRecordingEndTime
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end.
Definition: programinfo.h:413
Transcode::m_cmdHeight
int m_cmdHeight
Definition: transcode.h:67
Transcode::m_hlsStreamID
int m_hlsStreamID
Definition: transcode.h:60
REENCODE_ERROR
@ REENCODE_ERROR
Definition: transcodedefs.h:8
MythMediaWriter::SetEncodingPreset
void SetEncodingPreset(const QString &Preset)
Definition: mythmediawriter.cpp:104
HTTPLiveStream::GetSegmentSize
uint16_t GetSegmentSize(void) const
Definition: httplivestream.h:44
MythFIFOWriter::FIFODrain
void FIFODrain(void)
Definition: mythfifowriter.cpp:259
jobID
int jobID
Definition: mythcommflag.cpp:71
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:15
JobQueue::IsJobRunning
static bool IsJobRunning(int jobType, uint chanid, const QDateTime &recstartts)
Definition: jobqueue.cpp:1086
MythMediaWriter::SetFilename
void SetFilename(const QString &FileName)
Definition: mythmediawriter.cpp:24
REENCODE_STOPPED
@ REENCODE_STOPPED
Definition: transcodedefs.h:9
Transcode::m_hlsDisableAudioOnly
bool m_hlsDisableAudioOnly
Definition: transcode.h:61
Cutter::AdjustedCutList
frm_dir_map_t AdjustedCutList() const
Definition: cutter.cpp:58
MythMediaWriter::GetAudioFrameSize
int GetAudioFrameSize(void) const
Definition: mythmediawriter.cpp:124
Transcode::m_hlsMaxSegments
int m_hlsMaxSegments
Definition: transcode.h:62
AVFrame
struct AVFrame AVFrame
Definition: BorderDetector.h:15
AudioOutput
Definition: audiooutput.h:24
AudioBuffer::m_time
std::chrono::milliseconds m_time
Definition: audioreencodebuffer.h:24
HTTPLiveStream::GetAudioBitrate
uint32_t GetAudioBitrate(void) const
Definition: httplivestream.h:37
programinfo.h
MythVideoFrame::GetBufferSize
static size_t GetBufferSize(VideoFrameType Type, int Width, int Height, int Aligned=MYTH_WIDTH_ALIGNMENT)
Definition: mythframe.cpp:412
ProgramInfo::QueryMarkupFlag
bool QueryMarkupFlag(MarkTypes type) const
Returns true iff the speficied mark type is set on frame 0.
Definition: programinfo.cpp:3776
Transcode::m_cmdVideoCodec
QString m_cmdVideoCodec
Definition: transcode.h:65
mythlogging.h
AudioReencodeBuffer::GetData
AudioBuffer * GetData(std::chrono::milliseconds time)
Definition: audioreencodebuffer.cpp:202
Transcode::GetPlayer
MythPlayer * GetPlayer(void)
Definition: transcode.h:47
AudioReencodeBuffer::m_bytes_per_frame
int m_bytes_per_frame
Definition: audioreencodebuffer.h:72
MythMediaWriter::SetWidth
void SetWidth(int Width)
Definition: mythmediawriter.cpp:44
MythAVFormatWriter::OpenFile
bool OpenFile(void) override
Definition: mythavformatwriter.cpp:132
JobQueue::ChangeJobComment
static bool ChangeJobComment(int jobID, const QString &comment="")
Definition: jobqueue.cpp:1010
FORMAT_NONE
@ FORMAT_NONE
Definition: audiooutputsettings.h:25
HTTPLiveStream::InitForWrite
bool InitForWrite(void)
Definition: httplivestream.cpp:167
MythVideoFrame::m_timecode
std::chrono::milliseconds m_timecode
Definition: mythframe.h:130
Transcode::m_cmdAudioCodec
QString m_cmdAudioCodec
Definition: transcode.h:64
Cutter::NewFrame
void NewFrame(int64_t currentFrame)
Definition: cutter.cpp:73
kTranscoderInUseID
const QString kTranscoderInUseID
Definition: programtypes.cpp:24
mythtranscodeplayer.h
MythAVFormatWriter::NextFrameIsKeyFrame
bool NextFrameIsKeyFrame(void)
Definition: mythavformatwriter.cpp:199
HTTPLiveStream::UpdateStatusMessage
bool UpdateStatusMessage(const QString &message)
Definition: httplivestream.cpp:617
MythMediaWriter::SetEncodingTune
void SetEncodingTune(const QString &Tune)
Definition: mythmediawriter.cpp:109
ProgramInfo::QueryCutList
bool QueryCutList(frm_dir_map_t &delMap, bool loadAutosave=false) const
Definition: programinfo.cpp:3485
MythVideoFrame::m_frameNumber
long long m_frameNumber
Definition: mythframe.h:128
MythFIFOWriter::FIFOInit
bool FIFOInit(uint Id, const QString &Desc, const QString &Name, long Size, int NumBufs)
Definition: mythfifowriter.cpp:109
AudioReencodeBuffer::m_audioFrameSize
int m_audioFrameSize
Definition: audioreencodebuffer.h:76
JOB_COMMFLAG
@ JOB_COMMFLAG
Definition: jobqueue.h:79
MythMediaWriter::SetAudioBitrate
void SetAudioBitrate(int Bitrate)
Definition: mythmediawriter.cpp:74
HTTPLiveStream::GetBitrate
uint32_t GetBitrate(void) const
Definition: httplivestream.h:36
AudioBuffer::size
int size(void) const
Definition: audioreencodebuffer.h:18
MythVideoFrame::m_bufferSize
size_t m_bufferSize
Definition: mythframe.h:123
ProgramInfo::ClearMarkupFlag
void ClearMarkupFlag(MarkTypes type) const
Definition: programinfo.h:652
FMT_YV12
@ FMT_YV12
Definition: mythframe.h:23
HTTPLiveStream::GetAudioOnlyBitrate
uint32_t GetAudioOnlyBitrate(void) const
Definition: httplivestream.h:38
REENCODE_CUTLIST_CHANGE
@ REENCODE_CUTLIST_CHANGE
Definition: transcodedefs.h:6
MythAVFormatWriter::CloseFile
bool CloseFile(void) override
Definition: mythavformatwriter.cpp:184
jobqueue.h
AudioBuffer::data
char * data(void) const
Definition: audioreencodebuffer.h:17
mythavformatwriter.h
kNoITV
@ kNoITV
Definition: mythplayer.h:75
HTTPLiveStream::AddSegment
bool AddSegment(void)
Definition: httplivestream.cpp:306
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:57
HTTPLiveStream::GetHeight
uint16_t GetHeight(void) const
Definition: httplivestream.h:35
Cutter::InhibitDropFrame
bool InhibitDropFrame(void)
Definition: cutter.cpp:167
DEINT_CPU
@ DEINT_CPU
Definition: mythframe.h:72
MythMediaWriter::SetKeyFrameDist
void SetKeyFrameDist(int Dist)
Definition: mythmediawriter.cpp:64
Cutter::InhibitUseAudioFrames
bool InhibitUseAudioFrames(int64_t frames, long *totalAudio)
Definition: cutter.cpp:120
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:918
Transcode::m_cmdBitrate
int m_cmdBitrate
Definition: transcode.h:68
MythAVFormatWriter::WriteVideoFrame
int WriteVideoFrame(MythVideoFrame *Frame) override
Definition: mythavformatwriter.cpp:205
HTTPLiveStream::UpdatePercentComplete
bool UpdatePercentComplete(int percent)
Definition: httplivestream.cpp:642
MARK_GOP_BYFRAME
@ MARK_GOP_BYFRAME
Definition: programtypes.h:63
MythFIFOWriter::FIFOWrite
void FIFOWrite(uint Id, void *Buffer, long Size)
Definition: mythfifowriter.cpp:214
Transcode::GetProfile
bool GetProfile(const QString &profileName, const QString &encodingType, int height, int frameRate)
Definition: transcode.cpp:64
tvremoteutil.h
DecoderBase::GetVideoAspect
float GetVideoAspect(void) const
Definition: decoderbase.h:182
Transcode::m_proginfo
ProgramInfo * m_proginfo
Definition: transcode.h:50
mthreadpool.h
DEINT_MEDIUM
@ DEINT_MEDIUM
Definition: mythframe.h:70
HTTPLiveStream::GetStreamID
int GetStreamID(void) const
Definition: httplivestream.h:33
AudioBuffer::m_frames
int m_frames
Definition: audioreencodebuffer.h:23
MARK_DURATION_MS
@ MARK_DURATION_MS
Definition: programtypes.h:73
MythMediaWriter::SetThreadCount
void SetThreadCount(int Count)
Definition: mythmediawriter.cpp:94
kVideoIsNull
@ kVideoIsNull
Definition: mythplayer.h:73
MythMediaWriter::SetContainer
void SetContainer(const QString &Cont)
Definition: mythmediawriter.cpp:29
Transcode::m_avfMode
bool m_avfMode
Definition: transcode.h:58
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:67
AudioPlayer::GetCodec
AVCodecID GetCodec(void) const
Definition: audioplayer.h:58
VideoDecodeBuffer
Definition: videodecodebuffer.h:16
mythcorecontext.h
transcode.h
MythMediaWriter::GetTimecodeOffset
std::chrono::milliseconds GetTimecodeOffset(void) const
Definition: mythmediawriter.cpp:119
MythVideoFrame::m_type
VideoFrameType m_type
Definition: mythframe.h:118
ProgramInfo::QueryIsEditing
bool QueryIsEditing(void) const
Queries "recorded" table for its "editing" field and returns true if it is set to true.
Definition: programinfo.cpp:3124
JOB_STOP
@ JOB_STOP
Definition: jobqueue.h:54
ProgramInfo::ClearPositionMap
void ClearPositionMap(MarkTypes type) const
Definition: programinfo.cpp:3840
kHLSStatusStarting
@ kHLSStatusStarting
Definition: httplivestream.h:11
AudioReencodeBuffer::m_passthru
bool m_passthru
Definition: audioreencodebuffer.h:75
audiooutput.h
REENCODE_OK
@ REENCODE_OK
Definition: transcodedefs.h:7
MythAVUtil::FrameTypeToPixelFormat
static AVPixelFormat FrameTypeToPixelFormat(VideoFrameType Type)
Definition: mythavutil.cpp:28
Transcode::~Transcode
~Transcode() override
Definition: transcode.cpp:56
mythavutil.h
Transcode::m_hlsMode
bool m_hlsMode
Definition: transcode.h:59
MythMediaWriter::SetHeight
void SetHeight(int Height)
Definition: mythmediawriter.cpp:49
MythMediaWriter::SetFramerate
void SetFramerate(double Rate)
Definition: mythmediawriter.cpp:59
PlayerContext
Definition: playercontext.h:49
MythMediaBuffer::Create
static MythMediaBuffer * Create(const QString &Filename, bool Write, bool UseReadAhead=true, std::chrono::milliseconds Timeout=kDefaultOpenTimeout, bool StreamOnly=false)
Creates a RingBuffer instance.
Definition: mythmediabuffer.cpp:99
MythMediaBuffer::GetLastError
QString GetLastError(void) const
Definition: mythmediabuffer.cpp:1770
AudioBuffer
Definition: audioreencodebuffer.h:9
videodecodebuffer.h
MythVideoFrame::m_height
int m_height
Definition: mythframe.h:121
audioreencodebuffer.h
kTrackTypeAudio
@ kTrackTypeAudio
Definition: decoderbase.h:29
Transcode::m_ctx
PlayerContext * m_ctx
Definition: transcode.h:53
MythMediaWriter::SetAudioFormat
void SetAudioFormat(AudioFormat Format)
Definition: mythmediawriter.cpp:89
MythVideoFrame::GetAlignedBuffer
static uint8_t * GetAlignedBuffer(size_t Size)
Definition: mythframe.cpp:430
recordingprofile.h
Transcode::m_showProgress
bool m_showProgress
Definition: transcode.h:56
MythMediaWriter::SetAspect
void SetAspect(float Aspect)
Definition: mythmediawriter.cpp:54
RecordingProfile
Definition: recordingprofile.h:41
MythVideoFrame
Definition: mythframe.h:87
exitcodes.h
Transcode::SetPlayerContext
void SetPlayerContext(PlayerContext *player_ctx)
Definition: transcode.cpp:125
Transcode::m_cmdWidth
int m_cmdWidth
Definition: transcode.h:66
Cutter::InhibitUseVideoFrame
bool InhibitUseVideoFrame(void)
Definition: cutter.cpp:100
Cutter::SetCutList
void SetCutList(frm_dir_map_t &deleteMap, PlayerContext *ctx)
Definition: cutter.cpp:11
MThreadPool::globalInstance
static MThreadPool * globalInstance(void)
Definition: mthreadpool.cpp:307
MythMediaWriter::SetVideoBitrate
void SetVideoBitrate(int Bitrate)
Definition: mythmediawriter.cpp:39
AudioReencodeBuffer::m_channels
int m_channels
Definition: audioreencodebuffer.h:71
MythAVUtil::FillAVFrame
static int FillAVFrame(AVFrame *Frame, const MythVideoFrame *From, AVPixelFormat Fmt=AV_PIX_FMT_NONE)
Initialise AVFrame with content from MythVideoFrame.
Definition: mythavutil.cpp:199
MythVideoFrame::m_aspect
float m_aspect
Definition: mythframe.h:126
AudioReencodeBuffer::GetSamples
long long GetSamples(std::chrono::milliseconds time)
Definition: audioreencodebuffer.cpp:220
MythAVFormatWriter::Init
bool Init(void) override
Definition: mythavformatwriter.cpp:57
MThreadPool::start
void start(QRunnable *runnable, const QString &debugName, int priority=0)
Definition: mthreadpool.cpp:342
DecoderBase
Definition: decoderbase.h:120
MythAVFormatWriter::WriteAudioFrame
int WriteAudioFrame(unsigned char *Buffer, int FrameNumber, std::chrono::milliseconds &Timecode) override
Definition: mythavformatwriter.cpp:288
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:904
millisecondsFromFloat
std::enable_if_t< std::is_floating_point_v< T >, std::chrono::milliseconds > millisecondsFromFloat(T value)
Helper function for convert a floating point number to a duration.
Definition: mythchrono.h:91
MythVideoFrame::m_buffer
uint8_t * m_buffer
Definition: mythframe.h:119
MythTranscodePlayer
Definition: mythtranscodeplayer.h:7
MythVideoOutput::DoneDisplayingFrame
virtual void DoneDisplayingFrame(MythVideoFrame *Frame)
Releases frame returned from GetLastShownFrame() onto the queue of frames ready for decoding onto.
Definition: mythvideoout.cpp:420
Transcode::TranscodeFile
int TranscodeFile(const QString &inputname, const QString &outputname, const QString &profileName, bool honorCutList, bool framecontrol, int jobID, const QString &fifodir, bool fifo_info, bool cleanCut, frm_dir_map_t &deleteMap, int AudioTrackNo, bool passthru=false)
Definition: transcode.cpp:134