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 
79  if (!m_device)
80  return;
81 
82  INIT_ST;
83  if (m_device_type != BC_70015)
84  {
85  st = DtsFlushRxCapture(m_device, static_cast<int>(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  CHECK_ST;
304  if (!ok)
305  {
306  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to set decoder output format");
307  return false;
308  }
309 
310  st = DtsStartDecoder(m_device);
311  CHECK_ST;
312  if (!ok)
313  {
314  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to start decoder");
315  return false;
316  }
317 
318  st = DtsStartCapture(m_device);
319  CHECK_ST;
320  if (!ok)
321  {
322  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to start capture");
323  return false;
324  }
325 
326  Reset();
327 
328  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Created decoder %1 %2x%3")
329  .arg(ff_codec_id_string(avctx->codec_id))
330  .arg(avctx->coded_width).arg(avctx->coded_height));
331  return true;
332 }
333 
334 bool PrivateDecoderCrystalHD::CreateFilter(AVCodecContext *avctx)
335 {
336  int nalsize = (avctx->extradata[4] & 0x3) + 1;
337  if (!nalsize || nalsize == 3 || nalsize > 4)
338  {
339  LOG(VB_PLAYBACK, LOG_ERR, LOC + QString("Invalid nal size (%1)")
340  .arg(nalsize));
341  return false;
342  }
343 
344  static const uint8_t testnal[] = { 0,0,0,2,0,0 };
345  AVBitStreamFilterContext *bsfc =
346  av_bitstream_filter_init("h264_mp4toannexb");
347  if (!bsfc)
348  return false;
349  m_filter = bsfc;
350 
351  // and test extradata
352  const uint8_t *test = testnal;
353  int testsize = 6;
354  int outbuf_size = 0;
355  uint8_t *outbuf = nullptr;
356  int res = av_bitstream_filter_filter(m_filter, avctx, nullptr, &outbuf,
357  &outbuf_size, test, testsize, 0);
358  av_freep(&outbuf);
359  return res > 0;
360 }
361 
362 void inline free_frame(VideoFrame* frame)
363 {
364  if (frame)
365  {
366  if (frame->buf)
367  av_freep(&frame->buf);
368  if (frame->priv[0])
369  av_freep(&frame->priv[0]);
370  delete frame;
371  }
372 }
373 
374 void inline free_buffer(PacketBuffer* buffer)
375 {
376  if (buffer)
377  {
378  if (buffer->buf)
379  av_freep(&buffer->buf);
380  delete buffer;
381  }
382 }
383 
385 {
386  if (m_fetcher_thread)
387  {
388  m_fetcher_pause = true;
389  int tries = 0;
390  while (!m_fetcher_paused && (tries++ < 50))
391  usleep(10000);
392  if (!m_fetcher_paused)
393  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to pause fetcher thread");
394  }
395 
396  QMutexLocker lock(&m_decoded_frames_lock);
398  m_frame = nullptr;
399 
400  for (int i = 0; i < m_decoded_frames.size(); i++)
402  m_decoded_frames.clear();
403 
404  for (int i = 0; i < m_packet_buffers.size(); i++)
406  m_packet_buffers.clear();
407 
408  if (!m_device)
409  return true;
410 
411  if (m_device_type != BC_70015)
412  {
413  INIT_ST;
414  st = DtsFlushInput(m_device, 2);
415  CHECK_ST;
416  }
417  return true;;
418 }
419 
421 {
422  m_decoded_frames_lock.lock();
423  bool result = !m_decoded_frames.empty();
424  m_decoded_frames_lock.unlock();
425  return result;
426 }
427 
428 int PrivateDecoderCrystalHD::ProcessPacket(AVStream *stream, AVPacket *pkt)
429 {
430  int result = -1;
431  AVCodecContext *avctx = gCodecMap->getCodecContext(stream);
432  if (!avctx)
433  return result;
434 
435  PacketBuffer *buffer1 = new PacketBuffer();
436  if (!buffer1)
437  return result;
438 
439  buffer1->buf = (unsigned char*)av_malloc(pkt->size);
440  buffer1->size = pkt->size;
441  buffer1->pts = pkt->pts;
442  memcpy(buffer1->buf, pkt->data, pkt->size);
443 
444  m_packet_buffers.insert(0, buffer1);
445  LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
446  QString("%1 packet buffers queued up").arg(m_packet_buffers.size()));
447 
448  while (!m_packet_buffers.empty())
449  {
450  PacketBuffer *buffer2 = m_packet_buffers.last();
451  if (GetTxFreeSize(false) < buffer2->size)
452  {
453  usleep(10000);
454  return 0;
455  }
456 
457  buffer2 = m_packet_buffers.takeLast();
458  uint8_t* buf = buffer2->buf;
459  int size = buffer2->size;
460  bool free_buf = false;
461  int outbuf_size = 0;
462  uint8_t *outbuf = nullptr;
463 
464  if (m_filter)
465  {
466  int res = av_bitstream_filter_filter(m_filter, avctx, nullptr, &outbuf,
467  &outbuf_size, buf, size, 0);
468  if (res <= 0)
469  {
470  static int count = 0;
471  if (count == 0)
472  LOG(VB_GENERAL, LOG_ERR, LOC +
473  QString("Failed to convert packet (%1)").arg(res));
474  count++;
475  if (count > 200)
476  count = 0;
477  }
478 
479  if (outbuf && (outbuf_size > 0))
480  {
481  free_buf = outbuf != buf;
482  size = outbuf_size;
483  buf = outbuf;
484  }
485  }
486 
487  usleep(1000);
488  uint64_t chd_timestamp = 0; // 100 nsec units
489  if (buffer2->pts != AV_NOPTS_VALUE)
490  chd_timestamp = (uint64_t)(av_q2d(stream->time_base) *
491  buffer2->pts * 10000000);
492  LOG(VB_TIMESTAMP, LOG_DEBUG, LOC +
493  QString("decoder input timecode %1 ms (pts %2)")
494  .arg(chd_timestamp / 10000).arg(buffer2->pts));
495 
496  // TODO check for busy state
497  INIT_ST;
498  st = DtsProcInput(m_device, buf, size, chd_timestamp, static_cast<int>(false));
499  CHECK_ST;
500 
501  if (free_buf)
502  av_freep(&buf);
503 
504  if (!ok)
505  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to send packet to decoder.");
506 
507  result = buffer2->size;
508 
509  free_buffer(buffer2);
510  }
511  return result;
512 }
513 
515  AVFrame *picture,
516  int *got_picture_ptr,
517  AVPacket *pkt)
518 {
519  int result = -1;
520  if (!stream || !m_device || !picture)
521  return result;
522 
523  AVCodecContext *avctx = gCodecMap->getCodecContext(stream);
524 
525  if (!avctx || !StartFetcherThread())
526  return result;
527 
528  if (pkt && pkt->size)
529  {
530  result = ProcessPacket(stream, pkt);
531  if (result < 0)
532  return result;
533  }
534 
535  m_decoded_frames_lock.lock();
536  int available = m_decoded_frames.size();
537  m_decoded_frames_lock.unlock();
538  if (!available)
539  return result;
540 
541  if (avctx->get_buffer2(avctx, picture, 0) < 0)
542  {
543  LOG(VB_GENERAL, LOG_ERR, LOC +
544  QString("%1 decoded frames available but no video buffers.")
545  .arg(available));
546  return -1;
547  }
548 
549  m_decoded_frames_lock.lock();
550  VideoFrame *frame = m_decoded_frames.takeLast();
551  m_decoded_frames_lock.unlock();
552 
553  *got_picture_ptr = 1;
554  picture->reordered_opaque = (int64_t)(frame->timecode /
555  av_q2d(stream->time_base) / 10000000);
556  LOG(VB_TIMESTAMP, LOG_DEBUG, LOC +
557  QString("decoder output timecode %1 ms (pts %2)")
558  .arg(frame->timecode / 10000).arg(picture->reordered_opaque));
559  copy((VideoFrame*)picture->opaque, frame);
560  if (frame->priv[0] && frame->qstride)
561  {
562  memcpy(picture->atsc_cc_buf, frame->priv[0], frame->qstride);
563  picture->atsc_cc_len = frame->qstride;
564  }
565  free_frame(frame);
566  return result;
567 }
568 
570 {
571  INIT_ST;
572  bool valid = false;
573  m_fetcher_paused = false;
574  while (!m_fetcher_stop)
575  {
576  usleep(1000);
577  if (m_fetcher_pause)
578  {
579  m_fetcher_paused = true;
580  continue;
581  }
582  m_fetcher_paused = false;
583 
584  BC_DTS_STATUS status;
585  st = DtsGetDriverStatus(m_device, &status);
586  CHECK_ST;
587 
588  if (!status.ReadyListCount)
589  continue;
590 
591  BC_DTS_PROC_OUT out;
592  memset(&out, 0, sizeof(BC_DTS_PROC_OUT));
593  st = DtsProcOutputNoCopy(m_device, valid ? 2000 : 20, &out);
594 
595  if (BC_STS_FMT_CHANGE == st)
596  {
597  LOG(VB_GENERAL, LOG_INFO, LOC + "Decoder reported format change.");
598  CheckProcOutput(&out);
599  valid = true;
600  continue;
601  }
602  CHECK_ST;
603 
604  if (!ok)
605  {
606  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to fetch decoded frame");
607  continue;
608  }
609 
610  if (ok && valid && (out.PoutFlags & BC_POUT_FLAGS_PIB_VALID))
611  FillFrame(&out);
612  st = DtsReleaseOutputBuffs(m_device, nullptr, static_cast<int>(false));
613  CHECK_ST;
614  }
615 }
616 
618 {
619  m_fetcher_pause = false;
620  if (m_fetcher_thread)
621  return true;
622 
623  m_fetcher_thread = new FetcherThread(this);
624  if (!m_fetcher_thread)
625  return false;
626 
628  return true;
629 }
630 
631 
632 void PrivateDecoderCrystalHD::FillFrame(BC_DTS_PROC_OUT *out)
633 {
634  bool second_field = false;
635  if (m_frame)
636  {
637  if (out->PicInfo.picture_number != m_frame->frameNumber)
638  {
639  LOG(VB_PLAYBACK, LOG_WARNING, LOC + "Missing second field");
640  AddFrameToQueue();
641  }
642  else
643  {
644  second_field = true;
645  }
646  }
647 
648  int in_width = out->PicInfo.width;
649  int in_height = out->PicInfo.height;
650  int out_width = (in_width + 15) & (~0xf);
651  int out_height = in_height;
652  uint8_t* src = out->Ybuff;
653 
654  if (!m_frame)
655  {
656  int size = buffersize(FMT_YV12, out_width, out_height);
657  unsigned char* buf = (unsigned char*)av_malloc(size);
658  m_frame = new VideoFrame();
659  init(m_frame, FMT_YV12, buf, out_width, out_height, size);
660  m_frame->timecode = (int64_t)out->PicInfo.timeStamp;
661  m_frame->frameNumber = out->PicInfo.picture_number;
662  }
663 
664  // line 21 data (608/708 captions)
665  // this appears to be unimplemented in the driver
666  if (out->UserDataSz)
667  {
668  int size = out->UserDataSz > 1024 ? 1024 : out->UserDataSz;
669  m_frame->priv[0] = (unsigned char*)av_malloc(size);
670  memcpy(m_frame->priv[0], out->UserData, size);
671  m_frame->qstride = size; // don't try this at home
672  }
673 
674  AVPixelFormat out_fmt = AV_PIX_FMT_YUV420P;
675  AVPixelFormat in_fmt = bcmpixfmt_to_pixfmt(m_pix_fmt);
676  AVFrame img_in;
677 
678  av_image_fill_arrays(img_in.data, img_in.linesize,
679  src, in_fmt, in_width, in_height, IMAGE_ALIGN);
680 
681  if (!(out->PicInfo.flags & VDEC_FLAG_INTERLACED_SRC))
682  {
683  m_copyCtx.Copy(m_frame, &img_in, in_fmt);
685  AddFrameToQueue();
686  }
687  else
688  {
689  AVFrame img_out;
690 
691  AVPictureFill(&img_out, m_frame);
692  img_out.linesize[0] *= 2;
693  img_out.linesize[1] *= 2;
694  img_out.linesize[2] *= 2;
695  m_frame->top_field_first = out->PicInfo.pulldown == vdecTopBottom;
696  int field = out->PoutFlags & BC_POUT_FLAGS_FLD_BOT;
697  if (field)
698  {
699  img_out.data[0] += out_width;
700  img_out.data[1] += out_width >> 1;
701  img_out.data[2] += out_width >> 1;
702  }
703  m_copyCtx.Copy(&img_out, out_fmt, &img_in, in_fmt, in_width, in_height / 2);
704  if (second_field)
705  AddFrameToQueue();
706  }
707 }
708 
710 {
711  m_decoded_frames_lock.lock();
712  m_decoded_frames.insert(0, m_frame);
713  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("Decoded frame queue size %1")
714  .arg(m_decoded_frames.size()));
715  m_decoded_frames_lock.unlock();
716  m_frame = nullptr;
717 }
718 
720 {
721  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut Ybuf : %1")
722  .arg((uintptr_t)out->Ybuff));
723  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut Ybuffsz : %1")
724  .arg(out->YbuffSz));
725  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut Ybuffdnsz : %1")
726  .arg(out->YBuffDoneSz));
727  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut Ubuf : %1")
728  .arg((uintptr_t)out->UVbuff));
729  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut Ubuffsz : %1")
730  .arg(out->UVbuffSz));
731  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut Ubuffdnsz : %1")
732  .arg(out->UVBuffDoneSz));
733  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut StrideSz : %1")
734  .arg(out->StrideSz));
735  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut Flags : %1")
736  .arg(poutflags_to_string(out->PoutFlags)));
737  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut DiscCnt : %1")
738  .arg(out->discCnt));
739  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut usrdatasz : %1")
740  .arg(out->UserDataSz));
741  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut DropFrames: %1")
742  .arg(out->DropFrames));
743  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut b422Mode : %1")
744  .arg(bcmpixfmt_to_string((BC_OUTPUT_FORMAT)out->b422Mode)));
745  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut bPIBenc : %1")
746  .arg(out->bPibEnc));
747  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut revertscra: %1")
748  .arg(out->bRevertScramble));
749  CheckPicInfo(out);
750 }
751 
752 void PrivateDecoderCrystalHD::CheckPicInfo(BC_DTS_PROC_OUT *out)
753 {
754  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo timestamp: %1")
755  .arg(out->PicInfo.timeStamp));
756  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo picnumber: %1")
757  .arg(out->PicInfo.picture_number));
758  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo width : %1")
759  .arg(out->PicInfo.width));
760  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo height : %1")
761  .arg(out->PicInfo.height));
762  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo chromafmt: %1")
763  .arg(out->PicInfo.chroma_format));
764  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo pulldown : %1")
765  .arg(pulldown_to_string(out->PicInfo.pulldown)));
766  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo flags : %1")
767  .arg(decoderflags_to_string(out->PicInfo.flags)));
768  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo framerate: %1")
769  .arg(out->PicInfo.frame_rate));
770  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo aspectrat: %1")
771  .arg(out->PicInfo.colour_primaries));
772  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo metapaylo: %1")
773  .arg(out->PicInfo.picture_meta_payload));
774  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo sess_num : %1")
775  .arg(out->PicInfo.sess_num));
776  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo ycom : %1")
777  .arg(out->PicInfo.ycom));
778  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo customasp: %1")
779  .arg(out->PicInfo.custom_aspect_ratio_width_height));
780  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo ndrop : %1")
781  .arg(out->PicInfo.n_drop));
782 }
783 
785 {
786  BC_DTS_STATUS status;
787  status.cpbEmptySize = 0x00000000; // set bit 31 for real HW free size
788  INIT_ST;
789  st = DtsGetDriverStatus(m_device, &status);
790  CHECK_ST;
791  if (!ok)
792  return;
793 
794  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ReadyListCount : %1")
795  .arg(status.ReadyListCount));
796  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("FreeListCount : %1")
797  .arg(status.FreeListCount));
798  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("PowerStateChange: %1")
799  .arg(status.PowerStateChange));
800  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("FrameDropped : %1")
801  .arg(status.FramesDropped));
802  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("FramesCaptured : %1")
803  .arg(status.FramesCaptured));
804  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("FramesRepeated : %1")
805  .arg(status.FramesRepeated));
806  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("InputCount : %1")
807  .arg(status.InputCount));
808  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("InputTotalSize : %1")
809  .arg(status.InputTotalSize));
810  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("InputBusyCount : %1")
811  .arg(status.InputBusyCount));
812  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("PIBMissCount : %1")
813  .arg(status.PIBMissCount));
814  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("cpbEmptySize : %1")
815  .arg(status.cpbEmptySize));
816  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("NextTimeStamp : %1")
817  .arg(status.NextTimeStamp));
818  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("PicNumFlags : %1")
819  .arg(status.picNumFlags));
820 }
821 
823 {
824  BC_DTS_STATUS status;
825  if (hwsel)
826  status.cpbEmptySize = 0xC0000000; // set bit 31 for real HW free size
827  else
828  status.cpbEmptySize = 0x40000000; // set bit 30 for TX only status
829  INIT_ST;
830  st = DtsGetDriverStatus(m_device, &status);
831  CHECK_ST;
832  if (!ok)
833  return -1;
834 
835  return status.cpbEmptySize;
836 }
837 
839 {
840  switch (device)
841  {
842  case BC_70012: return "BCM70012";
843  case BC_70015: return "BCM70015";
844  }
845  return "Unknown";
846 }
847 
848 QString bcmerr_to_string(BC_STATUS err)
849 {
850  switch (err)
851  {
852  case BC_STS_INV_ARG: return "Invalid argument";
853  case BC_STS_BUSY: return "Busy";
854  case BC_STS_NOT_IMPL: return "Not implemented";
855  case BC_STS_PGM_QUIT: return "PGM quit";
856  case BC_STS_NO_ACCESS: return "No access";
857  case BC_STS_INSUFF_RES: return "Insufficient resources";
858  case BC_STS_IO_ERROR: return "I/O error";
859  case BC_STS_NO_DATA: return "No data";
860  case BC_STS_VER_MISMATCH: return "Version mismatch";
861  case BC_STS_TIMEOUT: return "Timeout";
862  case BC_STS_FW_CMD_ERR: return "Command error";
863  case BC_STS_DEC_NOT_OPEN: return "Decoder not open";
864  case BC_STS_ERR_USAGE: return "Usage error";
865  case BC_STS_IO_USER_ABORT: return "I/O user abort";
866  case BC_STS_IO_XFR_ERROR: return "I/O transfer error";
867  case BC_STS_DEC_NOT_STARTED: return "Decoder not started";
868  case BC_STS_FWHEX_NOT_FOUND: return "FirmwareHex not found";
869  case BC_STS_FMT_CHANGE: return "Format change";
870  case BC_STS_HIF_ACCESS: return "HIF access";
871  case BC_STS_CMD_CANCELLED: return "Command cancelled";
872  case BC_STS_FW_AUTH_FAILED: return "Firmware authorisation failed";
873  case BC_STS_BOOTLOADER_FAILED: return "Bootloader failed";
874  case BC_STS_CERT_VERIFY_ERROR: return "Certificate verify error";
875  case BC_STS_DEC_EXIST_OPEN: return "Decoder exist open (?)";
876  case BC_STS_PENDING: return "Pending";
877  case BC_STS_ERROR: return "Unknown";
878  default: break;
879  }
880  return "Unknown error";
881 }
882 
883 QString bcmpixfmt_to_string(BC_OUTPUT_FORMAT fmt)
884 {
885  switch (fmt)
886  {
887  case OUTPUT_MODE420: return "YUV420P";
888  case OUTPUT_MODE422_YUY2: return "YUYV422";
889  case OUTPUT_MODE422_UYVY: return "UYVY422";
890  default: break;
891  }
892  return "Unknown";
893 }
894 
895 QString pulldown_to_string(int pulldown)
896 {
897  switch (pulldown)
898  {
899  case vdecNoPulldownInfo: return "Unknown";
900  case vdecTop: return "Top";
901  case vdecBottom: return "Bottom";
902  case vdecTopBottom: return "TopBottom";
903  case vdecBottomTop: return "BottomTop";
904  case vdecTopBottomTop: return "TopBottomTop";
905  case vdecBottomTopBottom: return "BottomTopBottom";
906  case vdecFrame_X2: return "X2";
907  case vdecFrame_X3: return "X3";
908  case vdecFrame_X1: return "X1";
909  case vdecFrame_X4: return "X4";
910  }
911  return "Unknown";
912 }
913 
914 QString decoderflags_to_string(int flags)
915 {
916  QString res;
917  if (flags & VDEC_FLAG_EOS) res += "EndOfStream ";
918  if (flags & VDEC_FLAG_FIELDPAIR) res += "FieldPair ";
919  if (flags & VDEC_FLAG_TOPFIELD) res += "TopField ";
920  if (flags & VDEC_FLAG_BOTTOMFIELD) res += "BottomField ";
921  if (flags & VDEC_FLAG_INTERLACED_SRC) res += "InterlacedSource ";
922  if (flags & VDEC_FLAG_UNKNOWN_SRC) res += "UnknownSource ";
923  if (flags & VDEC_FLAG_BOTTOM_FIRST) res += "BottomFirst ";
924  if (flags & VDEC_FLAG_LAST_PICTURE) res += "LastPicture ";
925  if (flags & VDEC_FLAG_PICTURE_META_DATA_PRESENT) res += "MetaDataPresent ";
926  return res;
927 }
928 
929 QString poutflags_to_string(int flags)
930 {
931  QString res;
932  if (flags & BC_POUT_FLAGS_YV12) res += "YV12 ";
933  if (flags & BC_POUT_FLAGS_STRIDE) res += "STRIDE ";
934  if (flags & BC_POUT_FLAGS_SIZE) res += "SIZE ";
935  if (flags & BC_POUT_FLAGS_INTERLACED) res += "INTERLACED ";
936  if (flags & BC_POUT_FLAGS_INTERLEAVED) res += "INTERLEAVED ";
937  if (flags & BC_POUT_FLAGS_STRIDE_UV) res += "UVSTRIDE ";
938  if (flags & BC_POUT_FLAGS_MODE) res += "APPMODE ";
939  if (flags & BC_POUT_FLAGS_FMT_CHANGE) res += "FORMATCHANGED ";
940  if (flags & BC_POUT_FLAGS_PIB_VALID) res += "PIBVALID ";
941  if (flags & BC_POUT_FLAGS_ENCRYPTED) res += "ENCRYPTED ";
942  if (flags & BC_POUT_FLAGS_FLD_BOT) res += "FIELDBOTTOM ";
943  return res;
944 }
945 
946 AVPixelFormat bcmpixfmt_to_pixfmt(BC_OUTPUT_FORMAT fmt)
947 {
948  switch (fmt)
949  {
950  case OUTPUT_MODE420: return AV_PIX_FMT_YUV420P;
951  case OUTPUT_MODE422_YUY2: return AV_PIX_FMT_YUYV422;
952  case OUTPUT_MODE422_UYVY: return AV_PIX_FMT_UYVY422;
953  default: break;
954  }
955  return AV_PIX_FMT_YUV420P;
956 }
struct PacketBuffer_ PacketBuffer
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:215
void start(QThread::Priority=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:294
#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:200
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:311
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)
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:381
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:274
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:392
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:202
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:115
struct VideoFrame_ VideoFrame
static uint buffersize(VideoFrameType type, int width, int height, int _aligned=64)
Definition: mythframe.h:297
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)