FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
crystalhd.c
Go to the documentation of this file.
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,
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 {
94 
97 
99 
102  uint32_t sps_pps_size;
106 
109 
110  /* Options */
111  uint32_t sWidth;
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,
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;
135  return BC_MSUBTYPE_DIVX311;
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, };
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
633  frame->pkt_pts = pkt_pts;
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 
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
void av_bsf_free(AVBSFContext **ctx)
Free a bitstream filter context and everything associated with it; write NULL into the supplied point...
Definition: bsf.c:35
#define NULL
Definition: coverity.c:32
const struct AVCodec * codec
Definition: avcodec.h:1741
int av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane)
Compute the size of an image line with format pix_fmt and width width for the plane plane...
Definition: imgutils.c:76
AVCodecParameters * par_out
Parameters of the output stream.
Definition: avcodec.h:5872
This structure describes decoded (raw) audio or video data.
Definition: frame.h:193
AVOption.
Definition: opt.h:246
int64_t pkt_pos
reordered pos from the last AVPacket that has been input into the decoder
Definition: frame.h:456
misc image utilities
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
uint8_t is_nal
Definition: crystalhd.c:103
static OpaqueList * opaque_list_pop(CHDContext *priv, uint64_t fake_timestamp)
Definition: crystalhd.c:223
uint8_t * orig_extradata
Definition: crystalhd.c:95
The bitstream filter state.
Definition: avcodec.h:5838
int size
Definition: avcodec.h:1658
const AVBitStreamFilter * av_bsf_get_by_name(const char *name)
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown) That is the width of a pixel divided by the height of the pixel...
Definition: avcodec.h:2143
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1960
int version
Definition: avisynth_c.h:766
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:222
static AVPacket pkt
static CopyRet receive_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame)
Definition: crystalhd.c:651
#define src
Definition: vp8dsp.c:254
uint8_t bframe_bug
Definition: crystalhd.c:112
static av_cold int init(AVCodecContext *avctx)
Definition: crystalhd.c:379
int av_bsf_init(AVBSFContext *ctx)
Prepare the filter for use, after all the parameters and options have been set.
Definition: bsf.c:134
uint32_t sWidth
Definition: crystalhd.c:111
#define TIMESTAMP_UNIT
Step between fake timestamps passed to hardware in units of 100ns.
Definition: crystalhd.c:71
int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **ctx)
Allocate a context for a given bitstream filter.
Definition: bsf.c:81
AVCodecContext * avctx
Definition: crystalhd.c:92
int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt)
Retrieve a filtered packet.
Definition: bsf.c:196
OpaqueList * tail
Definition: crystalhd.c:108
uint8_t
#define av_cold
Definition: attributes.h:82
#define av_malloc(s)
static av_cold int uninit(AVCodecContext *avctx)
Definition: crystalhd.c:288
#define DEFINE_CRYSTALHD_DECODER(x, X)
Definition: crystalhd.c:914
AVOptions.
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:202
int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt)
Called by decoders to get the next packet for decoding.
Definition: decode.c:292
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:277
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:1847
static AVFrame * frame
#define height
static int crystalhd_decode_packet(AVCodecContext *avctx, const AVPacket *avpkt)
Definition: crystalhd.c:756
uint8_t * data
Definition: avcodec.h:1657
#define AVERROR_EOF
End of file.
Definition: error.h:55
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
int interlaced_frame
The content of the picture is interlaced.
Definition: frame.h:331
ptrdiff_t size
Definition: opengl_enc.c:101
#define av_log(a,...)
int av_packet_ref(AVPacket *dst, const AVPacket *src)
Setup a new reference to the data described by a given packet.
Definition: avpacket.c:585
enum AVCodecID id
Definition: avcodec.h:3695
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: avcodec.h:214
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
static int crystalhd_receive_frame(AVCodecContext *avctx, AVFrame *frame)
Definition: crystalhd.c:851
#define AVERROR(e)
Definition: error.h:43
CopyRet
Definition: crystalhd.c:78
#define FALSE
Definition: windows2linux.h:37
static void flush(AVCodecContext *avctx)
Definition: crystalhd.c:276
const char * name
Name of the codec implementation.
Definition: avcodec.h:3688
#define fail()
Definition: checkasm.h:90
uint32_t sps_pps_size
Definition: crystalhd.c:102
int extradata_size
Size of the extradata content in bytes.
Definition: avcodec.h:4092
static void print_frame_info(CHDContext *priv, BC_DTS_PROC_OUT *output)
Definition: crystalhd.c:149
uint8_t interlaced
Definition: mxfenc.c:1822
#define width
static const AVOption options[]
Definition: crystalhd.c:115
int width
picture width / height.
Definition: avcodec.h:1919
PVOID HANDLE
static int filter_packet(AVFormatContext *avf, ConcatStream *cs, AVPacket *pkt)
Definition: concatdec.c:522
OpaqueList * head
Definition: crystalhd.c:107
uint8_t * sps_pps_buf
Definition: crystalhd.c:101
int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt)
Submit a packet for filtering.
Definition: bsf.c:175
#define TRUE
Definition: windows2linux.h:33
uint64_t reordered_opaque
Definition: crystalhd.c:87
uint64_t fake_timestamp
Definition: crystalhd.c:86
#define AVERROR_BSF_NOT_FOUND
Bitstream filter not found.
Definition: error.h:49
uint8_t draining
Definition: crystalhd.c:105
preferred ID for MPEG-1/2 video decoding
Definition: avcodec.h:219
HANDLE dev
Definition: crystalhd.c:93
struct OpaqueList * next
Definition: crystalhd.c:85
#define AV_LOG_INFO
Standard information.
Definition: log.h:187
static av_cold int init_bsf(AVCodecContext *avctx, const char *bsf_name)
Definition: crystalhd.c:330
Libavcodec external API header.
int64_t pkt_duration
duration of the corresponding packet, expressed in AVStream->time_base units, 0 if unknown...
Definition: frame.h:464
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:224
uint32_t orig_extradata_size
Definition: crystalhd.c:96
#define AV_OPT_FLAG_VIDEO_PARAM
Definition: opt.h:282
main external API structure.
Definition: avcodec.h:1732
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:576
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition: pixfmt.h:63
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1601
int extradata_size
Definition: avcodec.h:1848
static const char * format
Definition: movenc.c:47
Describe the class of an AVClass context structure.
Definition: log.h:67
static BC_MEDIA_SUBTYPE id2subtype(CHDContext *priv, enum AVCodecID id)
Definition: crystalhd.c:129
uint8_t need_second_field
Definition: crystalhd.c:104
Rational number (pair of numerator and denominator).
Definition: rational.h:58
int avcodec_parameters_from_context(AVCodecParameters *par, const AVCodecContext *codec)
Fill the parameters struct based on the values from the supplied codec context.
Definition: utils.c:2297
#define AV_OPT_FLAG_DECODING_PARAM
a generic parameter which can be set by the user for demuxing or decoding
Definition: opt.h:277
static int64_t pts
Global timestamp for the audio frames.
uint8_t is_70012
Definition: crystalhd.c:100
static CopyRet copy_frame(AVCodecContext *avctx, BC_DTS_PROC_OUT *output, AVFrame *frame, int *got_frame)
Definition: crystalhd.c:511
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:207
attribute_deprecated int64_t pkt_pts
PTS copied from the AVPacket that was decoded to produce this frame.
Definition: frame.h:285
AVClass * av_class
Definition: crystalhd.c:91
#define FF_DISABLE_DEPRECATION_WARNINGS
Definition: internal.h:83
common internal api header.
static uint64_t opaque_list_push(CHDContext *priv, uint64_t reordered_opaque)
Definition: crystalhd.c:195
#define OUTPUT_PROC_TIMEOUT
Timeout parameter passed to DtsProcOutput() in us.
Definition: crystalhd.c:69
AVBSFContext * bsfc
Definition: crystalhd.c:98
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
Definition: avcodec.h:772
void * priv_data
Definition: avcodec.h:1774
#define av_free(p)
#define FF_ENABLE_DEPRECATION_WARNINGS
Definition: internal.h:84
int top_field_first
If the content is interlaced, is top field displayed first.
Definition: frame.h:336
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: avcodec.h:4088
#define av_freep(p)
void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height)
Copy image plane from src to dst.
Definition: imgutils.c:337
int pkt_size
size of the corresponding packet containing the compressed frame.
Definition: frame.h:498
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:57
This structure stores compressed data.
Definition: avcodec.h:1634
AVCodecParameters * par_in
Parameters of the input stream.
Definition: avcodec.h:5866
mode
Use these values in ebur128_init (or'ed).
Definition: ebur128.h:83
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1650
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248