1 /*
2 * - CrystalHD decoder module -
3 *
4 * Copyright(C) 2010,2011 Philip Langdale <ffmpeg.philipl@overt.org>
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 /*
24 * - Principles of Operation -
25 *
26 * The CrystalHD decoder operates at the bitstream level - which is an even
27 * higher level than the decoding hardware you typically see in modern GPUs.
28 * This means it has a very simple interface, in principle. You feed demuxed
29 * packets in one end and get decoded picture (fields/frames) out the other.
30 *
31 * Of course, nothing is ever that simple. Due, at the very least, to b-frame
32 * dependencies in the supported formats, the hardware has a delay between
33 * when a packet goes in, and when a picture comes out. Furthermore, this delay
34 * is not just a function of time, but also one of the dependency on additional
35 * frames being fed into the decoder to satisfy the b-frame dependencies.
36 *
37 * As such, the hardware can only be used effectively with a decode API that
38 * doesn't assume a 1:1 relationship between input packets and output frames.
39 * The new avcodec decode API is such an API (an m:n API) while the old one is
40 * 1:1. Consequently, we no longer support the old API, which allows us to avoid
41 * the vicious hacks that are required to approximate 1:1 operation.
42 */
43
44 /*****************************************************************************
45 * Includes
46 ****************************************************************************/
47
48 #include "config_components.h"
49
50 #define _XOPEN_SOURCE 600
51 #include <inttypes.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54
55 #include <libcrystalhd/bc_dts_types.h>
56 #include <libcrystalhd/bc_dts_defs.h>
57 #include <libcrystalhd/libcrystalhd_if.h>
58
66
67 #if HAVE_UNISTD_H
68 #include <unistd.h>
69 #endif
70
71 /** Timeout parameter passed to DtsProcOutput() in us */
72 #define OUTPUT_PROC_TIMEOUT 50
73 /** Step between fake timestamps passed to hardware in units of 100ns */
74 #define TIMESTAMP_UNIT 100000
75
76
77 /*****************************************************************************
78 * Module private data
79 ****************************************************************************/
80
92
96 /* This packet coincides with AVCodecInternal.in_pkt
97 * and is not owned by us. */
100
104
107
108 /* Options */
111
113 { "crystalhd_downscale_width",
114 "Turn on downscaling to the specified width",
119 };
120
121
122 /*****************************************************************************
123 * Helper functions
124 ****************************************************************************/
125
127 {
128 switch (id) {
130 return BC_MSUBTYPE_DIVX;
132 return BC_MSUBTYPE_DIVX311;
134 return BC_MSUBTYPE_MPEG2VIDEO;
136 return BC_MSUBTYPE_VC1;
138 return BC_MSUBTYPE_WMV3;
140 return BC_MSUBTYPE_H264;
141 default:
142 return BC_MSUBTYPE_INVALID;
143 }
144 }
145
147 {
154 output->PicInfo.timeStamp);
156 output->PicInfo.picture_number);
162 output->PicInfo.chroma_format);
164 output->PicInfo.pulldown);
168 output->PicInfo.frame_rate);
170 output->PicInfo.aspect_ratio);
172 output->PicInfo.colour_primaries);
174 output->PicInfo.picture_meta_payload);
176 output->PicInfo.sess_num);
180 output->PicInfo.custom_aspect_ratio_width_height);
184 output->PicInfo.other.h264.valid);
185 }
186
187
188 /*****************************************************************************
189 * OpaqueList functions
190 ****************************************************************************/
191
193 {
195 if (!newNode) {
197 "Unable to allocate new node in OpaqueList.\n");
198 return 0;
199 }
202 priv->
head = newNode;
203 } else {
206 }
207 priv->
tail = newNode;
209
211 }
212
213 /*
214 * The OpaqueList is built in decode order, while elements will be removed
215 * in presentation order. If frames are reordered, this means we must be
216 * able to remove elements that are not the first element.
217 *
218 * Returned node must be freed by caller.
219 */
221 {
223
226 "CrystalHD: Attempted to query non-existent timestamps.\n");
228 }
229
230 /*
231 * The first element is special-cased because we have to manipulate
232 * the head pointer rather than the previous element in the list.
233 */
236
239
241 return node;
242 }
243
244 /*
245 * The list is processed at arm's length so that we have the
246 * previous element available to rewrite its next pointer.
247 */
252
255
257 return current;
258 } else {
259 node = current;
260 }
261 }
262
264 "CrystalHD: Couldn't match fake_timestamp.\n");
266 }
267
268
269 /*****************************************************************************
270 * Video decoder API function definitions
271 ****************************************************************************/
272
274 {
276
279
280 /* Flush mode 4 flushes all software and hardware buffers. */
281 DtsFlushInput(priv->
dev, 4);
282 }
283
284
286 {
288 HANDLE device;
289
291 DtsStopDecoder(device);
292 DtsCloseDecoder(device);
293 DtsDeviceClose(device);
294
297 while (node) {
300 node = next;
301 }
302 }
303
304 return 0;
305 }
306
308 {
312 BC_INPUT_FORMAT
format = {
313 .FGTEnable = FALSE,
314 .Progressive = TRUE,
315 .OptFlags = 0x80000000 | vdecFrameRate59_94 | 0x40,
318 };
319
320 BC_MEDIA_SUBTYPE subtype;
321
322 uint32_t
mode = DTS_PLAYBACK_MODE |
323 DTS_LOAD_FILE_PLAY_FW |
324 DTS_SKIP_TX_CHK_CPB |
325 DTS_PLAYBACK_DROP_RPT_MODE |
326 DTS_SINGLE_THREADED_MODE |
327 DTS_DFLT_RESOLUTION(vdecRESOLUTION_1080p23_976);
328
331
333
334 /* Initialize the library */
339
341 switch (subtype) {
342 case BC_MSUBTYPE_H264:
344 // Fall-through
345 case BC_MSUBTYPE_VC1:
346 case BC_MSUBTYPE_WVC1:
347 case BC_MSUBTYPE_WMV3:
348 case BC_MSUBTYPE_WMVA:
349 case BC_MSUBTYPE_MPEG2VIDEO:
350 case BC_MSUBTYPE_DIVX:
351 case BC_MSUBTYPE_DIVX311:
354 break;
355 default:
358 }
359 format.mSubtype = subtype;
360
362 format.bEnableScaling = 1;
364 }
365
366 /* Get a decoder instance */
368 // Initialize the Link and Decoder devices
370 if (
ret != BC_STS_SUCCESS) {
373 }
374
376 if (
ret != BC_STS_SUCCESS) {
378 "CrystalHD: DtsCrystalHDVersion failed\n");
380 }
382
384 (subtype == BC_MSUBTYPE_DIVX || subtype == BC_MSUBTYPE_DIVX311)) {
386 "CrystalHD: BCM70012 doesn't support MPEG4-ASP/DivX/Xvid\n");
388 }
389
391 if (
ret != BC_STS_SUCCESS) {
394 }
395
396 ret = DtsOpenDecoder(priv->
dev, BC_STREAM_TYPE_ES);
397 if (
ret != BC_STS_SUCCESS) {
400 }
401
402 ret = DtsSetColorSpace(priv->
dev, OUTPUT_MODE422_YUY2);
403 if (
ret != BC_STS_SUCCESS) {
406 }
407 ret = DtsStartDecoder(priv->
dev);
408 if (
ret != BC_STS_SUCCESS) {
411 }
412 ret = DtsStartCapture(priv->
dev);
413 if (
ret != BC_STS_SUCCESS) {
416 }
417
419
420 return 0;
421
424 return -1;
425 }
426
427
431 {
433 BC_DTS_STATUS decoder_status = { 0, };
435
438
439 uint8_t bottom_field = (
output->PicInfo.flags & VDEC_FLAG_BOTTOMFIELD) ==
440 VDEC_FLAG_BOTTOMFIELD;
441 uint8_t bottom_first = !!(
output->PicInfo.flags & VDEC_FLAG_BOTTOM_FIRST);
442
445 int bwidth;
447 int sStride;
448 uint8_t *dst;
449 int dStride;
450
451 if (
output->PicInfo.timeStamp != 0) {
453 if (node) {
456 } else {
457 /*
458 * We will encounter a situation where a timestamp cannot be
459 * popped if a second field is being returned. In this case,
460 * each field has the same timestamp and the first one will
461 * cause it to be popped. We'll avoid overwriting the valid
462 * timestamp below.
463 */
464 }
466 output->PicInfo.timeStamp);
467 }
468
469 ret = DtsGetDriverStatus(priv->
dev, &decoder_status);
470 if (
ret != BC_STS_SUCCESS) {
472 "CrystalHD: GetDriverStatus failed: %u\n",
ret);
474 }
475
477
480
482
483 if (!
frame->data[0]) {
486 }
487
489 if (bwidth < 0)
491
493 int pStride;
494
496 pStride = 720;
497 else if (
width <= 1280)
498 pStride = 1280;
499 else pStride = 1920;
501 if (sStride < 0)
503 } else {
504 sStride = bwidth;
505 }
506
507 dStride =
frame->linesize[0];
508 dst =
frame->data[0];
509
511
512 /*
513 * The hardware doesn't return the first sample of a picture.
514 * Ignoring why it behaves this way, it's better to copy the sample from
515 * the second line, rather than the next sample across because the chroma
516 * values should be correct (assuming the decoded video was 4:2:0, which
517 * it was).
518 */
519 *((uint32_t *)
src) = *((uint32_t *)(
src + sStride));
520
522 int dY = 0;
523 int sY = 0;
524
526 if (bottom_field) {
528 dY = 1;
529 } else {
531 dY = 0;
532 }
533
534 for (sY = 0; sY <
height; dY++, sY++) {
535 memcpy(&(dst[dY * dStride]), &(
src[sY * sStride]), bwidth);
536 dY++;
537 }
538 } else {
540 }
541
544 frame->top_field_first = !bottom_first;
545
546 frame->pts = pkt_pts;
547
549 frame->pkt_duration = 0;
550 frame->pkt_size = -1;
551
553 *got_frame = 1;
554 } else {
556 }
557
559 }
560
561
564 {
566 BC_DTS_PROC_OUT
output = {
567 .PicInfo.width = avctx->
width,
568 .PicInfo.height = avctx->
height,
569 };
571 HANDLE dev = priv->
dev;
572
573 *got_frame = 0;
574
575 // Request decoded data from the driver
577 if (
ret == BC_STS_FMT_CHANGE) {
581 switch (
output.PicInfo.aspect_ratio ) {
582 case vdecAspectRatioSquare:
584 break;
585 case vdecAspectRatio12_11:
587 break;
588 case vdecAspectRatio10_11:
590 break;
591 case vdecAspectRatio16_11:
593 break;
594 case vdecAspectRatio40_33:
596 break;
597 case vdecAspectRatio24_11:
599 break;
600 case vdecAspectRatio20_11:
602 break;
603 case vdecAspectRatio32_11:
605 break;
606 case vdecAspectRatio80_33:
608 break;
609 case vdecAspectRatio18_11:
611 break;
612 case vdecAspectRatio15_11:
614 break;
615 case vdecAspectRatio64_33:
617 break;
618 case vdecAspectRatio160_99:
620 break;
621 case vdecAspectRatio4_3:
623 break;
624 case vdecAspectRatio16_9:
626 break;
627 case vdecAspectRatio221_1:
629 break;
630 }
632 }
else if (
ret == BC_STS_SUCCESS) {
633 int copy_ret = -1;
634 if (
output.PoutFlags & BC_POUT_FLAGS_PIB_VALID) {
636
638 } else {
639 /*
640 * An invalid frame has been consumed.
641 */
643 "invalid PIB\n");
645 }
646 DtsReleaseOutputBuffs(dev,
NULL, FALSE);
647
648 return copy_ret;
649 }
else if (
ret == BC_STS_BUSY) {
651 } else {
654 }
655 }
656
658 {
659 BC_STATUS bc_ret;
661 HANDLE dev = priv->
dev;
663
665
666 if (avpkt && avpkt->
size) {
668
669 /*
670 * Despite being notionally opaque, either libcrystalhd or
671 * the hardware itself will mangle pts values that are too
672 * small or too large. The docs claim it should be in units
673 * of 100ns. Given that we're nominally dealing with a black
674 * box on both sides, any transform we do has no guarantee of
675 * avoiding mangling so we need to build a mapping to values
676 * we know will not be mangled.
677 */
681 goto exit;
682 }
684 "input \"pts\": %"PRIu64
"\n",
pts);
685 bc_ret = DtsProcInput(dev, avpkt->
data, avpkt->
size,
pts, 0);
686 if (bc_ret == BC_STS_BUSY) {
688 "CrystalHD: ProcInput returned busy\n");
690 goto exit;
691 } else if (bc_ret != BC_STS_SUCCESS) {
693 "CrystalHD: ProcInput failed: %u\n",
ret);
695 goto exit;
696 }
697 } else {
701 goto exit;
702 }
703 exit:
705 }
706
708 {
709 BC_STATUS bc_ret;
710 BC_DTS_STATUS decoder_status = { 0, };
714 HANDLE dev = priv->
dev;
715 int got_frame = 0;
717
719
723 }
724
725 while (
pkt->
size > DtsTxFreeSize(dev)) {
726 /*
727 * Block until there is space in the buffer for the next packet.
728 * We assume that the hardware will make forward progress at this
729 * point, although in pathological cases that may not happen.
730 */
732 }
733
736 // crystalhd_is_buffer_full() should avoid this.
739 }
742 }
743
744 do {
745 bc_ret = DtsGetDriverStatus(dev, &decoder_status);
746 if (bc_ret != BC_STS_SUCCESS) {
748 return -1;
749 }
750
751 if (decoder_status.ReadyListCount == 0) {
753 got_frame = 0;
755 break;
756 }
757
760
762 return -1;
763 } else if (got_frame == 0) {
765 } else {
766 return 0;
767 }
768 }
769
770 #define DEFINE_CRYSTALHD_DECODER(x, X, bsf_name) \
771 static const AVClass x##_crystalhd_class = { \
772 .class_name = #x "_crystalhd", \
773 .item_name = av_default_item_name, \
774 .option = options, \
775 .version = LIBAVUTIL_VERSION_INT, \
776 }; \
777 const FFCodec ff_##x##_crystalhd_decoder = { \
778 .p.name = #x "_crystalhd", \
779 .p.long_name = NULL_IF_CONFIG_SMALL("CrystalHD " #X " decoder"), \
780 .p.type = AVMEDIA_TYPE_VIDEO, \
781 .p.id = AV_CODEC_ID_##X, \
782 .priv_data_size = sizeof(CHDContext), \
783 .p.priv_class = &x##_crystalhd_class, \
784 .init = init, \
785 .close = uninit, \
786 FF_CODEC_RECEIVE_FRAME_CB(crystalhd_receive_frame), \
787 .flush = flush, \
788 .bsfs = bsf_name, \
789 .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \
790 .caps_internal = FF_CODEC_CAP_SETS_FRAME_PROPS, \
791 .p.pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_YUYV422, AV_PIX_FMT_NONE}, \
792 .p.wrapper_name = "crystalhd", \
793 };
794
795 #if CONFIG_H264_CRYSTALHD_DECODER
797 #endif
798
799 #if CONFIG_MPEG2_CRYSTALHD_DECODER
801 #endif
802
803 #if CONFIG_MPEG4_CRYSTALHD_DECODER
805 #endif
806
807 #if CONFIG_MSMPEG4_CRYSTALHD_DECODER
809 #endif
810
811 #if CONFIG_VC1_CRYSTALHD_DECODER
813 #endif
814
815 #if CONFIG_WMV3_CRYSTALHD_DECODER
817 #endif