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