MythTV  0.26-pre
privatedecoder_crystalhd.cpp
Go to the documentation of this file.
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     // and test extradata
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; // 100 nsec units
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         // TODO check for busy state
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     // line 21 data (608/708 captions)
00655     // this appears to be unimplemented in the driver
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; // don't try this at home
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; // set bit 31 for real HW free size
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; // set bit 31 for real HW free size
00817     else
00818         status.cpbEmptySize = 0x40000000; // set bit 30 for TX only status
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends