00001 #include "privatedecoder_crystalhd.h"
00002 #include "myth_imgconvert.h"
00003 #include "mythlogging.h"
00004
00005 #define LOC QString("CrystalHD: ")
00006 #define ERR QString("CrystalHD Err: ")
00007 #define WARN QString("CrystalHD Warn: ")
00008
00009 void FetcherThread::run(void)
00010 {
00011 RunProlog();
00012 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Starting Fetcher thread."));
00013 if (m_dec)
00014 m_dec->FetchFrames();
00015 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Stopping Fetcher thread."));
00016 RunEpilog();
00017 }
00018
00019 PixelFormat bcmpixfmt_to_pixfmt(BC_OUTPUT_FORMAT fmt);
00020 QString device_to_string(BC_DEVICE_TYPE device);
00021 QString bcmerr_to_string(BC_STATUS err);
00022 QString bcmpixfmt_to_string(BC_OUTPUT_FORMAT fmt);
00023 QString pulldown_to_string(int pulldown);
00024 QString decoderflags_to_string(int flags);
00025 QString poutflags_to_string(int flags);
00026
00027 #define INIT_ST BC_STATUS st; bool ok = true
00028 #define CHECK_ST \
00029 ok &= (st == BC_STS_SUCCESS); \
00030 if (!ok) \
00031 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Error at %1:%2 (#%3, %4)") \
00032 .arg(__FILE__).arg( __LINE__).arg(st) \
00033 .arg(bcmerr_to_string(st)))
00034
00035 void PrivateDecoderCrystalHD::GetDecoders(render_opts &opts)
00036 {
00037 opts.decoders->append("crystalhd");
00038 (*opts.equiv_decoders)["crystalhd"].append("nuppel");
00039 (*opts.equiv_decoders)["crystalhd"].append("ffmpeg");
00040 (*opts.equiv_decoders)["crystalhd"].append("dummy");
00041 }
00042
00043 PrivateDecoderCrystalHD::PrivateDecoderCrystalHD()
00044 : m_device(NULL), m_device_type(BC_70012),
00045 m_pix_fmt(OUTPUT_MODE_INVALID), m_decoded_frames_lock(QMutex::Recursive),
00046 m_fetcher_thread(NULL), m_fetcher_pause(false), m_fetcher_paused(false),
00047 m_fetcher_stop(false), m_frame(NULL), m_filter(NULL)
00048 {
00049 }
00050
00051 PrivateDecoderCrystalHD::~PrivateDecoderCrystalHD()
00052 {
00053 if (m_fetcher_thread)
00054 {
00055 m_fetcher_pause = true;
00056 m_fetcher_stop = true;
00057 int tries = 0;
00058 while (!m_fetcher_thread->wait(100) && (tries++ < 50))
00059 LOG(VB_PLAYBACK, LOG_WARNING, LOC +
00060 "Waited 100ms for Fetcher to stop");
00061
00062 if (m_fetcher_thread->isRunning())
00063 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to stop Fetcher.");
00064 else
00065 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Stopped frame Fetcher.");
00066 delete m_fetcher_thread;
00067 }
00068
00069 if (m_filter)
00070 av_bitstream_filter_close(m_filter);
00071
00072 Reset();
00073 if (!m_device)
00074 return;
00075
00076 INIT_ST;
00077 if (m_device_type != BC_70015)
00078 {
00079 st = DtsFlushRxCapture(m_device, false);
00080 CHECK_ST;
00081 }
00082 st = DtsStopDecoder(m_device);
00083 CHECK_ST;
00084 st = DtsCloseDecoder(m_device);
00085 CHECK_ST;
00086 DtsDeviceClose(m_device);
00087 }
00088
00089 bool PrivateDecoderCrystalHD::Init(const QString &decoder,
00090 PlayerFlags flags,
00091 AVCodecContext *avctx)
00092 {
00093 if ((decoder != "crystalhd") || !(flags & kDecodeAllowEXT) ||
00094 !avctx || getenv("NO_CRYSTALHD"))
00095 return false;
00096
00097 static bool debugged = false;
00098
00099 uint32_t well_documented = DTS_PLAYBACK_MODE | DTS_LOAD_FILE_PLAY_FW |
00100 DTS_SKIP_TX_CHK_CPB |
00101 DTS_PLAYBACK_DROP_RPT_MODE |
00102 DTS_DFLT_RESOLUTION(vdecRESOLUTION_CUSTOM);
00103 INIT_ST;
00104 st = DtsDeviceOpen(&m_device, well_documented);
00105 CHECK_ST;
00106 if (!ok)
00107 {
00108 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to open CrystalHD device");
00109 return false;
00110 }
00111
00112 _BC_INFO_CRYSTAL_ info;
00113 st = DtsCrystalHDVersion(m_device, &info);
00114 CHECK_ST;
00115 if (!ok)
00116 {
00117 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to get device info.");
00118 return false;
00119 }
00120
00121 m_device_type = (BC_DEVICE_TYPE)info.device;
00122
00123 if (!debugged)
00124 {
00125 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Device: %1")
00126 .arg(device_to_string(m_device_type)));
00127 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Library : %1.%2.%3")
00128 .arg(info.dilVersion.dilMajor)
00129 .arg(info.dilVersion.dilMinor)
00130 .arg(info.dilVersion.version));
00131 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Driver : %1.%2.%3")
00132 .arg(info.drvVersion.drvMajor)
00133 .arg(info.drvVersion.drvMinor)
00134 .arg(info.drvVersion.version));
00135 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Firmware: %1.%2.%3")
00136 .arg(info.fwVersion.fwMajor)
00137 .arg(info.fwVersion.fwMinor)
00138 .arg(info.fwVersion.version));
00139 }
00140
00141 if (BC_70012 == m_device_type)
00142 {
00143 LOG(VB_GENERAL, LOG_ERR, LOC +
00144 "BCM70012 device is currently unsupported.");
00145 return false;
00146 }
00147
00148 BC_HW_CAPS hw_caps;
00149 uint32_t codecs;
00150 st = DtsGetCapabilities(m_device, &hw_caps);
00151 CHECK_ST;
00152 if (!ok)
00153 {
00154 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to get device capabilities");
00155 return false;
00156 }
00157
00158 BC_OUTPUT_FORMAT m_desired_fmt = (m_device_type == BC_70015) ?
00159 OUTPUT_MODE422_YUY2 : OUTPUT_MODE420;
00160 m_pix_fmt = OUTPUT_MODE_INVALID;
00161 for (int i = 0; i < hw_caps.ColorCaps.Count; i++)
00162 {
00163 if (m_desired_fmt == hw_caps.ColorCaps.OutFmt[i])
00164 m_pix_fmt = m_desired_fmt;
00165 if (!debugged)
00166 {
00167 LOG(VB_PLAYBACK, LOG_INFO, LOC +
00168 QString("Supported output format: %1")
00169 .arg(bcmpixfmt_to_string(hw_caps.ColorCaps.OutFmt[i])));
00170 }
00171 }
00172 if (m_pix_fmt != m_desired_fmt)
00173 {
00174 LOG(VB_PLAYBACK, LOG_ERR, LOC +
00175 "Failed to find correct output format.");
00176 return false;
00177 }
00178 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Using: %1")
00179 .arg(bcmpixfmt_to_string(m_pix_fmt)));
00180
00181 codecs = hw_caps.DecCaps;
00182 if (!debugged)
00183 {
00184 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("H.264 support: %1")
00185 .arg((bool)(codecs & BC_DEC_FLAGS_H264)));
00186 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("MPEG2 support: %1")
00187 .arg((bool)(codecs & BC_DEC_FLAGS_MPEG2)));
00188 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("VC1 support: %1")
00189 .arg((bool)(codecs & BC_DEC_FLAGS_VC1)));
00190 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("MPEG4 support: %1")
00191 .arg((bool)(codecs & BC_DEC_FLAGS_M4P2)));
00192 debugged = true;
00193 }
00194
00195 BC_MEDIA_SUBTYPE sub_type = BC_MSUBTYPE_INVALID;
00196
00197 switch (avctx->codec_id)
00198 {
00199 case CODEC_ID_MPEG4:
00200 if (codecs & BC_DEC_FLAGS_M4P2)
00201 sub_type = BC_MSUBTYPE_DIVX;
00202 break;
00203 case CODEC_ID_MPEG1VIDEO:
00204 if (codecs & BC_DEC_FLAGS_MPEG2)
00205 sub_type = BC_MSUBTYPE_MPEG1VIDEO;
00206 break;
00207 case CODEC_ID_MPEG2VIDEO:
00208 if (codecs & BC_DEC_FLAGS_MPEG2)
00209 sub_type = BC_MSUBTYPE_MPEG2VIDEO;
00210 break;
00211 case CODEC_ID_VC1:
00212 if (codecs & BC_DEC_FLAGS_VC1)
00213 {
00214 if (avctx->codec_tag == MKTAG('W','V','C','1'))
00215 sub_type = BC_MSUBTYPE_WVC1;
00216 else
00217 sub_type = BC_MSUBTYPE_VC1;
00218 }
00219 break;
00220 case CODEC_ID_WMV3:
00221 if (codecs & BC_DEC_FLAGS_VC1)
00222 sub_type = BC_MSUBTYPE_WMV3;
00223 break;
00224 case CODEC_ID_H264:
00225 if (codecs & BC_DEC_FLAGS_H264)
00226 {
00227 if (avctx->extradata[0] == 0x01)
00228 {
00229 if (!CreateFilter(avctx))
00230 {
00231 LOG(VB_PLAYBACK, LOG_ERR, LOC +
00232 "Failed to create stream filter");
00233 return false;
00234 }
00235 sub_type = BC_MSUBTYPE_AVC1;
00236 }
00237 else
00238 sub_type = BC_MSUBTYPE_H264;
00239 }
00240 break;
00241 }
00242
00243 if (sub_type == BC_MSUBTYPE_INVALID)
00244 {
00245 LOG(VB_PLAYBACK, LOG_ERR, LOC + QString("Codec %1 not supported")
00246 .arg(ff_codec_id_string(avctx->codec_id)));
00247 return false;
00248 }
00249
00250 int nalsize = 4;
00251 if (avctx->codec_id == CODEC_ID_H264)
00252 {
00253 LOG(VB_PLAYBACK, LOG_INFO, LOC +
00254 QString("H.264 Profile: %1 RefFrames: %2 Codec tag: %3")
00255 .arg(avctx->profile).arg(avctx->refs)
00256 .arg(fourcc_str(avctx->codec_tag)));
00257 if (avctx->extradata[0] == 1)
00258 {
00259 nalsize = (avctx->extradata[4] & 0x03) + 1;
00260 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("avcC nal size: %1")
00261 .arg(nalsize));
00262 }
00263 }
00264
00265 BC_INPUT_FORMAT fmt;
00266 memset(&fmt, 0, sizeof(BC_INPUT_FORMAT));
00267 fmt.OptFlags = 0x80000000 | vdecFrameRateUnknown;
00268 fmt.width = avctx->coded_width;
00269 fmt.height = avctx->coded_height;
00270 fmt.Progressive = 1;
00271 fmt.FGTEnable = 0;
00272 fmt.MetaDataEnable = 0;
00273 fmt.metaDataSz = avctx->extradata_size;
00274 fmt.pMetaData = avctx->extradata;
00275 fmt.startCodeSz = nalsize;
00276 fmt.mSubtype = sub_type;
00277
00278 st = DtsSetInputFormat(m_device, &fmt);
00279 CHECK_ST;
00280 if (!ok)
00281 {
00282 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to set decoder input format");
00283 return false;
00284 }
00285
00286 st = DtsOpenDecoder(m_device, BC_STREAM_TYPE_ES);
00287 CHECK_ST;
00288 if (!ok)
00289 {
00290 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to open CrystalHD decoder");
00291 return false;
00292 }
00293
00294 st = DtsSetColorSpace(m_device, m_pix_fmt);
00295 if (!ok)
00296 {
00297 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to set decoder output format");
00298 return false;
00299 }
00300
00301 st = DtsStartDecoder(m_device);
00302 if (!ok)
00303 {
00304 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to start decoder");
00305 return false;
00306 }
00307
00308 st = DtsStartCapture(m_device);
00309 if (!ok)
00310 {
00311 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to start capture");
00312 return false;
00313 }
00314
00315 Reset();
00316
00317 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Created decoder %1 %2x%3")
00318 .arg(ff_codec_id_string(avctx->codec_id))
00319 .arg(avctx->coded_width).arg(avctx->coded_height));
00320 return true;
00321 }
00322
00323 bool PrivateDecoderCrystalHD::CreateFilter(AVCodecContext *avctx)
00324 {
00325 int nalsize = (avctx->extradata[4] & 0x3) + 1;
00326 if (!nalsize || nalsize == 3 || nalsize > 4)
00327 {
00328 LOG(VB_PLAYBACK, LOG_ERR, LOC + QString("Invalid nal size (%1)")
00329 .arg(nalsize));
00330 return false;
00331 }
00332
00333 static const uint8_t testnal[] = { 0,0,0,2,0,0 };
00334 AVBitStreamFilterContext *bsfc =
00335 av_bitstream_filter_init("h264_mp4toannexb");
00336 if (!bsfc)
00337 return false;
00338 m_filter = bsfc;
00339
00340
00341 const uint8_t *test = testnal;
00342 int testsize = 6;
00343 int outbuf_size = 0;
00344 uint8_t *outbuf = NULL;
00345 int res = av_bitstream_filter_filter(m_filter, avctx, NULL, &outbuf,
00346 &outbuf_size, test, testsize, 0);
00347 delete outbuf;
00348 return res > 0;
00349 }
00350
00351 void inline free_frame(VideoFrame* frame)
00352 {
00353 if (frame)
00354 {
00355 if (frame->buf)
00356 delete [] frame->buf;
00357 if (frame->priv[0])
00358 delete [] frame->priv[0];
00359 delete frame;
00360 }
00361 }
00362
00363 void inline free_buffer(PacketBuffer* buffer)
00364 {
00365 if (buffer)
00366 {
00367 if (buffer->buf)
00368 delete [] buffer->buf;
00369 delete buffer;
00370 }
00371 }
00372
00373 bool PrivateDecoderCrystalHD::Reset(void)
00374 {
00375 if (m_fetcher_thread)
00376 {
00377 m_fetcher_pause = true;
00378 int tries = 0;
00379 while (!m_fetcher_paused && (tries++ < 50))
00380 usleep(10000);
00381 if (!m_fetcher_paused)
00382 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to pause fetcher thread");
00383 }
00384
00385 QMutexLocker lock(&m_decoded_frames_lock);
00386 free_frame(m_frame);
00387 m_frame = NULL;
00388
00389 for (int i = 0; i < m_decoded_frames.size(); i++)
00390 free_frame(m_decoded_frames[i]);
00391 m_decoded_frames.clear();
00392
00393 for (int i = 0; i < m_packet_buffers.size(); i++)
00394 free_buffer(m_packet_buffers[i]);
00395 m_packet_buffers.clear();
00396
00397 if (!m_device)
00398 return true;
00399
00400 if (m_device_type != BC_70015)
00401 {
00402 INIT_ST;
00403 st = DtsFlushInput(m_device, 2);
00404 CHECK_ST;
00405 }
00406 return true;;
00407 }
00408
00409 bool PrivateDecoderCrystalHD::HasBufferedFrames(void)
00410 {
00411 m_decoded_frames_lock.lock();
00412 bool result = m_decoded_frames.size() > 0;
00413 m_decoded_frames_lock.unlock();
00414 return result;
00415 }
00416
00417 int PrivateDecoderCrystalHD::ProcessPacket(AVStream *stream, AVPacket *pkt)
00418 {
00419 int result = -1;
00420 AVCodecContext *avctx = stream->codec;
00421 if (!avctx)
00422 return result;
00423
00424 PacketBuffer *buffer = new PacketBuffer();
00425 if (!buffer)
00426 return result;
00427
00428 buffer->buf = new unsigned char[pkt->size];
00429 buffer->size = pkt->size;
00430 buffer->pts = pkt->pts;
00431 memcpy(buffer->buf, pkt->data, pkt->size);
00432
00433 m_packet_buffers.insert(0, buffer);
00434 LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
00435 QString("%1 packet buffers queued up").arg(m_packet_buffers.size()));
00436
00437 while (m_packet_buffers.size() > 0)
00438 {
00439
00440 PacketBuffer *buffer = m_packet_buffers.last();
00441 if (GetTxFreeSize(0) < buffer->size)
00442 {
00443 usleep(10000);
00444 return 0;
00445 }
00446
00447 buffer = m_packet_buffers.takeLast();
00448 uint8_t* buf = buffer->buf;
00449 int size = buffer->size;
00450 bool free_buf = false;
00451 int outbuf_size = 0;
00452 uint8_t *outbuf = NULL;
00453
00454 if (m_filter)
00455 {
00456 int res = av_bitstream_filter_filter(m_filter, avctx, NULL, &outbuf,
00457 &outbuf_size, buf, size, 0);
00458 if (res <= 0)
00459 {
00460 static int count = 0;
00461 if (count == 0)
00462 LOG(VB_GENERAL, LOG_ERR, LOC +
00463 QString("Failed to convert packet (%1)").arg(res));
00464 count++;
00465 if (count > 200)
00466 count = 0;
00467 }
00468
00469 if (outbuf && (outbuf_size > 0))
00470 {
00471 free_buf = outbuf != buf;
00472 size = outbuf_size;
00473 buf = outbuf;
00474 }
00475 }
00476
00477 usleep(1000);
00478 uint64_t chd_timestamp = 0;
00479 if (buffer->pts != (int64_t)AV_NOPTS_VALUE)
00480 chd_timestamp = (uint64_t)(av_q2d(stream->time_base) *
00481 buffer->pts * 10000000);
00482 LOG(VB_TIMESTAMP, LOG_DEBUG, LOC +
00483 QString("decoder input timecode %1 ms (pts %2)")
00484 .arg(chd_timestamp / 10000).arg(buffer->pts));
00485
00486
00487 INIT_ST;
00488 st = DtsProcInput(m_device, buf, size, chd_timestamp, false);
00489 CHECK_ST;
00490
00491 if (free_buf)
00492 delete buf;
00493
00494 free_buffer(buffer);
00495 if (!ok)
00496 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to send packet to decoder.");
00497 result = buffer->size;
00498 }
00499 return result;
00500 }
00501
00502 int PrivateDecoderCrystalHD::GetFrame(AVStream *stream,
00503 AVFrame *picture,
00504 int *got_picture_ptr,
00505 AVPacket *pkt)
00506 {
00507 int result = -1;
00508 if (!stream || !m_device || !picture)
00509 return result;
00510
00511 AVCodecContext *avctx = stream->codec;
00512 if (!avctx || !StartFetcherThread())
00513 return result;
00514
00515 if (pkt && pkt->size)
00516 {
00517 result = ProcessPacket(stream, pkt);
00518 if (result < 0)
00519 return result;
00520 }
00521
00522 m_decoded_frames_lock.lock();
00523 int available = m_decoded_frames.size();
00524 m_decoded_frames_lock.unlock();
00525 if (!available)
00526 return result;
00527
00528 if (avctx->get_buffer(avctx, picture) < 0)
00529 {
00530 LOG(VB_GENERAL, LOG_ERR, LOC +
00531 QString("%1 decoded frames available but no video buffers.")
00532 .arg(available));
00533 return -1;
00534 }
00535
00536 m_decoded_frames_lock.lock();
00537 VideoFrame *frame = m_decoded_frames.takeLast();
00538 m_decoded_frames_lock.unlock();
00539
00540 *got_picture_ptr = 1;
00541 picture->reordered_opaque = (int64_t)(frame->timecode /
00542 av_q2d(stream->time_base) / 10000000);
00543 LOG(VB_TIMESTAMP, LOG_DEBUG, LOC +
00544 QString("decoder output timecode %1 ms (pts %2)")
00545 .arg(frame->timecode / 10000).arg(picture->reordered_opaque));
00546 copy((VideoFrame*)picture->opaque, frame);
00547 if (frame->priv[0] && frame->qstride)
00548 {
00549 memcpy(picture->atsc_cc_buf, frame->priv[0], frame->qstride);
00550 picture->atsc_cc_len = frame->qstride;
00551 }
00552 free_frame(frame);
00553 return result;
00554 }
00555
00556 void PrivateDecoderCrystalHD::FetchFrames(void)
00557 {
00558 INIT_ST;
00559 bool valid = false;
00560 m_fetcher_paused = false;
00561 while (!m_fetcher_stop)
00562 {
00563 usleep(1000);
00564 if (m_fetcher_pause)
00565 {
00566 m_fetcher_paused = true;
00567 continue;
00568 }
00569 m_fetcher_paused = false;
00570
00571 BC_DTS_STATUS status;
00572 st = DtsGetDriverStatus(m_device, &status);
00573 CHECK_ST;
00574
00575 if (!status.ReadyListCount)
00576 continue;
00577
00578 BC_DTS_PROC_OUT out;
00579 memset(&out, 0, sizeof(BC_DTS_PROC_OUT));
00580 st = DtsProcOutputNoCopy(m_device, valid ? 2000 : 20, &out);
00581
00582 if (BC_STS_FMT_CHANGE == st)
00583 {
00584 LOG(VB_GENERAL, LOG_INFO, LOC + "Decoder reported format change.");
00585 CheckProcOutput(&out);
00586 valid = true;
00587 continue;
00588 }
00589 CHECK_ST;
00590
00591 if (!ok)
00592 {
00593 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to fetch decoded frame");
00594 continue;
00595 }
00596
00597 if (ok && valid && (out.PoutFlags & BC_POUT_FLAGS_PIB_VALID))
00598 FillFrame(&out);
00599 st = DtsReleaseOutputBuffs(m_device, NULL, false);
00600 CHECK_ST;
00601 }
00602 }
00603
00604 bool PrivateDecoderCrystalHD::StartFetcherThread(void)
00605 {
00606 m_fetcher_pause = false;
00607 if (m_fetcher_thread)
00608 return true;
00609
00610 m_fetcher_thread = new FetcherThread(this);
00611 if (!m_fetcher_thread)
00612 return false;
00613
00614 m_fetcher_thread->start();
00615 return true;
00616 }
00617
00618
00619 void PrivateDecoderCrystalHD::FillFrame(BC_DTS_PROC_OUT *out)
00620 {
00621 bool second_field = false;
00622 if (m_frame)
00623 {
00624 if (out->PicInfo.picture_number != m_frame->frameNumber)
00625 {
00626 LOG(VB_PLAYBACK, LOG_WARNING, LOC + "Missing second field");
00627 AddFrameToQueue();
00628 }
00629 else
00630 {
00631 second_field = true;
00632 }
00633 }
00634
00635 int in_width = out->PicInfo.width;
00636 int in_height = out->PicInfo.height;
00637 int out_width = (in_width + 15) & (~0xf);
00638 int out_height = in_height;
00639 int size = ((out_width * (out_height + 1)) * 3) / 2;
00640 uint8_t* src = out->Ybuff;
00641
00642 if (!m_frame)
00643 {
00644 unsigned char* buf = new unsigned char[size];
00645 m_frame = new VideoFrame();
00646 init(m_frame, FMT_YV12, buf, out_width, out_height, size);
00647 m_frame->timecode = (int64_t)out->PicInfo.timeStamp;
00648 m_frame->frameNumber = out->PicInfo.picture_number;
00649 }
00650
00651 if (!m_frame)
00652 return;
00653
00654
00655
00656 if (out->UserData && out->UserDataSz)
00657 {
00658 int size = out->UserDataSz > 1024 ? 1024 : out->UserDataSz;
00659 m_frame->priv[0] = new unsigned char[size];
00660 memcpy(m_frame->priv[0], out->UserData, size);
00661 m_frame->qstride = size;
00662 }
00663
00664 PixelFormat out_fmt = PIX_FMT_YUV420P;
00665 PixelFormat in_fmt = bcmpixfmt_to_pixfmt(m_pix_fmt);
00666 AVPicture img_in, img_out;
00667 avpicture_fill(&img_out, (uint8_t *)m_frame->buf, out_fmt,
00668 out_width, out_height);
00669 avpicture_fill(&img_in, src, in_fmt,
00670 in_width, in_height);
00671
00672 if (!(out->PicInfo.flags & VDEC_FLAG_INTERLACED_SRC))
00673 {
00674 myth_sws_img_convert(&img_out, out_fmt, &img_in, in_fmt,
00675 in_width, in_height);
00676 m_frame->interlaced_frame = 0;
00677 AddFrameToQueue();
00678 }
00679 else
00680 {
00681 img_out.linesize[0] *= 2;
00682 img_out.linesize[1] *= 2;
00683 img_out.linesize[2] *= 2;
00684 m_frame->top_field_first = out->PicInfo.pulldown == vdecTopBottom;
00685 int field = out->PoutFlags & BC_POUT_FLAGS_FLD_BOT;
00686 if (field)
00687 {
00688 img_out.data[0] += out_width;
00689 img_out.data[1] += out_width >> 1;
00690 img_out.data[2] += out_width >> 1;
00691 }
00692 myth_sws_img_convert(&img_out, out_fmt, &img_in,
00693 in_fmt, in_width, in_height / 2);
00694 if (second_field)
00695 AddFrameToQueue();
00696 }
00697 }
00698
00699 void PrivateDecoderCrystalHD::AddFrameToQueue(void)
00700 {
00701 m_decoded_frames_lock.lock();
00702 m_decoded_frames.insert(0, m_frame);
00703 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("Decoded frame queue size %1")
00704 .arg(m_decoded_frames.size()));
00705 m_decoded_frames_lock.unlock();
00706 m_frame = NULL;
00707 }
00708
00709 void PrivateDecoderCrystalHD::CheckProcOutput(BC_DTS_PROC_OUT *out)
00710 {
00711 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut Ybuf : %1")
00712 .arg((uintptr_t)out->Ybuff));
00713 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut Ybuffsz : %1")
00714 .arg(out->YbuffSz));
00715 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut Ybuffdnsz : %1")
00716 .arg(out->YBuffDoneSz));
00717 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut Ubuf : %1")
00718 .arg((uintptr_t)out->UVbuff));
00719 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut Ubuffsz : %1")
00720 .arg(out->UVbuffSz));
00721 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut Ubuffdnsz : %1")
00722 .arg(out->UVBuffDoneSz));
00723 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut StrideSz : %1")
00724 .arg(out->StrideSz));
00725 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut Flags : %1")
00726 .arg(poutflags_to_string(out->PoutFlags)));
00727 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut DiscCnt : %1")
00728 .arg(out->discCnt));
00729 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut usrdatasz : %1")
00730 .arg(out->UserDataSz));
00731 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut DropFrames: %1")
00732 .arg(out->DropFrames));
00733 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut b422Mode : %1")
00734 .arg(bcmpixfmt_to_string((BC_OUTPUT_FORMAT)out->b422Mode)));
00735 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut bPIBenc : %1")
00736 .arg(out->bPibEnc));
00737 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut revertscra: %1")
00738 .arg(out->bRevertScramble));
00739 CheckPicInfo(out);
00740 }
00741
00742 void PrivateDecoderCrystalHD::CheckPicInfo(BC_DTS_PROC_OUT *out)
00743 {
00744 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo timestamp: %1")
00745 .arg(out->PicInfo.timeStamp));
00746 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo picnumber: %1")
00747 .arg(out->PicInfo.picture_number));
00748 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo width : %1")
00749 .arg(out->PicInfo.width));
00750 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo height : %1")
00751 .arg(out->PicInfo.height));
00752 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo chromafmt: %1")
00753 .arg(out->PicInfo.chroma_format));
00754 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo pulldown : %1")
00755 .arg(pulldown_to_string(out->PicInfo.pulldown)));
00756 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo flags : %1")
00757 .arg(decoderflags_to_string(out->PicInfo.flags)));
00758 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo framerate: %1")
00759 .arg(out->PicInfo.frame_rate));
00760 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo aspectrat: %1")
00761 .arg(out->PicInfo.colour_primaries));
00762 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo metapaylo: %1")
00763 .arg(out->PicInfo.picture_meta_payload));
00764 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo sess_num : %1")
00765 .arg(out->PicInfo.sess_num));
00766 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo ycom : %1")
00767 .arg(out->PicInfo.ycom));
00768 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo customasp: %1")
00769 .arg(out->PicInfo.custom_aspect_ratio_width_height));
00770 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ProcOut PicInfo ndrop : %1")
00771 .arg(out->PicInfo.n_drop));
00772 }
00773
00774 void PrivateDecoderCrystalHD::CheckStatus(void)
00775 {
00776 BC_DTS_STATUS status;
00777 status.cpbEmptySize = 0x00000000;
00778 INIT_ST;
00779 st = DtsGetDriverStatus(m_device, &status);
00780 CHECK_ST;
00781 if (!ok)
00782 return;
00783
00784 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("ReadyListCount : %1")
00785 .arg(status.ReadyListCount));
00786 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("FreeListCount : %1")
00787 .arg(status.FreeListCount));
00788 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("PowerStateChange: %1")
00789 .arg(status.PowerStateChange));
00790 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("FrameDropped : %1")
00791 .arg(status.FramesDropped));
00792 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("FramesCaptured : %1")
00793 .arg(status.FramesCaptured));
00794 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("FramesRepeated : %1")
00795 .arg(status.FramesRepeated));
00796 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("InputCount : %1")
00797 .arg(status.InputCount));
00798 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("InputTotalSize : %1")
00799 .arg(status.InputTotalSize));
00800 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("InputBusyCount : %1")
00801 .arg(status.InputBusyCount));
00802 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("PIBMissCount : %1")
00803 .arg(status.PIBMissCount));
00804 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("cpbEmptySize : %1")
00805 .arg(status.cpbEmptySize));
00806 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("NextTimeStamp : %1")
00807 .arg(status.NextTimeStamp));
00808 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("PicNumFlags : %1")
00809 .arg(status.picNumFlags));
00810 }
00811
00812 int PrivateDecoderCrystalHD::GetTxFreeSize(bool hwsel)
00813 {
00814 BC_DTS_STATUS status;
00815 if (hwsel)
00816 status.cpbEmptySize = 0xC0000000;
00817 else
00818 status.cpbEmptySize = 0x40000000;
00819 INIT_ST;
00820 st = DtsGetDriverStatus(m_device, &status);
00821 CHECK_ST;
00822 if (!ok)
00823 return -1;
00824
00825 return status.cpbEmptySize;
00826 }
00827
00828 QString device_to_string(BC_DEVICE_TYPE device)
00829 {
00830 switch (device)
00831 {
00832 case BC_70012: return "BCM70012";
00833 case BC_70015: return "BCM70015";
00834 }
00835 return "Unknown";
00836 }
00837
00838 QString bcmerr_to_string(BC_STATUS err)
00839 {
00840 switch (err)
00841 {
00842 case BC_STS_INV_ARG: return "Invalid argument";
00843 case BC_STS_BUSY: return "Busy";
00844 case BC_STS_NOT_IMPL: return "Not implemented";
00845 case BC_STS_PGM_QUIT: return "PGM quit";
00846 case BC_STS_NO_ACCESS: return "No access";
00847 case BC_STS_INSUFF_RES: return "Insufficient resources";
00848 case BC_STS_IO_ERROR: return "I/O error";
00849 case BC_STS_NO_DATA: return "No data";
00850 case BC_STS_VER_MISMATCH: return "Version mismatch";
00851 case BC_STS_TIMEOUT: return "Timeout";
00852 case BC_STS_FW_CMD_ERR: return "Command error";
00853 case BC_STS_DEC_NOT_OPEN: return "Decoder not open";
00854 case BC_STS_ERR_USAGE: return "Usage error";
00855 case BC_STS_IO_USER_ABORT: return "I/O user abort";
00856 case BC_STS_IO_XFR_ERROR: return "I/O transfer error";
00857 case BC_STS_DEC_NOT_STARTED: return "Decoder not started";
00858 case BC_STS_FWHEX_NOT_FOUND: return "FirmwareHex not found";
00859 case BC_STS_FMT_CHANGE: return "Format change";
00860 case BC_STS_HIF_ACCESS: return "HIF access";
00861 case BC_STS_CMD_CANCELLED: return "Command cancelled";
00862 case BC_STS_FW_AUTH_FAILED: return "Firmware authorisation failed";
00863 case BC_STS_BOOTLOADER_FAILED: return "Bootloader failed";
00864 case BC_STS_CERT_VERIFY_ERROR: return "Certificate verify error";
00865 case BC_STS_DEC_EXIST_OPEN: return "Decoder exist open (?)";
00866 case BC_STS_PENDING: return "Pending";
00867 case BC_STS_ERROR: return "Unknown";
00868 }
00869 return "Unknown error";
00870 }
00871
00872 QString bcmpixfmt_to_string(BC_OUTPUT_FORMAT fmt)
00873 {
00874 switch (fmt)
00875 {
00876 case OUTPUT_MODE420: return "YUV420P";
00877 case OUTPUT_MODE422_YUY2: return "YUYV422";
00878 case OUTPUT_MODE422_UYVY: return "UYVY422";
00879 }
00880 return "Unknown";
00881 }
00882
00883 QString pulldown_to_string(int pulldown)
00884 {
00885 switch (pulldown)
00886 {
00887 case vdecNoPulldownInfo: return "Unknown";
00888 case vdecTop: return "Top";
00889 case vdecBottom: return "Bottom";
00890 case vdecTopBottom: return "TopBottom";
00891 case vdecBottomTop: return "BottomTop";
00892 case vdecTopBottomTop: return "TopBottomTop";
00893 case vdecBottomTopBottom: return "BottomTopBottom";
00894 case vdecFrame_X2: return "X2";
00895 case vdecFrame_X3: return "X3";
00896 case vdecFrame_X1: return "X1";
00897 case vdecFrame_X4: return "X4";
00898 }
00899 return "Unknown";
00900 }
00901
00902 QString decoderflags_to_string(int flags)
00903 {
00904 QString res;
00905 if (flags & VDEC_FLAG_EOS) res += "EndOfStream ";
00906 if (flags & VDEC_FLAG_FIELDPAIR) res += "FieldPair ";
00907 if (flags & VDEC_FLAG_TOPFIELD) res += "TopField ";
00908 if (flags & VDEC_FLAG_BOTTOMFIELD) res += "BottomField ";
00909 if (flags & VDEC_FLAG_INTERLACED_SRC) res += "InterlacedSource ";
00910 if (flags & VDEC_FLAG_UNKNOWN_SRC) res += "UnknownSource ";
00911 if (flags & VDEC_FLAG_BOTTOM_FIRST) res += "BottomFirst ";
00912 if (flags & VDEC_FLAG_LAST_PICTURE) res += "LastPicture ";
00913 if (flags & VDEC_FLAG_PICTURE_META_DATA_PRESENT) res += "MetaDataPresent ";
00914 return res;
00915 }
00916
00917 QString poutflags_to_string(int flags)
00918 {
00919 QString res;
00920 if (flags & BC_POUT_FLAGS_YV12) res += "YV12 ";
00921 if (flags & BC_POUT_FLAGS_STRIDE) res += "STRIDE ";
00922 if (flags & BC_POUT_FLAGS_SIZE) res += "SIZE ";
00923 if (flags & BC_POUT_FLAGS_INTERLACED) res += "INTERLACED ";
00924 if (flags & BC_POUT_FLAGS_INTERLEAVED) res += "INTERLEAVED ";
00925 if (flags & BC_POUT_FLAGS_STRIDE_UV) res += "UVSTRIDE ";
00926 if (flags & BC_POUT_FLAGS_MODE) res += "APPMODE ";
00927 if (flags & BC_POUT_FLAGS_FMT_CHANGE) res += "FORMATCHANGED ";
00928 if (flags & BC_POUT_FLAGS_PIB_VALID) res += "PIBVALID ";
00929 if (flags & BC_POUT_FLAGS_ENCRYPTED) res += "ENCRYPTED ";
00930 if (flags & BC_POUT_FLAGS_FLD_BOT) res += "FIELDBOTTOM ";
00931 return res;
00932 }
00933
00934 PixelFormat bcmpixfmt_to_pixfmt(BC_OUTPUT_FORMAT fmt)
00935 {
00936 switch (fmt)
00937 {
00938 case OUTPUT_MODE420: return PIX_FMT_YUV420P;
00939 case OUTPUT_MODE422_YUY2: return PIX_FMT_YUYV422;
00940 case OUTPUT_MODE422_UYVY: return PIX_FMT_UYVY422;
00941 }
00942 return PIX_FMT_YUV420P;
00943 }