MythTV  master
privatedecoder_crystalhd.cpp
Go to the documentation of this file.
2 #include "mythlogging.h"
3 #include "mythavutil.h"
4 #include "fourcc.h"
5 #include "unistd.h"
6 
7 extern "C" {
8 #include "libavutil/imgutils.h"
9 }
10 
11 #define LOC QString("CrystalHD: ")
12 #define ERR QString("CrystalHD Err: ")
13 #define WARN QString("CrystalHD Warn: ")
14 
16 {
17  RunProlog();
18  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Starting Fetcher thread."));
19  if (m_dec)
20  m_dec->FetchFrames();
21  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Stopping Fetcher thread."));
22  RunEpilog();
23 }
24 
25 AVPixelFormat bcmpixfmt_to_pixfmt(BC_OUTPUT_FORMAT fmt);
26 QString device_to_string(BC_DEVICE_TYPE device);
27 QString bcmerr_to_string(BC_STATUS err);
28 QString bcmpixfmt_to_string(BC_OUTPUT_FORMAT fmt);
29 QString pulldown_to_string(int pulldown);
30 QString decoderflags_to_string(int flags);
31 QString poutflags_to_string(int flags);
32 
33 #define INIT_ST BC_STATUS st; bool ok = true
34 #define CHECK_ST \
35  ok &= (st == BC_STS_SUCCESS); \
36  if (!ok) \
37  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Error at %1:%2 (#%3, %4)") \
38  .arg(__FILE__).arg( __LINE__).arg(st) \
39  .arg(bcmerr_to_string(st)))
40 
42 {
43  opts.decoders->append("crystalhd");
44  (*opts.equiv_decoders)["crystalhd"].append("nuppel");
45  (*opts.equiv_decoders)["crystalhd"].append("ffmpeg");
46  (*opts.equiv_decoders)["crystalhd"].append("dummy");
47 }
48 
50  : m_device(nullptr), m_device_type(BC_70012),
51  m_pix_fmt(OUTPUT_MODE_INVALID), m_decoded_frames_lock(QMutex::Recursive),
52  m_fetcher_thread(nullptr), m_fetcher_pause(false), m_fetcher_paused(false),
53  m_fetcher_stop(false), m_frame(nullptr), m_filter(nullptr)
54 {
55 }
56 
58 {
59  if (m_fetcher_thread)
60  {
61  m_fetcher_pause = true;
62  m_fetcher_stop = true;
63  int tries = 0;
64  while (!m_fetcher_thread->wait(100) && (tries++ < 50))
65  LOG(VB_PLAYBACK, LOG_WARNING, LOC +
66  "Waited 100ms for Fetcher to stop");
67 
69  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to stop Fetcher.");
70  else
71  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Stopped frame Fetcher.");
72  delete m_fetcher_thread;
73  }
74 
75  if (m_filter)
76  av_bitstream_filter_close(m_filter);
77 
78  Reset();
79  if (!m_device)
80  return;
81 
82  INIT_ST;
83  if (m_device_type != BC_70015)
84  {
85  st = DtsFlushRxCapture(m_device, false);
86  CHECK_ST;
87  }
88  st = DtsStopDecoder(m_device);
89  CHECK_ST;
90  st = DtsCloseDecoder(m_device);
91  CHECK_ST;
92  DtsDeviceClose(m_device);
93 }
94 
95 bool PrivateDecoderCrystalHD::Init(const QString &decoder,
96  PlayerFlags flags,
97  AVCodecContext *avctx)
98 {
99  if ((decoder != "crystalhd") || !(flags & kDecodeAllowEXT) ||
100  !avctx || getenv("NO_CRYSTALHD"))
101  return false;
102 
103  static bool debugged = false;
104 
105  uint32_t well_documented = DTS_PLAYBACK_MODE | DTS_LOAD_FILE_PLAY_FW |
106  DTS_SKIP_TX_CHK_CPB |
107  DTS_PLAYBACK_DROP_RPT_MODE |
108  DTS_DFLT_RESOLUTION(vdecRESOLUTION_CUSTOM);
109  INIT_ST;
110  st = DtsDeviceOpen(&m_device, well_documented);
111  CHECK_ST;
112  if (!ok)
113  {
114  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to open CrystalHD device");
115  return false;
116  }
117 
118  _BC_INFO_CRYSTAL_ info;
119  st = DtsCrystalHDVersion(m_device, &info);
120  CHECK_ST;
121  if (!ok)
122  {
123  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to get device info.");
124  return false;
125  }
126 
127  m_device_type = (BC_DEVICE_TYPE)info.device;
128 
129  if (!debugged)
130  {
131  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Device: %1")
133  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Library : %1.%2.%3")
134  .arg(info.dilVersion.dilMajor)
135  .arg(info.dilVersion.dilMinor)
136  .arg(info.dilVersion.version));
137  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Driver : %1.%2.%3")
138  .arg(info.drvVersion.drvMajor)
139  .arg(info.drvVersion.drvMinor)
140  .arg(info.drvVersion.version));
141  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Firmware: %1.%2.%3")
142  .arg(info.fwVersion.fwMajor)
143  .arg(info.fwVersion.fwMinor)
144  .arg(info.fwVersion.version));
145  }
146 
147  if (BC_70012 == m_device_type)
148  {
149  LOG(VB_GENERAL, LOG_ERR, LOC +
150  "BCM70012 device is currently unsupported.");
151  return false;
152  }
153 
154  BC_HW_CAPS hw_caps;
155  uint32_t codecs;
156  st = DtsGetCapabilities(m_device, &hw_caps);
157  CHECK_ST;
158  if (!ok)
159  {
160  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to get device capabilities");
161  return false;
162  }
163 
164  BC_OUTPUT_FORMAT m_desired_fmt = (m_device_type == BC_70015) ?
165  OUTPUT_MODE422_YUY2 : OUTPUT_MODE420;
166  m_pix_fmt = OUTPUT_MODE_INVALID;
167  for (int i = 0; i < hw_caps.ColorCaps.Count; i++)
168  {
169  if (m_desired_fmt == hw_caps.ColorCaps.OutFmt[i])
170  m_pix_fmt = m_desired_fmt;
171  if (!debugged)
172  {
173  LOG(VB_PLAYBACK, LOG_INFO, LOC +
174  QString("Supported output format: %1")
175  .arg(bcmpixfmt_to_string(hw_caps.ColorCaps.OutFmt[i])));
176  }
177  }
178  if (m_pix_fmt != m_desired_fmt)
179  {
180  LOG(VB_PLAYBACK, LOG_ERR, LOC +
181  "Failed to find correct output format.");
182  return false;
183  }
184  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Using: %1")
186 
187  codecs = hw_caps.DecCaps;
188  if (!debugged)
189  {
190  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("H.264 support: %1")
191  .arg((bool)(codecs & BC_DEC_FLAGS_H264)));
192  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("MPEG2 support: %1")
193  .arg((bool)(codecs & BC_DEC_FLAGS_MPEG2)));
194  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("VC1 support: %1")
195  .arg((bool)(codecs & BC_DEC_FLAGS_VC1)));
196  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("MPEG4 support: %1")
197  .arg((bool)(codecs & BC_DEC_FLAGS_M4P2)));
198  debugged = true;
199  }
200 
201  BC_MEDIA_SUBTYPE sub_type = BC_MSUBTYPE_INVALID;
202 
203  switch (avctx->codec_id)
204  {
205  case AV_CODEC_ID_MPEG4:
206  if (codecs & BC_DEC_FLAGS_M4P2)
207  sub_type = BC_MSUBTYPE_DIVX;
208  break;
209  case AV_CODEC_ID_MPEG1VIDEO:
210  if (codecs & BC_DEC_FLAGS_MPEG2)
211  sub_type = BC_MSUBTYPE_MPEG1VIDEO;
212  break;
213  case AV_CODEC_ID_MPEG2VIDEO:
214  if (codecs & BC_DEC_FLAGS_MPEG2)
215  sub_type = BC_MSUBTYPE_MPEG2VIDEO;
216  break;
217  case AV_CODEC_ID_VC1:
218  if (codecs & BC_DEC_FLAGS_VC1)
219  {
220  if (avctx->codec_tag == MKTAG('W','V','C','1'))
221  sub_type = BC_MSUBTYPE_WVC1;
222  else
223  sub_type = BC_MSUBTYPE_VC1;
224  }
225  break;
226  case AV_CODEC_ID_WMV3:
227  if (codecs & BC_DEC_FLAGS_VC1)
228  sub_type = BC_MSUBTYPE_WMV3;
229  break;
230  case AV_CODEC_ID_H264:
231  if (codecs & BC_DEC_FLAGS_H264)
232  {
233  if (avctx->extradata[0] == 0x01)
234  {
235  if (!CreateFilter(avctx))
236  {
237  LOG(VB_PLAYBACK, LOG_ERR, LOC +
238  "Failed to create stream filter");
239  return false;
240  }
241  sub_type = BC_MSUBTYPE_AVC1;
242  }
243  else
244  sub_type = BC_MSUBTYPE_H264;
245  }
246  break;
247  default:
248  break;
249  }
250 
251  if (sub_type == BC_MSUBTYPE_INVALID)
252  {
253  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString("Codec %1 not supported")
254  .arg(ff_codec_id_string(avctx->codec_id)));
255  return false;
256  }
257 
258  int nalsize = 4;
259  if (avctx->codec_id == AV_CODEC_ID_H264)
260  {
261  LOG(VB_PLAYBACK, LOG_INFO, LOC +
262  QString("H.264 Profile: %1 RefFrames: %2 Codec tag: %3")
263  .arg(avctx->profile).arg(avctx->refs)
264  .arg(fourcc_str(avctx->codec_tag)));
265  if (avctx->extradata[0] == 1)
266  {
267  nalsize = (avctx->extradata[4] & 0x03) + 1;
268  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("avcC nal size: %1")
269  .arg(nalsize));
270  }
271  }
272 
273  BC_INPUT_FORMAT fmt;
274  memset(&fmt, 0, sizeof(BC_INPUT_FORMAT));
275  fmt.OptFlags = 0x80000000 | vdecFrameRateUnknown;
276  fmt.width = avctx->coded_width;
277  fmt.height = avctx->coded_height;
278  fmt.Progressive = 1;
279  fmt.FGTEnable = 0;
280  fmt.MetaDataEnable = 0;
281  fmt.metaDataSz = avctx->extradata_size;
282  fmt.pMetaData = avctx->extradata;
283  fmt.startCodeSz = nalsize;
284  fmt.mSubtype = sub_type;
285 
286  st = DtsSetInputFormat(m_device, &fmt);
287  CHECK_ST;
288  if (!ok)
289  {
290  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to set decoder input format");
291  return false;
292  }
293 
294  st = DtsOpenDecoder(m_device, BC_STREAM_TYPE_ES);
295  CHECK_ST;
296  if (!ok)
297  {
298  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to open CrystalHD decoder");
299  return false;
300  }
301 
302  st = DtsSetColorSpace(m_device, m_pix_fmt);
303  if (!ok)
304  {
305  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to set decoder output format");
306  return false;
307  }
308 
309  st = DtsStartDecoder(m_device);
310  if (!ok)
311  {
312  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to start decoder");
313  return false;
314  }
315 
316  st = DtsStartCapture(m_device);
317  if (!ok)
318  {
319  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to start capture");
320  return false;
321  }
322 
323  Reset();
324 
325  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Created decoder %1 %2x%3")
326  .arg(ff_codec_id_string(avctx->codec_id))
327  .arg(avctx->coded_width).arg(avctx->coded_height));
328  return true;
329 }
330 
331 bool PrivateDecoderCrystalHD::CreateFilter(AVCodecContext *avctx)
332 {
333  int nalsize = (avctx->extradata[4] & 0x3) + 1;
334  if (!nalsize || nalsize == 3 || nalsize > 4)
335  {
336  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString("Invalid nal size (%1)")
337  .arg(nalsize));
338  return false;
339  }
340 
341  static const uint8_t testnal[] = { 0,0,0,2,0,0 };
342  AVBitStreamFilterContext *bsfc =
343  av_bitstream_filter_init("h264_mp4toannexb");
344  if (!bsfc)
345  return false;
346  m_filter = bsfc;
347 
348  // and test extradata
349  const uint8_t *test = testnal;
350  int testsize = 6;
351  int outbuf_size = 0;
352  uint8_t *outbuf = nullptr;
353  int res = av_bitstream_filter_filter(m_filter, avctx, nullptr, &outbuf,
354  &outbuf_size, test, testsize, 0);
355  av_freep(&outbuf);
356  return res > 0;
357 }
358 
359 void inline free_frame(VideoFrame* frame)
360 {
361  if (frame)
362  {
363  if (frame->buf)
364  av_freep(&frame->buf);
365  if (frame->priv[0])
366  av_freep(&frame->priv[0]);
367  delete frame;
368  }
369 }
370 
371 void inline free_buffer(PacketBuffer* buffer)
372 {
373  if (buffer)
374  {
375  if (buffer->buf)
376  av_freep(&buffer->buf);
377  delete buffer;
378  }
379 }
380 
382 {
383  if (m_fetcher_thread)
384  {
385  m_fetcher_pause = true;
386  int tries = 0;
387  while (!m_fetcher_paused && (tries++ < 50))
388  usleep(10000);
389  if (!m_fetcher_paused)
390  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to pause fetcher thread");
391  }
392 
393  QMutexLocker lock(&m_decoded_frames_lock);
395  m_frame = nullptr;
396 
397  for (int i = 0; i < m_decoded_frames.size(); i++)
399  m_decoded_frames.clear();
400 
401  for (int i = 0; i < m_packet_buffers.size(); i++)
403  m_packet_buffers.clear();
404 
405  if (!m_device)
406  return true;
407 
408  if (m_device_type != BC_70015)
409  {
410  INIT_ST;
411  st = DtsFlushInput(m_device, 2);
412  CHECK_ST;
413  }
414  return true;;
415 }
416 
418 {
419  m_decoded_frames_lock.lock();
420  bool result = m_decoded_frames.size() > 0;
421  m_decoded_frames_lock.unlock();
422  return result;
423 }
424 
425 int PrivateDecoderCrystalHD::ProcessPacket(AVStream *stream, AVPacket *pkt)
426 {
427  int result = -1;
428  AVCodecContext *avctx = gCodecMap->getCodecContext(stream);
429  if (!avctx)
430  return result;
431 
432  PacketBuffer *buffer1 = new PacketBuffer();
433  if (!buffer1)
434  return result;
435 
436  buffer1->buf = (unsigned char*)av_malloc(pkt->size);
437  buffer1->size = pkt->size;
438  buffer1->pts = pkt->pts;
439  memcpy(buffer1->buf, pkt->data, pkt->size);
440 
441  m_packet_buffers.insert(0, buffer1);
442  LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
443  QString("%1 packet buffers queued up").arg(m_packet_buffers.size()));
444 
445  while (m_packet_buffers.size() > 0)
446  {
447  PacketBuffer *buffer2 = m_packet_buffers.last();
448  if (GetTxFreeSize(false) < buffer2->size)
449  {
450  usleep(10000);
451  return 0;
452  }
453 
454  buffer2 = m_packet_buffers.takeLast();
455  uint8_t* buf = buffer2->buf;
456  int size = buffer2->size;
457  bool free_buf = false;
458  int outbuf_size = 0;
459  uint8_t *outbuf = nullptr;
460 
461  if (m_filter)
462  {
463  int res = av_bitstream_filter_filter(m_filter, avctx, nullptr, &outbuf,
464  &outbuf_size, buf, size, 0);
465  if (res <= 0)
466  {
467  static int count = 0;
468  if (count == 0)
469  LOG(VB_GENERAL, LOG_ERR, LOC +
470  QString("Failed to convert packet (%1)").arg(res));
471  count++;
472  if (count > 200)
473  count = 0;
474  }
475 
476  if (outbuf && (outbuf_size > 0))
477  {
478  free_buf = outbuf != buf;
479  size = outbuf_size;
480  buf = outbuf;
481  }
482  }
483 
484  usleep(1000);
485  uint64_t chd_timestamp = 0; // 100 nsec units
486  if (buffer2->pts != AV_NOPTS_VALUE)
487  chd_timestamp = (uint64_t)(av_q2d(stream->time_base) *
488  buffer2->pts * 10000000);
489  LOG(VB_TIMESTAMP, LOG_DEBUG, LOC +
490  QString("decoder input timecode %1 ms (pts %2)")
491  .arg(chd_timestamp / 10000).arg(buffer2->pts));
492 
493  // TODO check for busy state
494  INIT_ST;
495  st = DtsProcInput(m_device, buf, size, chd_timestamp, false);
496  CHECK_ST;
497 
498  if (free_buf)
499  av_freep(&buf);
500 
501  if (!ok)
502  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to send packet to decoder.");
503 
504  result = buffer2->size;
505 
506  free_buffer(buffer2);
507  }
508  return result;
509 }
510 
512  AVFrame *picture,
513  int *got_picture_ptr,
514  AVPacket *pkt)
515 {
516  int result = -1;
517  if (!stream || !m_device || !picture)
518  return result;
519 
520  AVCodecContext *avctx = gCodecMap->getCodecContext(stream);
521 
522  if (!avctx || !StartFetcherThread())
523  return result;
524 
525  if (pkt && pkt->size)
526  {
527  result = ProcessPacket(stream, pkt);
528  if (result < 0)
529  return result;
530  }
531 
532  m_decoded_frames_lock.lock();
533  int available = m_decoded_frames.size();
534  m_decoded_frames_lock.unlock();
535  if (!available)
536  return result;
537 
538  if (avctx->get_buffer2(avctx, picture, 0) < 0)
539  {
540  LOG(VB_GENERAL, LOG_ERR, LOC +
541  QString("%1 decoded frames available but no video buffers.")
542  .arg(available));
543  return -1;
544  }
545 
546  m_decoded_frames_lock.lock();
547  VideoFrame *frame = m_decoded_frames.takeLast();
548  m_decoded_frames_lock.unlock();
549 
550  *got_picture_ptr = 1;
551  picture->reordered_opaque = (int64_t)(frame->timecode /
552  av_q2d(stream->time_base) / 10000000);
553  LOG(VB_TIMESTAMP, LOG_DEBUG, LOC +
554  QString("decoder output timecode %1 ms (pts %2)")
555  .arg(frame->timecode / 10000).arg(picture->reordered_opaque));
556  copy((VideoFrame*)picture->opaque, frame);
557  if (frame->priv[0] && frame->qstride)
558  {
559  memcpy(picture->atsc_cc_buf, frame->priv[0], frame->qstride);
560  picture->atsc_cc_len = frame->qstride;
561  }
562  free_frame(frame);
563  return result;
564 }
565 
567 {
568  INIT_ST;
569  bool valid = false;
570  m_fetcher_paused = false;
571  while (!m_fetcher_stop)
572  {
573  usleep(1000);
574  if (m_fetcher_pause)
575  {
576  m_fetcher_paused = true;
577  continue;
578  }
579  m_fetcher_paused = false;
580 
581  BC_DTS_STATUS status;
582  st = DtsGetDriverStatus(m_device, &status);
583  CHECK_ST;
584 
585  if (!status.ReadyListCount)
586  continue;
587 
588  BC_DTS_PROC_OUT out;
589  memset(&out, 0, sizeof(BC_DTS_PROC_OUT));
590  st = DtsProcOutputNoCopy(m_device, valid ? 2000 : 20, &out);
591 
592  if (BC_STS_FMT_CHANGE == st)
593  {
594  LOG(VB_GENERAL, LOG_INFO, LOC + "Decoder reported format change.");
595  CheckProcOutput(&out);
596  valid = true;
597  continue;
598  }
599  CHECK_ST;
600 
601  if (!ok)
602  {
603  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to fetch decoded frame");
604  continue;
605  }
606 
607  if (ok && valid && (out.PoutFlags & BC_POUT_FLAGS_PIB_VALID))
608  FillFrame(&out);
609  st = DtsReleaseOutputBuffs(m_device, nullptr, false);
610  CHECK_ST;
611  }
612 }
613 
615 {
616  m_fetcher_pause = false;
617  if (m_fetcher_thread)
618  return true;
619 
620  m_fetcher_thread = new FetcherThread(this);
621  if (!m_fetcher_thread)
622  return false;
623 
625  return true;
626 }
627 
628 
629 void PrivateDecoderCrystalHD::FillFrame(BC_DTS_PROC_OUT *out)
630 {
631  bool second_field = false;
632  if (m_frame)
633  {
634  if (out->PicInfo.picture_number != m_frame->frameNumber)
635  {
636  LOG(VB_PLAYBACK, LOG_WARNING, LOC + "Missing second field");
637  AddFrameToQueue();
638  }
639  else
640  {
641  second_field = true;
642  }
643  }
644 
645  int in_width = out->PicInfo.width;
646  int in_height = out->PicInfo.height;
647  int out_width = (in_width + 15) & (~0xf);
648  int out_height = in_height;
649  uint8_t* src = out->Ybuff;
650 
651  if (!m_frame)
652  {
653  int size = buffersize(FMT_YV12, out_width, out_height);
654  unsigned char* buf = (unsigned char*)av_malloc(size);
655  m_frame = new VideoFrame();
656  init(m_frame, FMT_YV12, buf, out_width, out_height, size);
657  m_frame->timecode = (int64_t)out->PicInfo.timeStamp;
658  m_frame->frameNumber = out->PicInfo.picture_number;
659  }
660 
661  // line 21 data (608/708 captions)
662  // this appears to be unimplemented in the driver
663  if (out->UserDataSz)
664  {
665  int size = out->UserDataSz > 1024 ? 1024 : out->UserDataSz;
666  m_frame->priv[0] = (unsigned char*)av_malloc(size);
667  memcpy(m_frame->priv[0], out->UserData, size);
668  m_frame->qstride = size; // don't try this at home
669  }
670 
671  AVPixelFormat out_fmt = AV_PIX_FMT_YUV420P;
672  AVPixelFormat in_fmt = bcmpixfmt_to_pixfmt(m_pix_fmt);
673  AVFrame img_in;
674 
675  av_image_fill_arrays(img_in.data, img_in.linesize,
676  src, in_fmt, in_width, in_height, IMAGE_ALIGN);
677 
678  if (!(out->PicInfo.flags & VDEC_FLAG_INTERLACED_SRC))
679  {
680  m_copyCtx.Copy(m_frame, &img_in, in_fmt);
682  AddFrameToQueue();
683  }
684  else
685  {
686  AVFrame img_out;
687 
688  AVPictureFill(&img_out, m_frame);
689  img_out.linesize[0] *= 2;
690  img_out.linesize[1] *= 2;
691  img_out.linesize[2] *= 2;
692  m_frame->top_field_first = out->PicInfo.pulldown == vdecTopBottom;
693  int field = out->PoutFlags & BC_POUT_FLAGS_FLD_BOT;
694  if (field)
695  {
696  img_out.data[0] += out_width;
697  img_out.data[1] += out_width >> 1;
698  img_out.data[2] += out_width >> 1;
699  }
700  m_copyCtx.Copy(&img_out, out_fmt, &img_in, in_fmt, in_width, in_height / 2);
701  if (second_field)
702  AddFrameToQueue();
703  }
704 }
705 
707 {
708  m_decoded_frames_lock.lock();
709  m_decoded_frames.insert(0, m_frame);
710  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("Decoded frame queue size %1")
711  .arg(m_decoded_frames.size()));
712  m_decoded_frames_lock.unlock();
713  m_frame = nullptr;
714 }
715 
717 {
718  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut Ybuf : %1")
719  .arg((uintptr_t)out->Ybuff));
720  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut Ybuffsz : %1")
721  .arg(out->YbuffSz));
722  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut Ybuffdnsz : %1")
723  .arg(out->YBuffDoneSz));
724  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut Ubuf : %1")
725  .arg((uintptr_t)out->UVbuff));
726  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut Ubuffsz : %1")
727  .arg(out->UVbuffSz));
728  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut Ubuffdnsz : %1")
729  .arg(out->UVBuffDoneSz));
730  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut StrideSz : %1")
731  .arg(out->StrideSz));
732  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut Flags : %1")
733  .arg(poutflags_to_string(out->PoutFlags)));
734  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut DiscCnt : %1")
735  .arg(out->discCnt));
736  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut usrdatasz : %1")
737  .arg(out->UserDataSz));
738  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut DropFrames: %1")
739  .arg(out->DropFrames));
740  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut b422Mode : %1")
741  .arg(bcmpixfmt_to_string((BC_OUTPUT_FORMAT)out->b422Mode)));
742  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut bPIBenc : %1")
743  .arg(out->bPibEnc));
744  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut revertscra: %1")
745  .arg(out->bRevertScramble));
746  CheckPicInfo(out);
747 }
748 
749 void PrivateDecoderCrystalHD::CheckPicInfo(BC_DTS_PROC_OUT *out)
750 {
751  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo timestamp: %1")
752  .arg(out->PicInfo.timeStamp));
753  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo picnumber: %1")
754  .arg(out->PicInfo.picture_number));
755  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo width : %1")
756  .arg(out->PicInfo.width));
757  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo height : %1")
758  .arg(out->PicInfo.height));
759  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo chromafmt: %1")
760  .arg(out->PicInfo.chroma_format));
761  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo pulldown : %1")
762  .arg(pulldown_to_string(out->PicInfo.pulldown)));
763  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo flags : %1")
764  .arg(decoderflags_to_string(out->PicInfo.flags)));
765  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo framerate: %1")
766  .arg(out->PicInfo.frame_rate));
767  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo aspectrat: %1")
768  .arg(out->PicInfo.colour_primaries));
769  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo metapaylo: %1")
770  .arg(out->PicInfo.picture_meta_payload));
771  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo sess_num : %1")
772  .arg(out->PicInfo.sess_num));
773  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo ycom : %1")
774  .arg(out->PicInfo.ycom));
775  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo customasp: %1")
776  .arg(out->PicInfo.custom_aspect_ratio_width_height));
777  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo ndrop : %1")
778  .arg(out->PicInfo.n_drop));
779 }
780 
782 {
783  BC_DTS_STATUS status;
784  status.cpbEmptySize = 0x00000000; // set bit 31 for real HW free size
785  INIT_ST;
786  st = DtsGetDriverStatus(m_device, &status);
787  CHECK_ST;
788  if (!ok)
789  return;
790 
791  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ReadyListCount : %1")
792  .arg(status.ReadyListCount));
793  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("FreeListCount : %1")
794  .arg(status.FreeListCount));
795  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("PowerStateChange: %1")
796  .arg(status.PowerStateChange));
797  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("FrameDropped : %1")
798  .arg(status.FramesDropped));
799  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("FramesCaptured : %1")
800  .arg(status.FramesCaptured));
801  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("FramesRepeated : %1")
802  .arg(status.FramesRepeated));
803  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("InputCount : %1")
804  .arg(status.InputCount));
805  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("InputTotalSize : %1")
806  .arg(status.InputTotalSize));
807  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("InputBusyCount : %1")
808  .arg(status.InputBusyCount));
809  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("PIBMissCount : %1")
810  .arg(status.PIBMissCount));
811  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("cpbEmptySize : %1")
812  .arg(status.cpbEmptySize));
813  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("NextTimeStamp : %1")
814  .arg(status.NextTimeStamp));
815  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("PicNumFlags : %1")
816  .arg(status.picNumFlags));
817 }
818 
820 {
821  BC_DTS_STATUS status;
822  if (hwsel)
823  status.cpbEmptySize = 0xC0000000; // set bit 31 for real HW free size
824  else
825  status.cpbEmptySize = 0x40000000; // set bit 30 for TX only status
826  INIT_ST;
827  st = DtsGetDriverStatus(m_device, &status);
828  CHECK_ST;
829  if (!ok)
830  return -1;
831 
832  return status.cpbEmptySize;
833 }
834 
836 {
837  switch (device)
838  {
839  case BC_70012: return "BCM70012";
840  case BC_70015: return "BCM70015";
841  }
842  return "Unknown";
843 }
844 
845 QString bcmerr_to_string(BC_STATUS err)
846 {
847  switch (err)
848  {
849  case BC_STS_INV_ARG: return "Invalid argument";
850  case BC_STS_BUSY: return "Busy";
851  case BC_STS_NOT_IMPL: return "Not implemented";
852  case BC_STS_PGM_QUIT: return "PGM quit";
853  case BC_STS_NO_ACCESS: return "No access";
854  case BC_STS_INSUFF_RES: return "Insufficient resources";
855  case BC_STS_IO_ERROR: return "I/O error";
856  case BC_STS_NO_DATA: return "No data";
857  case BC_STS_VER_MISMATCH: return "Version mismatch";
858  case BC_STS_TIMEOUT: return "Timeout";
859  case BC_STS_FW_CMD_ERR: return "Command error";
860  case BC_STS_DEC_NOT_OPEN: return "Decoder not open";
861  case BC_STS_ERR_USAGE: return "Usage error";
862  case BC_STS_IO_USER_ABORT: return "I/O user abort";
863  case BC_STS_IO_XFR_ERROR: return "I/O transfer error";
864  case BC_STS_DEC_NOT_STARTED: return "Decoder not started";
865  case BC_STS_FWHEX_NOT_FOUND: return "FirmwareHex not found";
866  case BC_STS_FMT_CHANGE: return "Format change";
867  case BC_STS_HIF_ACCESS: return "HIF access";
868  case BC_STS_CMD_CANCELLED: return "Command cancelled";
869  case BC_STS_FW_AUTH_FAILED: return "Firmware authorisation failed";
870  case BC_STS_BOOTLOADER_FAILED: return "Bootloader failed";
871  case BC_STS_CERT_VERIFY_ERROR: return "Certificate verify error";
872  case BC_STS_DEC_EXIST_OPEN: return "Decoder exist open (?)";
873  case BC_STS_PENDING: return "Pending";
874  case BC_STS_ERROR: return "Unknown";
875  default: break;
876  }
877  return "Unknown error";
878 }
879 
880 QString bcmpixfmt_to_string(BC_OUTPUT_FORMAT fmt)
881 {
882  switch (fmt)
883  {
884  case OUTPUT_MODE420: return "YUV420P";
885  case OUTPUT_MODE422_YUY2: return "YUYV422";
886  case OUTPUT_MODE422_UYVY: return "UYVY422";
887  default: break;
888  }
889  return "Unknown";
890 }
891 
892 QString pulldown_to_string(int pulldown)
893 {
894  switch (pulldown)
895  {
896  case vdecNoPulldownInfo: return "Unknown";
897  case vdecTop: return "Top";
898  case vdecBottom: return "Bottom";
899  case vdecTopBottom: return "TopBottom";
900  case vdecBottomTop: return "BottomTop";
901  case vdecTopBottomTop: return "TopBottomTop";
902  case vdecBottomTopBottom: return "BottomTopBottom";
903  case vdecFrame_X2: return "X2";
904  case vdecFrame_X3: return "X3";
905  case vdecFrame_X1: return "X1";
906  case vdecFrame_X4: return "X4";
907  }
908  return "Unknown";
909 }
910 
911 QString decoderflags_to_string(int flags)
912 {
913  QString res;
914  if (flags & VDEC_FLAG_EOS) res += "EndOfStream ";
915  if (flags & VDEC_FLAG_FIELDPAIR) res += "FieldPair ";
916  if (flags & VDEC_FLAG_TOPFIELD) res += "TopField ";
917  if (flags & VDEC_FLAG_BOTTOMFIELD) res += "BottomField ";
918  if (flags & VDEC_FLAG_INTERLACED_SRC) res += "InterlacedSource ";
919  if (flags & VDEC_FLAG_UNKNOWN_SRC) res += "UnknownSource ";
920  if (flags & VDEC_FLAG_BOTTOM_FIRST) res += "BottomFirst ";
921  if (flags & VDEC_FLAG_LAST_PICTURE) res += "LastPicture ";
922  if (flags & VDEC_FLAG_PICTURE_META_DATA_PRESENT) res += "MetaDataPresent ";
923  return res;
924 }
925 
926 QString poutflags_to_string(int flags)
927 {
928  QString res;
929  if (flags & BC_POUT_FLAGS_YV12) res += "YV12 ";
930  if (flags & BC_POUT_FLAGS_STRIDE) res += "STRIDE ";
931  if (flags & BC_POUT_FLAGS_SIZE) res += "SIZE ";
932  if (flags & BC_POUT_FLAGS_INTERLACED) res += "INTERLACED ";
933  if (flags & BC_POUT_FLAGS_INTERLEAVED) res += "INTERLEAVED ";
934  if (flags & BC_POUT_FLAGS_STRIDE_UV) res += "UVSTRIDE ";
935  if (flags & BC_POUT_FLAGS_MODE) res += "APPMODE ";
936  if (flags & BC_POUT_FLAGS_FMT_CHANGE) res += "FORMATCHANGED ";
937  if (flags & BC_POUT_FLAGS_PIB_VALID) res += "PIBVALID ";
938  if (flags & BC_POUT_FLAGS_ENCRYPTED) res += "ENCRYPTED ";
939  if (flags & BC_POUT_FLAGS_FLD_BOT) res += "FIELDBOTTOM ";
940  return res;
941 }
942 
943 AVPixelFormat bcmpixfmt_to_pixfmt(BC_OUTPUT_FORMAT fmt)
944 {
945  switch (fmt)
946  {
947  case OUTPUT_MODE420: return AV_PIX_FMT_YUV420P;
948  case OUTPUT_MODE422_YUY2: return AV_PIX_FMT_YUYV422;
949  case OUTPUT_MODE422_UYVY: return AV_PIX_FMT_UYVY422;
950  default: break;
951  }
952  return AV_PIX_FMT_YUV420P;
953 }
struct PacketBuffer_ PacketBuffer
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:216
void start(QThread::Priority=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:295
#define LOC
#define INIT_ST
int qstride
Definition: mythframe.h:55
PlayerFlags
Definition: mythplayer.h:88
void run(void) override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
void CheckProcOutput(BC_DTS_PROC_OUT *out)
int Copy(VideoFrame *dst, const VideoFrame *src)
Definition: mythavutil.cpp:196
int ProcessPacket(AVStream *stream, AVPacket *pkt)
MythAVCopy m_copyCtx
struct AVFrame AVFrame
QString poutflags_to_string(int flags)
bool wait(unsigned long time=ULONG_MAX)
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:312
void free_buffer(PacketBuffer *buffer)
QList< PacketBuffer * > m_packet_buffers
QList< VideoFrame * > m_decoded_frames
static char * fourcc_str(int i)
Definition: fourcc.h:25
long long timecode
Definition: mythframe.h:49
void FillFrame(BC_DTS_PROC_OUT *out)
unsigned char * priv[4]
random empty storage
Definition: mythframe.h:52
long long copy(QFile &dst, QFile &src, uint block_size)
Copies src file to dst file.
PrivateDecoderCrystalHD * m_dec
bool CreateFilter(AVCodecContext *avctx)
static void init(VideoFrame *vf, VideoFrameType _codec, unsigned char *_buf, int _width, int _height, int _size, const int *p=nullptr, const int *o=nullptr, float _aspect=-1.0f, double _rate=-1.0f, int _aligned=64)
Definition: mythframe.h:109
#define IMAGE_ALIGN
Definition: mythconfig.h:19
QString decoderflags_to_string(int flags)
int AVPictureFill(AVFrame *pic, const VideoFrame *frame, AVPixelFormat fmt)
AVPictureFill Initialise AVFrame pic with content from VideoFrame frame.
Definition: mythavutil.cpp:65
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:85
MythCodecMap * gCodecMap
This global variable contains the MythCodecMap instance for the app.
Definition: mythavutil.cpp:377
AVBitStreamFilterContext * m_filter
AVPixelFormat bcmpixfmt_to_pixfmt(BC_OUTPUT_FORMAT fmt)
QString device_to_string(BC_DEVICE_TYPE device)
bool isRunning(void) const
Definition: mthread.cpp:275
void CheckPicInfo(BC_DTS_PROC_OUT *out)
int GetFrame(AVStream *stream, AVFrame *picture, int *got_picture_ptr, AVPacket *pkt) override
long long frameNumber
Definition: mythframe.h:48
QString bcmpixfmt_to_string(BC_OUTPUT_FORMAT fmt)
#define CHECK_ST
int top_field_first
1 if top field is first.
Definition: mythframe.h:58
AVCodecContext * getCodecContext(const AVStream *, const AVCodec *pCodec=nullptr, bool nullCodec=false)
Definition: mythavutil.cpp:388
void * av_malloc(unsigned int size)
void free_frame(VideoFrame *frame)
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
static void GetDecoders(render_opts &opts)
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:203
struct VideoFrame_ VideoFrame
static uint buffersize(VideoFrameType type, int width, int height, int _aligned=64)
Definition: mythframe.h:291
int interlaced_frame
1 if interlaced.
Definition: mythframe.h:57
bool Init(const QString &decoder, PlayerFlags flags, AVCodecContext *avctx) override
QString bcmerr_to_string(BC_STATUS err)
unsigned char * buf
Definition: mythframe.h:39
QString pulldown_to_string(int pulldown)