]> git.sesse.net Git - ffmpeg/blob - libavcodec/crystalhd.c
8ccd6ff8bd5294c4625a24bdb83c9c5d547133ff
[ffmpeg] / libavcodec / crystalhd.c
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 #define _XOPEN_SOURCE 600
49 #include <inttypes.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52
53 #include <libcrystalhd/bc_dts_types.h>
54 #include <libcrystalhd/bc_dts_defs.h>
55 #include <libcrystalhd/libcrystalhd_if.h>
56
57 #include "avcodec.h"
58 #include "decode.h"
59 #include "internal.h"
60 #include "libavutil/imgutils.h"
61 #include "libavutil/intreadwrite.h"
62 #include "libavutil/opt.h"
63
64 #if HAVE_UNISTD_H
65 #include <unistd.h>
66 #endif
67
68 /** Timeout parameter passed to DtsProcOutput() in us */
69 #define OUTPUT_PROC_TIMEOUT 50
70 /** Step between fake timestamps passed to hardware in units of 100ns */
71 #define TIMESTAMP_UNIT 100000
72
73
74 /*****************************************************************************
75  * Module private data
76  ****************************************************************************/
77
78 typedef enum {
79     RET_ERROR           = -1,
80     RET_OK              = 0,
81     RET_COPY_AGAIN      = 1,
82 } CopyRet;
83
84 typedef struct OpaqueList {
85     struct OpaqueList *next;
86     uint64_t fake_timestamp;
87     uint64_t reordered_opaque;
88 } OpaqueList;
89
90 typedef struct {
91     AVClass *av_class;
92     AVCodecContext *avctx;
93     HANDLE dev;
94
95     uint8_t *orig_extradata;
96     uint32_t orig_extradata_size;
97
98     AVBSFContext *bsfc;
99
100     uint8_t is_70012;
101     uint8_t *sps_pps_buf;
102     uint32_t sps_pps_size;
103     uint8_t is_nal;
104     uint8_t need_second_field;
105     uint8_t draining;
106
107     OpaqueList *head;
108     OpaqueList *tail;
109
110     /* Options */
111     uint32_t sWidth;
112     uint8_t bframe_bug;
113 } CHDContext;
114
115 static const AVOption options[] = {
116     { "crystalhd_downscale_width",
117       "Turn on downscaling to the specified width",
118       offsetof(CHDContext, sWidth),
119       AV_OPT_TYPE_INT, {.i64 = 0}, 0, UINT32_MAX,
120       AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM, },
121     { NULL, },
122 };
123
124
125 /*****************************************************************************
126  * Helper functions
127  ****************************************************************************/
128
129 static inline BC_MEDIA_SUBTYPE id2subtype(CHDContext *priv, enum AVCodecID id)
130 {
131     switch (id) {
132     case AV_CODEC_ID_MPEG4:
133         return BC_MSUBTYPE_DIVX;
134     case AV_CODEC_ID_MSMPEG4V3:
135         return BC_MSUBTYPE_DIVX311;
136     case AV_CODEC_ID_MPEG2VIDEO:
137         return BC_MSUBTYPE_MPEG2VIDEO;
138     case AV_CODEC_ID_VC1:
139         return BC_MSUBTYPE_VC1;
140     case AV_CODEC_ID_WMV3:
141         return BC_MSUBTYPE_WMV3;
142     case AV_CODEC_ID_H264:
143         return priv->is_nal ? BC_MSUBTYPE_AVC1 : BC_MSUBTYPE_H264;
144     default:
145         return BC_MSUBTYPE_INVALID;
146     }
147 }
148
149 static inline void print_frame_info(CHDContext *priv, BC_DTS_PROC_OUT *output)
150 {
151     av_log(priv->avctx, AV_LOG_TRACE, "\tYBuffSz: %u\n", output->YbuffSz);
152     av_log(priv->avctx, AV_LOG_TRACE, "\tYBuffDoneSz: %u\n",
153            output->YBuffDoneSz);
154     av_log(priv->avctx, AV_LOG_TRACE, "\tUVBuffDoneSz: %u\n",
155            output->UVBuffDoneSz);
156     av_log(priv->avctx, AV_LOG_TRACE, "\tTimestamp: %"PRIu64"\n",
157            output->PicInfo.timeStamp);
158     av_log(priv->avctx, AV_LOG_TRACE, "\tPicture Number: %u\n",
159            output->PicInfo.picture_number);
160     av_log(priv->avctx, AV_LOG_TRACE, "\tWidth: %u\n",
161            output->PicInfo.width);
162     av_log(priv->avctx, AV_LOG_TRACE, "\tHeight: %u\n",
163            output->PicInfo.height);
164     av_log(priv->avctx, AV_LOG_TRACE, "\tChroma: 0x%03x\n",
165            output->PicInfo.chroma_format);
166     av_log(priv->avctx, AV_LOG_TRACE, "\tPulldown: %u\n",
167            output->PicInfo.pulldown);
168     av_log(priv->avctx, AV_LOG_TRACE, "\tFlags: 0x%08x\n",
169            output->PicInfo.flags);
170     av_log(priv->avctx, AV_LOG_TRACE, "\tFrame Rate/Res: %u\n",
171            output->PicInfo.frame_rate);
172     av_log(priv->avctx, AV_LOG_TRACE, "\tAspect Ratio: %u\n",
173            output->PicInfo.aspect_ratio);
174     av_log(priv->avctx, AV_LOG_TRACE, "\tColor Primaries: %u\n",
175            output->PicInfo.colour_primaries);
176     av_log(priv->avctx, AV_LOG_TRACE, "\tMetaData: %u\n",
177            output->PicInfo.picture_meta_payload);
178     av_log(priv->avctx, AV_LOG_TRACE, "\tSession Number: %u\n",
179            output->PicInfo.sess_num);
180     av_log(priv->avctx, AV_LOG_TRACE, "\tycom: %u\n",
181            output->PicInfo.ycom);
182     av_log(priv->avctx, AV_LOG_TRACE, "\tCustom Aspect: %u\n",
183            output->PicInfo.custom_aspect_ratio_width_height);
184     av_log(priv->avctx, AV_LOG_TRACE, "\tFrames to Drop: %u\n",
185            output->PicInfo.n_drop);
186     av_log(priv->avctx, AV_LOG_TRACE, "\tH264 Valid Fields: 0x%08x\n",
187            output->PicInfo.other.h264.valid);
188 }
189
190
191 /*****************************************************************************
192  * OpaqueList functions
193  ****************************************************************************/
194
195 static uint64_t opaque_list_push(CHDContext *priv, uint64_t reordered_opaque)
196 {
197     OpaqueList *newNode = av_mallocz(sizeof (OpaqueList));
198     if (!newNode) {
199         av_log(priv->avctx, AV_LOG_ERROR,
200                "Unable to allocate new node in OpaqueList.\n");
201         return 0;
202     }
203     if (!priv->head) {
204         newNode->fake_timestamp = TIMESTAMP_UNIT;
205         priv->head              = newNode;
206     } else {
207         newNode->fake_timestamp = priv->tail->fake_timestamp + TIMESTAMP_UNIT;
208         priv->tail->next        = newNode;
209     }
210     priv->tail = newNode;
211     newNode->reordered_opaque = reordered_opaque;
212
213     return newNode->fake_timestamp;
214 }
215
216 /*
217  * The OpaqueList is built in decode order, while elements will be removed
218  * in presentation order. If frames are reordered, this means we must be
219  * able to remove elements that are not the first element.
220  *
221  * Returned node must be freed by caller.
222  */
223 static OpaqueList *opaque_list_pop(CHDContext *priv, uint64_t fake_timestamp)
224 {
225     OpaqueList *node = priv->head;
226
227     if (!priv->head) {
228         av_log(priv->avctx, AV_LOG_ERROR,
229                "CrystalHD: Attempted to query non-existent timestamps.\n");
230         return NULL;
231     }
232
233     /*
234      * The first element is special-cased because we have to manipulate
235      * the head pointer rather than the previous element in the list.
236      */
237     if (priv->head->fake_timestamp == fake_timestamp) {
238         priv->head = node->next;
239
240         if (!priv->head->next)
241             priv->tail = priv->head;
242
243         node->next = NULL;
244         return node;
245     }
246
247     /*
248      * The list is processed at arm's length so that we have the
249      * previous element available to rewrite its next pointer.
250      */
251     while (node->next) {
252         OpaqueList *current = node->next;
253         if (current->fake_timestamp == fake_timestamp) {
254             node->next = current->next;
255
256             if (!node->next)
257                priv->tail = node;
258
259             current->next = NULL;
260             return current;
261         } else {
262             node = current;
263         }
264     }
265
266     av_log(priv->avctx, AV_LOG_VERBOSE,
267            "CrystalHD: Couldn't match fake_timestamp.\n");
268     return NULL;
269 }
270
271
272 /*****************************************************************************
273  * Video decoder API function definitions
274  ****************************************************************************/
275
276 static void flush(AVCodecContext *avctx)
277 {
278     CHDContext *priv = avctx->priv_data;
279
280     priv->need_second_field = 0;
281     priv->draining          = 0;
282
283     /* Flush mode 4 flushes all software and hardware buffers. */
284     DtsFlushInput(priv->dev, 4);
285 }
286
287
288 static av_cold int uninit(AVCodecContext *avctx)
289 {
290     CHDContext *priv = avctx->priv_data;
291     HANDLE device;
292
293     device = priv->dev;
294     DtsStopDecoder(device);
295     DtsCloseDecoder(device);
296     DtsDeviceClose(device);
297
298     /*
299      * Restore original extradata, so that if the decoder is
300      * reinitialised, the bitstream detection and filtering
301      * will work as expected.
302      */
303     if (priv->orig_extradata) {
304         av_free(avctx->extradata);
305         avctx->extradata = priv->orig_extradata;
306         avctx->extradata_size = priv->orig_extradata_size;
307         priv->orig_extradata = NULL;
308         priv->orig_extradata_size = 0;
309     }
310
311     if (priv->bsfc) {
312         av_bsf_free(&priv->bsfc);
313     }
314
315     av_freep(&priv->sps_pps_buf);
316
317     if (priv->head) {
318        OpaqueList *node = priv->head;
319        while (node) {
320           OpaqueList *next = node->next;
321           av_free(node);
322           node = next;
323        }
324     }
325
326     return 0;
327 }
328
329
330 static av_cold int init_bsf(AVCodecContext *avctx, const char *bsf_name)
331 {
332     CHDContext *priv = avctx->priv_data;
333     const AVBitStreamFilter *bsf;
334     int avret;
335     void *extradata = NULL;
336     size_t size = 0;
337
338     bsf = av_bsf_get_by_name(bsf_name);
339     if (!bsf) {
340         av_log(avctx, AV_LOG_ERROR,
341                "Cannot open the %s BSF!\n", bsf_name);
342         return AVERROR_BSF_NOT_FOUND;
343     }
344
345     avret = av_bsf_alloc(bsf, &priv->bsfc);
346     if (avret != 0) {
347         return avret;
348     }
349
350     avret = avcodec_parameters_from_context(priv->bsfc->par_in, avctx);
351     if (avret != 0) {
352         return avret;
353     }
354
355     avret = av_bsf_init(priv->bsfc);
356     if (avret != 0) {
357         return avret;
358     }
359
360     /* Back up the extradata so it can be restored at close time. */
361     priv->orig_extradata = avctx->extradata;
362     priv->orig_extradata_size = avctx->extradata_size;
363
364     size = priv->bsfc->par_out->extradata_size;
365     extradata = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
366     if (!extradata) {
367         av_log(avctx, AV_LOG_ERROR,
368                "Failed to allocate copy of extradata\n");
369         return AVERROR(ENOMEM);
370     }
371     memcpy(extradata, priv->bsfc->par_out->extradata, size);
372
373     avctx->extradata = extradata;
374     avctx->extradata_size = size;
375
376     return 0;
377 }
378
379 static av_cold int init(AVCodecContext *avctx)
380 {
381     CHDContext* priv;
382     int avret;
383     BC_STATUS ret;
384     BC_INFO_CRYSTAL version;
385     BC_INPUT_FORMAT format = {
386         .FGTEnable   = FALSE,
387         .Progressive = TRUE,
388         .OptFlags    = 0x80000000 | vdecFrameRate59_94 | 0x40,
389         .width       = avctx->width,
390         .height      = avctx->height,
391     };
392
393     BC_MEDIA_SUBTYPE subtype;
394
395     uint32_t mode = DTS_PLAYBACK_MODE |
396                     DTS_LOAD_FILE_PLAY_FW |
397                     DTS_SKIP_TX_CHK_CPB |
398                     DTS_PLAYBACK_DROP_RPT_MODE |
399                     DTS_SINGLE_THREADED_MODE |
400                     DTS_DFLT_RESOLUTION(vdecRESOLUTION_1080p23_976);
401
402     av_log(avctx, AV_LOG_VERBOSE, "CrystalHD Init for %s\n",
403            avctx->codec->name);
404
405     avctx->pix_fmt = AV_PIX_FMT_YUYV422;
406
407     /* Initialize the library */
408     priv               = avctx->priv_data;
409     priv->avctx        = avctx;
410     priv->is_nal       = avctx->extradata_size > 0 && *(avctx->extradata) == 1;
411     priv->draining     = 0;
412
413     subtype = id2subtype(priv, avctx->codec->id);
414     switch (subtype) {
415     case BC_MSUBTYPE_AVC1:
416         avret = init_bsf(avctx, "h264_mp4toannexb");
417         if (avret != 0) {
418             return avret;
419         }
420         subtype = BC_MSUBTYPE_H264;
421         format.startCodeSz = 4;
422         format.pMetaData  = avctx->extradata;
423         format.metaDataSz = avctx->extradata_size;
424         break;
425     case BC_MSUBTYPE_H264:
426         format.startCodeSz = 4;
427         // Fall-through
428     case BC_MSUBTYPE_VC1:
429     case BC_MSUBTYPE_WVC1:
430     case BC_MSUBTYPE_WMV3:
431     case BC_MSUBTYPE_WMVA:
432     case BC_MSUBTYPE_MPEG2VIDEO:
433     case BC_MSUBTYPE_DIVX:
434     case BC_MSUBTYPE_DIVX311:
435         format.pMetaData  = avctx->extradata;
436         format.metaDataSz = avctx->extradata_size;
437         break;
438     default:
439         av_log(avctx, AV_LOG_ERROR, "CrystalHD: Unknown codec name\n");
440         return AVERROR(EINVAL);
441     }
442     format.mSubtype = subtype;
443
444     if (priv->sWidth) {
445         format.bEnableScaling = 1;
446         format.ScalingParams.sWidth = priv->sWidth;
447     }
448
449     /* Get a decoder instance */
450     av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: starting up\n");
451     // Initialize the Link and Decoder devices
452     ret = DtsDeviceOpen(&priv->dev, mode);
453     if (ret != BC_STS_SUCCESS) {
454         av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: DtsDeviceOpen failed\n");
455         goto fail;
456     }
457
458     ret = DtsCrystalHDVersion(priv->dev, &version);
459     if (ret != BC_STS_SUCCESS) {
460         av_log(avctx, AV_LOG_VERBOSE,
461                "CrystalHD: DtsCrystalHDVersion failed\n");
462         goto fail;
463     }
464     priv->is_70012 = version.device == 0;
465
466     if (priv->is_70012 &&
467         (subtype == BC_MSUBTYPE_DIVX || subtype == BC_MSUBTYPE_DIVX311)) {
468         av_log(avctx, AV_LOG_VERBOSE,
469                "CrystalHD: BCM70012 doesn't support MPEG4-ASP/DivX/Xvid\n");
470         goto fail;
471     }
472
473     ret = DtsSetInputFormat(priv->dev, &format);
474     if (ret != BC_STS_SUCCESS) {
475         av_log(avctx, AV_LOG_ERROR, "CrystalHD: SetInputFormat failed\n");
476         goto fail;
477     }
478
479     ret = DtsOpenDecoder(priv->dev, BC_STREAM_TYPE_ES);
480     if (ret != BC_STS_SUCCESS) {
481         av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsOpenDecoder failed\n");
482         goto fail;
483     }
484
485     ret = DtsSetColorSpace(priv->dev, OUTPUT_MODE422_YUY2);
486     if (ret != BC_STS_SUCCESS) {
487         av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsSetColorSpace failed\n");
488         goto fail;
489     }
490     ret = DtsStartDecoder(priv->dev);
491     if (ret != BC_STS_SUCCESS) {
492         av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsStartDecoder failed\n");
493         goto fail;
494     }
495     ret = DtsStartCapture(priv->dev);
496     if (ret != BC_STS_SUCCESS) {
497         av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsStartCapture failed\n");
498         goto fail;
499     }
500
501     av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Init complete.\n");
502
503     return 0;
504
505  fail:
506     uninit(avctx);
507     return -1;
508 }
509
510
511 static inline CopyRet copy_frame(AVCodecContext *avctx,
512                                  BC_DTS_PROC_OUT *output,
513                                  AVFrame *frame, int *got_frame)
514 {
515     BC_STATUS ret;
516     BC_DTS_STATUS decoder_status = { 0, };
517     uint8_t interlaced;
518
519     CHDContext *priv = avctx->priv_data;
520     int64_t pkt_pts  = AV_NOPTS_VALUE;
521
522     uint8_t bottom_field = (output->PicInfo.flags & VDEC_FLAG_BOTTOMFIELD) ==
523                            VDEC_FLAG_BOTTOMFIELD;
524     uint8_t bottom_first = !!(output->PicInfo.flags & VDEC_FLAG_BOTTOM_FIRST);
525
526     int width    = output->PicInfo.width;
527     int height   = output->PicInfo.height;
528     int bwidth;
529     uint8_t *src = output->Ybuff;
530     int sStride;
531     uint8_t *dst;
532     int dStride;
533
534     if (output->PicInfo.timeStamp != 0) {
535         OpaqueList *node = opaque_list_pop(priv, output->PicInfo.timeStamp);
536         if (node) {
537             pkt_pts = node->reordered_opaque;
538             av_free(node);
539         } else {
540             /*
541              * We will encounter a situation where a timestamp cannot be
542              * popped if a second field is being returned. In this case,
543              * each field has the same timestamp and the first one will
544              * cause it to be popped. We'll avoid overwriting the valid
545              * timestamp below.
546              */
547         }
548         av_log(avctx, AV_LOG_VERBOSE, "output \"pts\": %"PRIu64"\n",
549                output->PicInfo.timeStamp);
550     }
551
552     ret = DtsGetDriverStatus(priv->dev, &decoder_status);
553     if (ret != BC_STS_SUCCESS) {
554         av_log(avctx, AV_LOG_ERROR,
555                "CrystalHD: GetDriverStatus failed: %u\n", ret);
556        return RET_ERROR;
557     }
558
559     interlaced = output->PicInfo.flags & VDEC_FLAG_INTERLACED_SRC;
560
561     av_log(avctx, AV_LOG_VERBOSE, "Interlaced state: %d\n",
562            interlaced);
563
564     priv->need_second_field = interlaced && !priv->need_second_field;
565
566     if (!frame->data[0]) {
567         if (ff_get_buffer(avctx, frame, 0) < 0)
568             return RET_ERROR;
569     }
570
571     bwidth = av_image_get_linesize(avctx->pix_fmt, width, 0);
572     if (bwidth < 0)
573        return RET_ERROR;
574
575     if (priv->is_70012) {
576         int pStride;
577
578         if (width <= 720)
579             pStride = 720;
580         else if (width <= 1280)
581             pStride = 1280;
582         else pStride = 1920;
583         sStride = av_image_get_linesize(avctx->pix_fmt, pStride, 0);
584         if (sStride < 0)
585             return RET_ERROR;
586     } else {
587         sStride = bwidth;
588     }
589
590     dStride = frame->linesize[0];
591     dst     = frame->data[0];
592
593     av_log(priv->avctx, AV_LOG_VERBOSE, "CrystalHD: Copying out frame\n");
594
595     /*
596      * The hardware doesn't return the first sample of a picture.
597      * Ignoring why it behaves this way, it's better to copy the sample from
598      * the second line, rather than the next sample across because the chroma
599      * values should be correct (assuming the decoded video was 4:2:0, which
600      * it was).
601      */
602     *((uint32_t *)src) = *((uint32_t *)(src + sStride));
603
604     if (interlaced) {
605         int dY = 0;
606         int sY = 0;
607
608         height /= 2;
609         if (bottom_field) {
610             av_log(priv->avctx, AV_LOG_VERBOSE, "Interlaced: bottom field\n");
611             dY = 1;
612         } else {
613             av_log(priv->avctx, AV_LOG_VERBOSE, "Interlaced: top field\n");
614             dY = 0;
615         }
616
617         for (sY = 0; sY < height; dY++, sY++) {
618             memcpy(&(dst[dY * dStride]), &(src[sY * sStride]), bwidth);
619             dY++;
620         }
621     } else {
622         av_image_copy_plane(dst, dStride, src, sStride, bwidth, height);
623     }
624
625     frame->interlaced_frame = interlaced;
626     if (interlaced)
627         frame->top_field_first = !bottom_first;
628
629     if (pkt_pts != AV_NOPTS_VALUE) {
630         frame->pts = pkt_pts;
631 #if FF_API_PKT_PTS
632 FF_DISABLE_DEPRECATION_WARNINGS
633         frame->pkt_pts = pkt_pts;
634 FF_ENABLE_DEPRECATION_WARNINGS
635 #endif
636     }
637     frame->pkt_pos = -1;
638     frame->pkt_duration = 0;
639     frame->pkt_size = -1;
640
641     if (!priv->need_second_field) {
642         *got_frame       = 1;
643     } else {
644         return RET_COPY_AGAIN;
645     }
646
647     return RET_OK;
648 }
649
650
651 static inline CopyRet receive_frame(AVCodecContext *avctx,
652                                     AVFrame *frame, int *got_frame)
653 {
654     BC_STATUS ret;
655     BC_DTS_PROC_OUT output = {
656         .PicInfo.width  = avctx->width,
657         .PicInfo.height = avctx->height,
658     };
659     CHDContext *priv = avctx->priv_data;
660     HANDLE dev       = priv->dev;
661
662     *got_frame = 0;
663
664     // Request decoded data from the driver
665     ret = DtsProcOutputNoCopy(dev, OUTPUT_PROC_TIMEOUT, &output);
666     if (ret == BC_STS_FMT_CHANGE) {
667         av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Initial format change\n");
668         avctx->width  = output.PicInfo.width;
669         avctx->height = output.PicInfo.height;
670         switch ( output.PicInfo.aspect_ratio ) {
671         case vdecAspectRatioSquare:
672             avctx->sample_aspect_ratio = (AVRational) {  1,  1};
673             break;
674         case vdecAspectRatio12_11:
675             avctx->sample_aspect_ratio = (AVRational) { 12, 11};
676             break;
677         case vdecAspectRatio10_11:
678             avctx->sample_aspect_ratio = (AVRational) { 10, 11};
679             break;
680         case vdecAspectRatio16_11:
681             avctx->sample_aspect_ratio = (AVRational) { 16, 11};
682             break;
683         case vdecAspectRatio40_33:
684             avctx->sample_aspect_ratio = (AVRational) { 40, 33};
685             break;
686         case vdecAspectRatio24_11:
687             avctx->sample_aspect_ratio = (AVRational) { 24, 11};
688             break;
689         case vdecAspectRatio20_11:
690             avctx->sample_aspect_ratio = (AVRational) { 20, 11};
691             break;
692         case vdecAspectRatio32_11:
693             avctx->sample_aspect_ratio = (AVRational) { 32, 11};
694             break;
695         case vdecAspectRatio80_33:
696             avctx->sample_aspect_ratio = (AVRational) { 80, 33};
697             break;
698         case vdecAspectRatio18_11:
699             avctx->sample_aspect_ratio = (AVRational) { 18, 11};
700             break;
701         case vdecAspectRatio15_11:
702             avctx->sample_aspect_ratio = (AVRational) { 15, 11};
703             break;
704         case vdecAspectRatio64_33:
705             avctx->sample_aspect_ratio = (AVRational) { 64, 33};
706             break;
707         case vdecAspectRatio160_99:
708             avctx->sample_aspect_ratio = (AVRational) {160, 99};
709             break;
710         case vdecAspectRatio4_3:
711             avctx->sample_aspect_ratio = (AVRational) {  4,  3};
712             break;
713         case vdecAspectRatio16_9:
714             avctx->sample_aspect_ratio = (AVRational) { 16,  9};
715             break;
716         case vdecAspectRatio221_1:
717             avctx->sample_aspect_ratio = (AVRational) {221,  1};
718             break;
719         }
720         return RET_COPY_AGAIN;
721     } else if (ret == BC_STS_SUCCESS) {
722         int copy_ret = -1;
723         if (output.PoutFlags & BC_POUT_FLAGS_PIB_VALID) {
724             if (avctx->codec->id == AV_CODEC_ID_MPEG4 &&
725                 output.PicInfo.timeStamp == 0 && priv->bframe_bug) {
726                 if (!priv->bframe_bug) {
727                     av_log(avctx, AV_LOG_VERBOSE,
728                            "CrystalHD: Not returning packed frame twice.\n");
729                 }
730                 DtsReleaseOutputBuffs(dev, NULL, FALSE);
731                 return RET_COPY_AGAIN;
732             }
733
734             print_frame_info(priv, &output);
735
736             copy_ret = copy_frame(avctx, &output, frame, got_frame);
737         } else {
738             /*
739              * An invalid frame has been consumed.
740              */
741             av_log(avctx, AV_LOG_ERROR, "CrystalHD: ProcOutput succeeded with "
742                                         "invalid PIB\n");
743             copy_ret = RET_COPY_AGAIN;
744         }
745         DtsReleaseOutputBuffs(dev, NULL, FALSE);
746
747         return copy_ret;
748     } else if (ret == BC_STS_BUSY) {
749         return RET_COPY_AGAIN;
750     } else {
751         av_log(avctx, AV_LOG_ERROR, "CrystalHD: ProcOutput failed %d\n", ret);
752         return RET_ERROR;
753     }
754 }
755
756 static int crystalhd_decode_packet(AVCodecContext *avctx, const AVPacket *avpkt)
757 {
758     BC_STATUS bc_ret;
759     CHDContext *priv   = avctx->priv_data;
760     HANDLE dev         = priv->dev;
761     AVPacket filtered_packet = { 0 };
762     int ret = 0;
763
764     av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: decode_packet\n");
765
766     if (avpkt && avpkt->size) {
767         uint64_t pts;
768         if (!priv->bframe_bug && (avpkt->size == 6 || avpkt->size == 7)) {
769             /*
770              * Drop frames trigger the bug
771              */
772             av_log(avctx, AV_LOG_WARNING,
773                    "CrystalHD: Enabling work-around for packed b-frame bug\n");
774             priv->bframe_bug = 1;
775         } else if (priv->bframe_bug && avpkt->size == 8) {
776             /*
777              * Delay frames don't trigger the bug
778              */
779             av_log(avctx, AV_LOG_WARNING,
780                    "CrystalHD: Disabling work-around for packed b-frame bug\n");
781             priv->bframe_bug = 0;
782         }
783
784         if (priv->bsfc) {
785             AVPacket filter_packet = { 0 };
786
787             ret = av_packet_ref(&filter_packet, avpkt);
788             if (ret < 0) {
789                 av_log(avctx, AV_LOG_ERROR, "CrystalHD: mpv4toannexb filter "
790                        "failed to ref input packet\n");
791                 goto exit;
792             }
793
794             ret = av_bsf_send_packet(priv->bsfc, &filter_packet);
795             if (ret < 0) {
796                 av_log(avctx, AV_LOG_ERROR, "CrystalHD: mpv4toannexb filter "
797                        "failed to send input packet\n");
798                 goto exit;
799             }
800
801             ret = av_bsf_receive_packet(priv->bsfc, &filtered_packet);
802             if (ret < 0) {
803                 av_log(avctx, AV_LOG_ERROR, "CrystalHD: mpv4toannexb filter "
804                        "failed to receive output packet\n");
805                 goto exit;
806             }
807
808             avpkt = &filtered_packet;
809             av_packet_unref(&filter_packet);
810         }
811
812         /*
813          * Despite being notionally opaque, either libcrystalhd or
814          * the hardware itself will mangle pts values that are too
815          * small or too large. The docs claim it should be in units
816          * of 100ns. Given that we're nominally dealing with a black
817          * box on both sides, any transform we do has no guarantee of
818          * avoiding mangling so we need to build a mapping to values
819          * we know will not be mangled.
820          */
821         pts = opaque_list_push(priv, avpkt->pts);
822         if (!pts) {
823             ret = AVERROR(ENOMEM);
824             goto exit;
825         }
826         av_log(priv->avctx, AV_LOG_VERBOSE,
827                "input \"pts\": %"PRIu64"\n", pts);
828         bc_ret = DtsProcInput(dev, avpkt->data, avpkt->size, pts, 0);
829         if (bc_ret == BC_STS_BUSY) {
830             av_log(avctx, AV_LOG_WARNING,
831                    "CrystalHD: ProcInput returned busy\n");
832             ret = AVERROR(EAGAIN);
833             goto exit;
834         } else if (bc_ret != BC_STS_SUCCESS) {
835             av_log(avctx, AV_LOG_ERROR,
836                    "CrystalHD: ProcInput failed: %u\n", ret);
837             ret = -1;
838             goto exit;
839         }
840     } else {
841         av_log(avctx, AV_LOG_INFO, "CrystalHD: No more input data\n");
842         priv->draining = 1;
843         ret = AVERROR_EOF;
844         goto exit;
845     }
846  exit:
847     av_packet_unref(&filtered_packet);
848     return ret;
849 }
850
851 static int crystalhd_receive_frame(AVCodecContext *avctx, AVFrame *frame)
852 {
853     BC_STATUS bc_ret;
854     BC_DTS_STATUS decoder_status = { 0, };
855     CopyRet rec_ret;
856     CHDContext *priv   = avctx->priv_data;
857     HANDLE dev         = priv->dev;
858     int got_frame = 0;
859     int ret = 0;
860     AVPacket pkt = {0};
861
862     av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: receive_frame\n");
863
864     ret = ff_decode_get_packet(avctx, &pkt);
865     if (ret < 0 && ret != AVERROR_EOF) {
866         return ret;
867     }
868
869     while (pkt.size > DtsTxFreeSize(dev)) {
870         /*
871          * Block until there is space in the buffer for the next packet.
872          * We assume that the hardware will make forward progress at this
873          * point, although in pathological cases that may not happen.
874          */
875         av_log(avctx, AV_LOG_TRACE, "CrystalHD: Waiting for space in input buffer\n");
876     }
877
878     ret = crystalhd_decode_packet(avctx, &pkt);
879     av_packet_unref(&pkt);
880     // crystalhd_is_buffer_full() should avoid this.
881     if (ret == AVERROR(EAGAIN)) {
882         ret = AVERROR_EXTERNAL;
883     }
884     if (ret < 0 && ret != AVERROR_EOF) {
885         return ret;
886     }
887
888     do {
889         bc_ret = DtsGetDriverStatus(dev, &decoder_status);
890         if (bc_ret != BC_STS_SUCCESS) {
891             av_log(avctx, AV_LOG_ERROR, "CrystalHD: GetDriverStatus failed\n");
892             return -1;
893         }
894
895         if (decoder_status.ReadyListCount == 0) {
896             av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Insufficient frames ready. Returning\n");
897             got_frame = 0;
898             rec_ret = RET_OK;
899             break;
900         }
901
902         rec_ret = receive_frame(avctx, frame, &got_frame);
903     } while (rec_ret == RET_COPY_AGAIN);
904
905     if (rec_ret == RET_ERROR) {
906         return -1;
907     } else if (got_frame == 0) {
908         return priv->draining ? AVERROR_EOF : AVERROR(EAGAIN);
909     } else {
910         return 0;
911     }
912 }
913
914 #define DEFINE_CRYSTALHD_DECODER(x, X) \
915     static const AVClass x##_crystalhd_class = { \
916         .class_name = #x "_crystalhd", \
917         .item_name = av_default_item_name, \
918         .option = options, \
919         .version = LIBAVUTIL_VERSION_INT, \
920     }; \
921     AVCodec ff_##x##_crystalhd_decoder = { \
922         .name           = #x "_crystalhd", \
923         .long_name      = NULL_IF_CONFIG_SMALL("CrystalHD " #X " decoder"), \
924         .type           = AVMEDIA_TYPE_VIDEO, \
925         .id             = AV_CODEC_ID_##X, \
926         .priv_data_size = sizeof(CHDContext), \
927         .priv_class     = &x##_crystalhd_class, \
928         .init           = init, \
929         .close          = uninit, \
930         .receive_frame  = crystalhd_receive_frame, \
931         .flush          = flush, \
932         .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \
933         .pix_fmts       = (const enum AVPixelFormat[]){AV_PIX_FMT_YUYV422, AV_PIX_FMT_NONE}, \
934     };
935
936 #if CONFIG_H264_CRYSTALHD_DECODER
937 DEFINE_CRYSTALHD_DECODER(h264, H264)
938 #endif
939
940 #if CONFIG_MPEG2_CRYSTALHD_DECODER
941 DEFINE_CRYSTALHD_DECODER(mpeg2, MPEG2VIDEO)
942 #endif
943
944 #if CONFIG_MPEG4_CRYSTALHD_DECODER
945 DEFINE_CRYSTALHD_DECODER(mpeg4, MPEG4)
946 #endif
947
948 #if CONFIG_MSMPEG4_CRYSTALHD_DECODER
949 DEFINE_CRYSTALHD_DECODER(msmpeg4, MSMPEG4V3)
950 #endif
951
952 #if CONFIG_VC1_CRYSTALHD_DECODER
953 DEFINE_CRYSTALHD_DECODER(vc1, VC1)
954 #endif
955
956 #if CONFIG_WMV3_CRYSTALHD_DECODER
957 DEFINE_CRYSTALHD_DECODER(wmv3, WMV3)
958 #endif