2 * - CrystalHD decoder module -
4 * Copyright(C) 2010,2011 Philip Langdale <ffmpeg.philipl@overt.org>
6 * This file is part of FFmpeg.
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.
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.
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
24 * - Principles of Operation -
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.
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.
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.
44 /*****************************************************************************
46 ****************************************************************************/
48 #include "config_components.h"
50 #define _XOPEN_SOURCE 600
55 #include <libcrystalhd/bc_dts_types.h>
56 #include <libcrystalhd/bc_dts_defs.h>
57 #include <libcrystalhd/libcrystalhd_if.h>
60 #include "codec_internal.h"
63 #include "libavutil/imgutils.h"
64 #include "libavutil/intreadwrite.h"
65 #include "libavutil/opt.h"
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
77 /*****************************************************************************
79 ****************************************************************************/
87 typedef struct OpaqueList {
88 struct OpaqueList *next;
89 uint64_t fake_timestamp;
90 uint64_t reordered_opaque;
95 AVCodecContext *avctx;
96 /* This packet coincides with AVCodecInternal.in_pkt
97 * and is not owned by us. */
102 uint8_t need_second_field;
112 static const AVOption options[] = {
113 { "crystalhd_downscale_width",
114 "Turn on downscaling to the specified width",
115 offsetof(CHDContext, sWidth),
116 AV_OPT_TYPE_INT, {.i64 = 0}, 0, UINT32_MAX,
117 AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM, },
122 /*****************************************************************************
124 ****************************************************************************/
126 static inline BC_MEDIA_SUBTYPE id2subtype(CHDContext *priv, enum AVCodecID id)
129 case AV_CODEC_ID_MPEG4:
130 return BC_MSUBTYPE_DIVX;
131 case AV_CODEC_ID_MSMPEG4V3:
132 return BC_MSUBTYPE_DIVX311;
133 case AV_CODEC_ID_MPEG2VIDEO:
134 return BC_MSUBTYPE_MPEG2VIDEO;
135 case AV_CODEC_ID_VC1:
136 return BC_MSUBTYPE_VC1;
137 case AV_CODEC_ID_WMV3:
138 return BC_MSUBTYPE_WMV3;
139 case AV_CODEC_ID_H264:
140 return BC_MSUBTYPE_H264;
142 return BC_MSUBTYPE_INVALID;
146 static inline void print_frame_info(CHDContext *priv, BC_DTS_PROC_OUT *output)
148 av_log(priv->avctx, AV_LOG_TRACE, "\tYBuffSz: %u\n", output->YbuffSz);
149 av_log(priv->avctx, AV_LOG_TRACE, "\tYBuffDoneSz: %u\n",
150 output->YBuffDoneSz);
151 av_log(priv->avctx, AV_LOG_TRACE, "\tUVBuffDoneSz: %u\n",
152 output->UVBuffDoneSz);
153 av_log(priv->avctx, AV_LOG_TRACE, "\tTimestamp: %"PRIu64"\n",
154 output->PicInfo.timeStamp);
155 av_log(priv->avctx, AV_LOG_TRACE, "\tPicture Number: %u\n",
156 output->PicInfo.picture_number);
157 av_log(priv->avctx, AV_LOG_TRACE, "\tWidth: %u\n",
158 output->PicInfo.width);
159 av_log(priv->avctx, AV_LOG_TRACE, "\tHeight: %u\n",
160 output->PicInfo.height);
161 av_log(priv->avctx, AV_LOG_TRACE, "\tChroma: 0x%03x\n",
162 output->PicInfo.chroma_format);
163 av_log(priv->avctx, AV_LOG_TRACE, "\tPulldown: %u\n",
164 output->PicInfo.pulldown);
165 av_log(priv->avctx, AV_LOG_TRACE, "\tFlags: 0x%08x\n",
166 output->PicInfo.flags);
167 av_log(priv->avctx, AV_LOG_TRACE, "\tFrame Rate/Res: %u\n",
168 output->PicInfo.frame_rate);
169 av_log(priv->avctx, AV_LOG_TRACE, "\tAspect Ratio: %u\n",
170 output->PicInfo.aspect_ratio);
171 av_log(priv->avctx, AV_LOG_TRACE, "\tColor Primaries: %u\n",
172 output->PicInfo.colour_primaries);
173 av_log(priv->avctx, AV_LOG_TRACE, "\tMetaData: %u\n",
174 output->PicInfo.picture_meta_payload);
175 av_log(priv->avctx, AV_LOG_TRACE, "\tSession Number: %u\n",
176 output->PicInfo.sess_num);
177 av_log(priv->avctx, AV_LOG_TRACE, "\tycom: %u\n",
178 output->PicInfo.ycom);
179 av_log(priv->avctx, AV_LOG_TRACE, "\tCustom Aspect: %u\n",
180 output->PicInfo.custom_aspect_ratio_width_height);
181 av_log(priv->avctx, AV_LOG_TRACE, "\tFrames to Drop: %u\n",
182 output->PicInfo.n_drop);
183 av_log(priv->avctx, AV_LOG_TRACE, "\tH264 Valid Fields: 0x%08x\n",
184 output->PicInfo.other.h264.valid);
188 /*****************************************************************************
189 * OpaqueList functions
190 ****************************************************************************/
192 static uint64_t opaque_list_push(CHDContext *priv, uint64_t reordered_opaque)
194 OpaqueList *newNode = av_mallocz(sizeof (OpaqueList));
196 av_log(priv->avctx, AV_LOG_ERROR,
197 "Unable to allocate new node in OpaqueList.\n");
201 newNode->fake_timestamp = TIMESTAMP_UNIT;
202 priv->head = newNode;
204 newNode->fake_timestamp = priv->tail->fake_timestamp + TIMESTAMP_UNIT;
205 priv->tail->next = newNode;
207 priv->tail = newNode;
208 newNode->reordered_opaque = reordered_opaque;
210 return newNode->fake_timestamp;
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.
218 * Returned node must be freed by caller.
220 static OpaqueList *opaque_list_pop(CHDContext *priv, uint64_t fake_timestamp)
222 OpaqueList *node = priv->head;
225 av_log(priv->avctx, AV_LOG_ERROR,
226 "CrystalHD: Attempted to query non-existent timestamps.\n");
231 * The first element is special-cased because we have to manipulate
232 * the head pointer rather than the previous element in the list.
234 if (priv->head->fake_timestamp == fake_timestamp) {
235 priv->head = node->next;
237 if (!priv->head->next)
238 priv->tail = priv->head;
245 * The list is processed at arm's length so that we have the
246 * previous element available to rewrite its next pointer.
249 OpaqueList *current = node->next;
250 if (current->fake_timestamp == fake_timestamp) {
251 node->next = current->next;
256 current->next = NULL;
263 av_log(priv->avctx, AV_LOG_VERBOSE,
264 "CrystalHD: Couldn't match fake_timestamp.\n");
269 /*****************************************************************************
270 * Video decoder API function definitions
271 ****************************************************************************/
273 static void flush(AVCodecContext *avctx)
275 CHDContext *priv = avctx->priv_data;
277 priv->need_second_field = 0;
280 /* Flush mode 4 flushes all software and hardware buffers. */
281 DtsFlushInput(priv->dev, 4);
285 static av_cold int uninit(AVCodecContext *avctx)
287 CHDContext *priv = avctx->priv_data;
291 DtsStopDecoder(device);
292 DtsCloseDecoder(device);
293 DtsDeviceClose(device);
296 OpaqueList *node = priv->head;
298 OpaqueList *next = node->next;
307 static av_cold int init(AVCodecContext *avctx)
311 BC_INFO_CRYSTAL version;
312 BC_INPUT_FORMAT format = {
315 .OptFlags = 0x80000000 | vdecFrameRate59_94 | 0x40,
316 .width = avctx->width,
317 .height = avctx->height,
320 BC_MEDIA_SUBTYPE subtype;
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);
329 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD Init for %s\n",
332 av_log(avctx, AV_LOG_WARNING, "CrystalHD support is deprecated and will "
333 "be removed. Please contact the developers if you are interested in "
334 "maintaining it.\n");
336 avctx->pix_fmt = AV_PIX_FMT_YUYV422;
338 /* Initialize the library */
339 priv = avctx->priv_data;
341 priv->pkt = avctx->internal->in_pkt;
344 subtype = id2subtype(priv, avctx->codec->id);
346 case BC_MSUBTYPE_H264:
347 format.startCodeSz = 4;
349 case BC_MSUBTYPE_VC1:
350 case BC_MSUBTYPE_WVC1:
351 case BC_MSUBTYPE_WMV3:
352 case BC_MSUBTYPE_WMVA:
353 case BC_MSUBTYPE_MPEG2VIDEO:
354 case BC_MSUBTYPE_DIVX:
355 case BC_MSUBTYPE_DIVX311:
356 format.pMetaData = avctx->extradata;
357 format.metaDataSz = avctx->extradata_size;
360 av_log(avctx, AV_LOG_ERROR, "CrystalHD: Unknown codec name\n");
361 return AVERROR(EINVAL);
363 format.mSubtype = subtype;
366 format.bEnableScaling = 1;
367 format.ScalingParams.sWidth = priv->sWidth;
370 /* Get a decoder instance */
371 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: starting up\n");
372 // Initialize the Link and Decoder devices
373 ret = DtsDeviceOpen(&priv->dev, mode);
374 if (ret != BC_STS_SUCCESS) {
375 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: DtsDeviceOpen failed\n");
379 ret = DtsCrystalHDVersion(priv->dev, &version);
380 if (ret != BC_STS_SUCCESS) {
381 av_log(avctx, AV_LOG_VERBOSE,
382 "CrystalHD: DtsCrystalHDVersion failed\n");
385 priv->is_70012 = version.device == 0;
387 if (priv->is_70012 &&
388 (subtype == BC_MSUBTYPE_DIVX || subtype == BC_MSUBTYPE_DIVX311)) {
389 av_log(avctx, AV_LOG_VERBOSE,
390 "CrystalHD: BCM70012 doesn't support MPEG4-ASP/DivX/Xvid\n");
394 ret = DtsSetInputFormat(priv->dev, &format);
395 if (ret != BC_STS_SUCCESS) {
396 av_log(avctx, AV_LOG_ERROR, "CrystalHD: SetInputFormat failed\n");
400 ret = DtsOpenDecoder(priv->dev, BC_STREAM_TYPE_ES);
401 if (ret != BC_STS_SUCCESS) {
402 av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsOpenDecoder failed\n");
406 ret = DtsSetColorSpace(priv->dev, OUTPUT_MODE422_YUY2);
407 if (ret != BC_STS_SUCCESS) {
408 av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsSetColorSpace failed\n");
411 ret = DtsStartDecoder(priv->dev);
412 if (ret != BC_STS_SUCCESS) {
413 av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsStartDecoder failed\n");
416 ret = DtsStartCapture(priv->dev);
417 if (ret != BC_STS_SUCCESS) {
418 av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsStartCapture failed\n");
422 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Init complete.\n");
432 static inline CopyRet copy_frame(AVCodecContext *avctx,
433 BC_DTS_PROC_OUT *output,
434 AVFrame *frame, int *got_frame)
437 BC_DTS_STATUS decoder_status = { 0, };
440 CHDContext *priv = avctx->priv_data;
441 int64_t pkt_pts = AV_NOPTS_VALUE;
443 uint8_t bottom_field = (output->PicInfo.flags & VDEC_FLAG_BOTTOMFIELD) ==
444 VDEC_FLAG_BOTTOMFIELD;
445 uint8_t bottom_first = !!(output->PicInfo.flags & VDEC_FLAG_BOTTOM_FIRST);
447 int width = output->PicInfo.width;
448 int height = output->PicInfo.height;
450 uint8_t *src = output->Ybuff;
455 if (output->PicInfo.timeStamp != 0) {
456 OpaqueList *node = opaque_list_pop(priv, output->PicInfo.timeStamp);
458 pkt_pts = node->reordered_opaque;
462 * We will encounter a situation where a timestamp cannot be
463 * popped if a second field is being returned. In this case,
464 * each field has the same timestamp and the first one will
465 * cause it to be popped. We'll avoid overwriting the valid
469 av_log(avctx, AV_LOG_VERBOSE, "output \"pts\": %"PRIu64"\n",
470 output->PicInfo.timeStamp);
473 ret = DtsGetDriverStatus(priv->dev, &decoder_status);
474 if (ret != BC_STS_SUCCESS) {
475 av_log(avctx, AV_LOG_ERROR,
476 "CrystalHD: GetDriverStatus failed: %u\n", ret);
480 interlaced = output->PicInfo.flags & VDEC_FLAG_INTERLACED_SRC;
482 av_log(avctx, AV_LOG_VERBOSE, "Interlaced state: %d\n",
485 priv->need_second_field = interlaced && !priv->need_second_field;
487 if (!frame->data[0]) {
488 if (ff_get_buffer(avctx, frame, 0) < 0)
492 bwidth = av_image_get_linesize(avctx->pix_fmt, width, 0);
496 if (priv->is_70012) {
501 else if (width <= 1280)
504 sStride = av_image_get_linesize(avctx->pix_fmt, pStride, 0);
511 dStride = frame->linesize[0];
512 dst = frame->data[0];
514 av_log(priv->avctx, AV_LOG_VERBOSE, "CrystalHD: Copying out frame\n");
517 * The hardware doesn't return the first sample of a picture.
518 * Ignoring why it behaves this way, it's better to copy the sample from
519 * the second line, rather than the next sample across because the chroma
520 * values should be correct (assuming the decoded video was 4:2:0, which
523 *((uint32_t *)src) = *((uint32_t *)(src + sStride));
531 av_log(priv->avctx, AV_LOG_VERBOSE, "Interlaced: bottom field\n");
534 av_log(priv->avctx, AV_LOG_VERBOSE, "Interlaced: top field\n");
538 for (sY = 0; sY < height; dY++, sY++) {
539 memcpy(&(dst[dY * dStride]), &(src[sY * sStride]), bwidth);
543 av_image_copy_plane(dst, dStride, src, sStride, bwidth, height);
546 frame->flags |= AV_FRAME_FLAG_INTERLACED * !!interlaced;
548 frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST * !bottom_first;
550 frame->pts = pkt_pts;
554 FF_DISABLE_DEPRECATION_WARNINGS
556 frame->pkt_size = -1;
557 FF_ENABLE_DEPRECATION_WARNINGS
560 if (!priv->need_second_field) {
563 return RET_COPY_AGAIN;
570 static inline CopyRet receive_frame(AVCodecContext *avctx,
571 AVFrame *frame, int *got_frame)
574 BC_DTS_PROC_OUT output = {
575 .PicInfo.width = avctx->width,
576 .PicInfo.height = avctx->height,
578 CHDContext *priv = avctx->priv_data;
579 HANDLE dev = priv->dev;
583 // Request decoded data from the driver
584 ret = DtsProcOutputNoCopy(dev, OUTPUT_PROC_TIMEOUT, &output);
585 if (ret == BC_STS_FMT_CHANGE) {
586 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Initial format change\n");
587 avctx->width = output.PicInfo.width;
588 avctx->height = output.PicInfo.height;
589 switch ( output.PicInfo.aspect_ratio ) {
590 case vdecAspectRatioSquare:
591 avctx->sample_aspect_ratio = (AVRational) { 1, 1};
593 case vdecAspectRatio12_11:
594 avctx->sample_aspect_ratio = (AVRational) { 12, 11};
596 case vdecAspectRatio10_11:
597 avctx->sample_aspect_ratio = (AVRational) { 10, 11};
599 case vdecAspectRatio16_11:
600 avctx->sample_aspect_ratio = (AVRational) { 16, 11};
602 case vdecAspectRatio40_33:
603 avctx->sample_aspect_ratio = (AVRational) { 40, 33};
605 case vdecAspectRatio24_11:
606 avctx->sample_aspect_ratio = (AVRational) { 24, 11};
608 case vdecAspectRatio20_11:
609 avctx->sample_aspect_ratio = (AVRational) { 20, 11};
611 case vdecAspectRatio32_11:
612 avctx->sample_aspect_ratio = (AVRational) { 32, 11};
614 case vdecAspectRatio80_33:
615 avctx->sample_aspect_ratio = (AVRational) { 80, 33};
617 case vdecAspectRatio18_11:
618 avctx->sample_aspect_ratio = (AVRational) { 18, 11};
620 case vdecAspectRatio15_11:
621 avctx->sample_aspect_ratio = (AVRational) { 15, 11};
623 case vdecAspectRatio64_33:
624 avctx->sample_aspect_ratio = (AVRational) { 64, 33};
626 case vdecAspectRatio160_99:
627 avctx->sample_aspect_ratio = (AVRational) {160, 99};
629 case vdecAspectRatio4_3:
630 avctx->sample_aspect_ratio = (AVRational) { 4, 3};
632 case vdecAspectRatio16_9:
633 avctx->sample_aspect_ratio = (AVRational) { 16, 9};
635 case vdecAspectRatio221_1:
636 avctx->sample_aspect_ratio = (AVRational) {221, 1};
639 return RET_COPY_AGAIN;
640 } else if (ret == BC_STS_SUCCESS) {
642 if (output.PoutFlags & BC_POUT_FLAGS_PIB_VALID) {
643 print_frame_info(priv, &output);
645 copy_ret = copy_frame(avctx, &output, frame, got_frame);
648 * An invalid frame has been consumed.
650 av_log(avctx, AV_LOG_ERROR, "CrystalHD: ProcOutput succeeded with "
652 copy_ret = RET_COPY_AGAIN;
654 DtsReleaseOutputBuffs(dev, NULL, FALSE);
657 } else if (ret == BC_STS_BUSY) {
658 return RET_COPY_AGAIN;
660 av_log(avctx, AV_LOG_ERROR, "CrystalHD: ProcOutput failed %d\n", ret);
665 static int crystalhd_decode_packet(AVCodecContext *avctx, const AVPacket *avpkt)
668 CHDContext *priv = avctx->priv_data;
669 HANDLE dev = priv->dev;
672 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: decode_packet\n");
674 if (avpkt && avpkt->size) {
678 * Despite being notionally opaque, either libcrystalhd or
679 * the hardware itself will mangle pts values that are too
680 * small or too large. The docs claim it should be in units
681 * of 100ns. Given that we're nominally dealing with a black
682 * box on both sides, any transform we do has no guarantee of
683 * avoiding mangling so we need to build a mapping to values
684 * we know will not be mangled.
686 pts = opaque_list_push(priv, avpkt->pts);
688 ret = AVERROR(ENOMEM);
691 av_log(priv->avctx, AV_LOG_VERBOSE,
692 "input \"pts\": %"PRIu64"\n", pts);
693 bc_ret = DtsProcInput(dev, avpkt->data, avpkt->size, pts, 0);
694 if (bc_ret == BC_STS_BUSY) {
695 av_log(avctx, AV_LOG_WARNING,
696 "CrystalHD: ProcInput returned busy\n");
697 ret = AVERROR(EAGAIN);
699 } else if (bc_ret != BC_STS_SUCCESS) {
700 av_log(avctx, AV_LOG_ERROR,
701 "CrystalHD: ProcInput failed: %u\n", ret);
706 av_log(avctx, AV_LOG_INFO, "CrystalHD: No more input data\n");
715 static int crystalhd_receive_frame(AVCodecContext *avctx, AVFrame *frame)
718 BC_DTS_STATUS decoder_status = { 0, };
720 CHDContext *priv = avctx->priv_data;
721 AVPacket *const pkt = priv->pkt;
722 HANDLE dev = priv->dev;
726 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: receive_frame\n");
728 ret = ff_decode_get_packet(avctx, pkt);
729 if (ret < 0 && ret != AVERROR_EOF) {
733 while (pkt->size > DtsTxFreeSize(dev)) {
735 * Block until there is space in the buffer for the next packet.
736 * We assume that the hardware will make forward progress at this
737 * point, although in pathological cases that may not happen.
739 av_log(avctx, AV_LOG_TRACE, "CrystalHD: Waiting for space in input buffer\n");
742 ret = crystalhd_decode_packet(avctx, pkt);
743 av_packet_unref(pkt);
744 // crystalhd_is_buffer_full() should avoid this.
745 if (ret == AVERROR(EAGAIN)) {
746 ret = AVERROR_EXTERNAL;
748 if (ret < 0 && ret != AVERROR_EOF) {
753 bc_ret = DtsGetDriverStatus(dev, &decoder_status);
754 if (bc_ret != BC_STS_SUCCESS) {
755 av_log(avctx, AV_LOG_ERROR, "CrystalHD: GetDriverStatus failed\n");
759 if (decoder_status.ReadyListCount == 0) {
760 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Insufficient frames ready. Returning\n");
766 rec_ret = receive_frame(avctx, frame, &got_frame);
767 } while (rec_ret == RET_COPY_AGAIN);
769 if (rec_ret == RET_ERROR) {
771 } else if (got_frame == 0) {
772 return priv->draining ? AVERROR_EOF : AVERROR(EAGAIN);
778 #define DEFINE_CRYSTALHD_DECODER(x, X, bsf_name) \
779 static const AVClass x##_crystalhd_class = { \
780 .class_name = #x "_crystalhd", \
781 .item_name = av_default_item_name, \
783 .version = LIBAVUTIL_VERSION_INT, \
785 const FFCodec ff_##x##_crystalhd_decoder = { \
786 .p.name = #x "_crystalhd", \
787 CODEC_LONG_NAME("CrystalHD " #X " decoder"), \
788 .p.type = AVMEDIA_TYPE_VIDEO, \
789 .p.id = AV_CODEC_ID_##X, \
790 .priv_data_size = sizeof(CHDContext), \
791 .p.priv_class = &x##_crystalhd_class, \
794 FF_CODEC_RECEIVE_FRAME_CB(crystalhd_receive_frame), \
797 .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \
798 .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | \
799 FF_CODEC_CAP_SETS_FRAME_PROPS, \
800 .p.pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_YUYV422, AV_PIX_FMT_NONE}, \
801 .p.wrapper_name = "crystalhd", \
804 #if CONFIG_H264_CRYSTALHD_DECODER
805 DEFINE_CRYSTALHD_DECODER(h264, H264, "h264_mp4toannexb")
808 #if CONFIG_MPEG2_CRYSTALHD_DECODER
809 DEFINE_CRYSTALHD_DECODER(mpeg2, MPEG2VIDEO, NULL)
812 #if CONFIG_MPEG4_CRYSTALHD_DECODER
813 DEFINE_CRYSTALHD_DECODER(mpeg4, MPEG4, "mpeg4_unpack_bframes")
816 #if CONFIG_MSMPEG4_CRYSTALHD_DECODER
817 DEFINE_CRYSTALHD_DECODER(msmpeg4, MSMPEG4V3, NULL)
820 #if CONFIG_VC1_CRYSTALHD_DECODER
821 DEFINE_CRYSTALHD_DECODER(vc1, VC1, NULL)
824 #if CONFIG_WMV3_CRYSTALHD_DECODER
825 DEFINE_CRYSTALHD_DECODER(wmv3, WMV3, NULL)