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