76 #define _XOPEN_SOURCE 600
82 #include <libcrystalhd/bc_dts_types.h>
83 #include <libcrystalhd/bc_dts_defs.h>
84 #include <libcrystalhd/libcrystalhd_if.h>
94 #define OUTPUT_PROC_TIMEOUT 50
96 #define TIMESTAMP_UNIT 100000
98 #define BASE_WAIT 10000
100 #define WAIT_UNIT 1000
154 {
"crystalhd_downscale_width",
155 "Turn on downscaling to the specified width",
171 return BC_MSUBTYPE_DIVX;
173 return BC_MSUBTYPE_DIVX311;
175 return BC_MSUBTYPE_MPEG2VIDEO;
177 return BC_MSUBTYPE_VC1;
179 return BC_MSUBTYPE_WMV3;
181 return priv->
is_nal ? BC_MSUBTYPE_AVC1 : BC_MSUBTYPE_H264;
183 return BC_MSUBTYPE_INVALID;
191 output->YBuffDoneSz);
193 output->UVBuffDoneSz);
195 output->PicInfo.timeStamp);
197 output->PicInfo.picture_number);
199 output->PicInfo.width);
201 output->PicInfo.height);
203 output->PicInfo.chroma_format);
205 output->PicInfo.pulldown);
207 output->PicInfo.flags);
209 output->PicInfo.frame_rate);
211 output->PicInfo.aspect_ratio);
213 output->PicInfo.colour_primaries);
215 output->PicInfo.picture_meta_payload);
217 output->PicInfo.sess_num);
219 output->PicInfo.ycom);
221 output->PicInfo.custom_aspect_ratio_width_height);
223 output->PicInfo.n_drop);
225 output->PicInfo.other.h264.valid);
239 "Unable to allocate new node in OpaqueList.\n");
244 priv->
head = newNode;
249 priv->
tail = newNode;
269 "CrystalHD: Attempted to query non-existent timestamps.\n");
307 "CrystalHD: Couldn't match fake_timestamp.\n");
331 DtsFlushInput(priv->
dev, 4);
341 DtsStopDecoder(device);
342 DtsCloseDecoder(device);
343 DtsDeviceClose(device);
386 BC_INPUT_FORMAT format = {
389 .OptFlags = 0x80000000 | vdecFrameRate59_94 | 0x40,
390 .width = avctx->
width,
394 BC_MEDIA_SUBTYPE subtype;
396 uint32_t
mode = DTS_PLAYBACK_MODE |
397 DTS_LOAD_FILE_PLAY_FW |
398 DTS_SKIP_TX_CHK_CPB |
399 DTS_PLAYBACK_DROP_RPT_MODE |
400 DTS_SINGLE_THREADED_MODE |
401 DTS_DFLT_RESOLUTION(vdecRESOLUTION_1080p23_976);
417 case BC_MSUBTYPE_AVC1:
426 "Failed to allocate copy of extradata\n");
435 "Cannot open the h264_mp4toannexb BSF!\n");
439 &dummy_int,
NULL, 0, 0);
441 subtype = BC_MSUBTYPE_H264;
443 case BC_MSUBTYPE_H264:
444 format.startCodeSz = 4;
446 case BC_MSUBTYPE_VC1:
447 case BC_MSUBTYPE_WVC1:
448 case BC_MSUBTYPE_WMV3:
449 case BC_MSUBTYPE_WMVA:
450 case BC_MSUBTYPE_MPEG2VIDEO:
451 case BC_MSUBTYPE_DIVX:
452 case BC_MSUBTYPE_DIVX311:
460 format.mSubtype = subtype;
463 format.bEnableScaling = 1;
464 format.ScalingParams.sWidth = priv->
sWidth;
470 ret = DtsDeviceOpen(&priv->
dev, mode);
471 if (ret != BC_STS_SUCCESS) {
476 ret = DtsCrystalHDVersion(priv->
dev, &version);
477 if (ret != BC_STS_SUCCESS) {
479 "CrystalHD: DtsCrystalHDVersion failed\n");
482 priv->
is_70012 = version.device == 0;
485 (subtype == BC_MSUBTYPE_DIVX || subtype == BC_MSUBTYPE_DIVX311)) {
487 "CrystalHD: BCM70012 doesn't support MPEG4-ASP/DivX/Xvid\n");
491 ret = DtsSetInputFormat(priv->
dev, &format);
492 if (ret != BC_STS_SUCCESS) {
497 ret = DtsOpenDecoder(priv->
dev, BC_STREAM_TYPE_ES);
498 if (ret != BC_STS_SUCCESS) {
503 ret = DtsSetColorSpace(priv->
dev, OUTPUT_MODE422_YUY2);
504 if (ret != BC_STS_SUCCESS) {
508 ret = DtsStartDecoder(priv->
dev);
509 if (ret != BC_STS_SUCCESS) {
513 ret = DtsStartCapture(priv->
dev);
514 if (ret != BC_STS_SUCCESS) {
523 "Cannot open the h.264 parser! Interlaced h.264 content "
524 "will not be detected reliably.\n");
538 BC_DTS_PROC_OUT *output,
539 void *
data,
int *got_frame)
542 BC_DTS_STATUS decoder_status = { 0, };
550 uint8_t bottom_field = (output->PicInfo.flags & VDEC_FLAG_BOTTOMFIELD) ==
551 VDEC_FLAG_BOTTOMFIELD;
552 uint8_t bottom_first = !!(output->PicInfo.flags & VDEC_FLAG_BOTTOM_FIRST);
554 int width = output->PicInfo.width;
555 int height = output->PicInfo.height;
562 if (output->PicInfo.timeStamp != 0) {
580 output->PicInfo.timeStamp);
585 ret = DtsGetDriverStatus(priv->
dev, &decoder_status);
586 if (ret != BC_STS_SUCCESS) {
588 "CrystalHD: GetDriverStatus failed: %u\n", ret);
609 !(output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) ||
611 (decoder_status.picNumFlags & ~0x40000000) ==
612 output->PicInfo.picture_number;
622 "Incorrectly guessed progressive frame. Discarding second field\n");
627 interlaced = (output->PicInfo.flags & VDEC_FLAG_INTERLACED_SRC) &&
630 if (!trust_interlaced && (decoder_status.picNumFlags & ~0x40000000) == 0) {
632 "Next picture number unknown. Assuming progressive frame.\n");
636 interlaced, trust_interlaced);
658 else if (width <= 1280)
684 for (sY = 0; sY <
height; dY++, sY++) {
685 memcpy(&(dst[dY * dStride]), &(src[sY * sStride]), bwidth);
710 if (!interlaced && (output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) &&
729 (!(output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) ||
736 void *
data,
int *got_frame)
739 BC_DTS_PROC_OUT output = {
740 .PicInfo.width = avctx->
width,
741 .PicInfo.height = avctx->
height,
744 HANDLE dev = priv->
dev;
750 if (ret == BC_STS_FMT_CHANGE) {
752 avctx->
width = output.PicInfo.width;
753 avctx->
height = output.PicInfo.height;
754 switch ( output.PicInfo.aspect_ratio ) {
755 case vdecAspectRatioSquare:
758 case vdecAspectRatio12_11:
761 case vdecAspectRatio10_11:
764 case vdecAspectRatio16_11:
767 case vdecAspectRatio40_33:
770 case vdecAspectRatio24_11:
773 case vdecAspectRatio20_11:
776 case vdecAspectRatio32_11:
779 case vdecAspectRatio80_33:
782 case vdecAspectRatio18_11:
785 case vdecAspectRatio15_11:
788 case vdecAspectRatio64_33:
791 case vdecAspectRatio160_99:
794 case vdecAspectRatio4_3:
797 case vdecAspectRatio16_9:
800 case vdecAspectRatio221_1:
805 }
else if (ret == BC_STS_SUCCESS) {
807 if (output.PoutFlags & BC_POUT_FLAGS_PIB_VALID) {
817 output.PicInfo.timeStamp == 0 && priv->
bframe_bug) {
819 "CrystalHD: Not returning packed frame twice.\n");
821 DtsReleaseOutputBuffs(dev,
NULL, FALSE);
827 if (priv->
last_picture + 1 < output.PicInfo.picture_number) {
829 "CrystalHD: Picture Number discontinuity\n");
843 copy_ret =
copy_frame(avctx, &output, data, got_frame);
844 if (*got_frame > 0) {
859 DtsReleaseOutputBuffs(dev,
NULL, FALSE);
862 }
else if (ret == BC_STS_BUSY) {
874 BC_DTS_STATUS decoder_status = { 0, };
877 HANDLE dev = priv->
dev;
890 "CrystalHD: Enabling work-around for packed b-frame bug\n");
897 "CrystalHD: Disabling work-around for packed b-frame bug\n");
910 avpkt->
data, len, 0);
921 in_data, len, avctx->
pkt->
pts,
925 "CrystalHD: Failed to parse h.264 packet to "
926 "detect interlacing.\n");
927 }
else if (index != len) {
929 "CrystalHD: Failed to parse h.264 packet "
930 "completely. Interlaced frames may be "
931 "incorrectly detected.\n");
934 "CrystalHD: parser picture type %d\n",
940 "CrystalHD: mp4toannexb filter failed to filter "
941 "packet. Interlaced frames may be incorrectly "
946 if (len < tx_free - 1024) {
964 "input \"pts\": %"PRIu64
"\n", pts);
965 ret = DtsProcInput(dev, in_data, len, pts, 0);
969 if (ret == BC_STS_BUSY) {
971 "CrystalHD: ProcInput returned busy\n");
974 }
else if (ret != BC_STS_SUCCESS) {
976 "CrystalHD: ProcInput failed: %u\n", ret);
995 ret = DtsGetDriverStatus(dev, &decoder_status);
996 if (ret != BC_STS_SUCCESS) {
1010 if (decoder_status.ReadyListCount != 0)
1015 }
else if (decoder_status.ReadyListCount == 0) {
1030 if (rec_ret ==
RET_OK && *got_frame == 0) {
1052 ret = DtsGetDriverStatus(dev, &decoder_status);
1053 if (ret == BC_STS_SUCCESS &&
1054 decoder_status.ReadyListCount > 0) {
1056 if ((rec_ret ==
RET_OK && *got_frame > 0) ||
1067 "Don't output on next decode call.\n");
1084 #if CONFIG_H264_CRYSTALHD_DECODER
1092 AVCodec ff_h264_crystalhd_decoder = {
1093 .
name =
"h264_crystalhd",
1102 .long_name =
NULL_IF_CONFIG_SMALL(
"H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (CrystalHD acceleration)"),
1108 #if CONFIG_MPEG2_CRYSTALHD_DECODER
1109 static AVClass mpeg2_class = {
1116 AVCodec ff_mpeg2_crystalhd_decoder = {
1117 .
name =
"mpeg2_crystalhd",
1128 .priv_class = &mpeg2_class,
1132 #if CONFIG_MPEG4_CRYSTALHD_DECODER
1140 AVCodec ff_mpeg4_crystalhd_decoder = {
1141 .
name =
"mpeg4_crystalhd",
1156 #if CONFIG_MSMPEG4_CRYSTALHD_DECODER
1157 static AVClass msmpeg4_class = {
1158 "msmpeg4_crystalhd",
1164 AVCodec ff_msmpeg4_crystalhd_decoder = {
1165 .
name =
"msmpeg4_crystalhd",
1174 .long_name =
NULL_IF_CONFIG_SMALL(
"MPEG-4 Part 2 Microsoft variant version 3 (CrystalHD acceleration)"),
1176 .priv_class = &msmpeg4_class,
1180 #if CONFIG_VC1_CRYSTALHD_DECODER
1188 AVCodec ff_vc1_crystalhd_decoder = {
1189 .
name =
"vc1_crystalhd",
1200 .priv_class = &vc1_class,
1204 #if CONFIG_WMV3_CRYSTALHD_DECODER
1212 AVCodec ff_wmv3_crystalhd_decoder = {
1213 .
name =
"wmv3_crystalhd",
1224 .priv_class = &wmv3_class,