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 "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 
77 typedef enum {
78  RET_ERROR = -1,
79  RET_OK = 0,
81 } CopyRet;
82 
83 typedef struct OpaqueList {
84  struct OpaqueList *next;
85  uint64_t fake_timestamp;
86  uint64_t reordered_opaque;
87 } OpaqueList;
88 
89 typedef struct {
93 
96 
98 
101  uint32_t sps_pps_size;
105 
108 
109  /* Options */
110  uint32_t sWidth;
112 } CHDContext;
113 
114 static 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,
120  { NULL, },
121 };
122 
123 
124 /*****************************************************************************
125  * Helper functions
126  ****************************************************************************/
127 
128 static 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;
134  return BC_MSUBTYPE_DIVX311;
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 
148 static 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 
194 static 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  */
222 static 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 
275 static 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 
287 static 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 
329 static 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 
378 static 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 
510 static 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, };
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
632  frame->pkt_pts = pkt_pts;
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 
650 static 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 
755 static 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 
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
918 DEFINE_CRYSTALHD_DECODER(h264, H264)
919 #endif
920 
921 #if CONFIG_MPEG2_CRYSTALHD_DECODER
922 DEFINE_CRYSTALHD_DECODER(mpeg2, MPEG2VIDEO)
923 #endif
924 
925 #if CONFIG_MPEG4_CRYSTALHD_DECODER
926 DEFINE_CRYSTALHD_DECODER(mpeg4, MPEG4)
927 #endif
928 
929 #if CONFIG_MSMPEG4_CRYSTALHD_DECODER
930 DEFINE_CRYSTALHD_DECODER(msmpeg4, MSMPEG4V3)
931 #endif
932 
933 #if CONFIG_VC1_CRYSTALHD_DECODER
934 DEFINE_CRYSTALHD_DECODER(vc1, VC1)
935 #endif
936 
937 #if CONFIG_WMV3_CRYSTALHD_DECODER
938 DEFINE_CRYSTALHD_DECODER(wmv3, WMV3)
939 #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:36
#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:5864
This structure describes decoded (raw) audio or video data.
Definition: frame.h:187
AVOption.
Definition: opt.h:246
misc image utilities
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
uint8_t is_nal
Definition: crystalhd.c:102
static OpaqueList * opaque_list_pop(CHDContext *priv, uint64_t fake_timestamp)
Definition: crystalhd.c:222
uint8_t * orig_extradata
Definition: crystalhd.c:94
The bitstream filter state.
Definition: avcodec.h:5830
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
void av_frame_set_pkt_duration(AVFrame *frame, int64_t val)
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 CopyRet receive_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame)
Definition: crystalhd.c:650
#define src
Definition: vp8dsp.c:254
void av_frame_set_pkt_size(AVFrame *frame, int val)
uint8_t bframe_bug
Definition: crystalhd.c:111
static av_cold int init(AVCodecContext *avctx)
Definition: crystalhd.c:378
int av_bsf_init(AVBSFContext *ctx)
Prepare the filter for use, after all the parameters and options have been set.
Definition: bsf.c:135
uint32_t sWidth
Definition: crystalhd.c:110
#define TIMESTAMP_UNIT
Step between fake timestamps passed to hardware in units of 100ns.
Definition: crystalhd.c:70
int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **ctx)
Allocate a context for a given bitstream filter.
Definition: bsf.c:82
AVCodecContext * avctx
Definition: crystalhd.c:91
int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt)
Retrieve a filtered packet.
Definition: bsf.c:199
OpaqueList * tail
Definition: crystalhd.c:107
uint8_t
#define av_cold
Definition: attributes.h:82
#define av_malloc(s)
static av_cold int uninit(AVCodecContext *avctx)
Definition: crystalhd.c:287
#define DEFINE_CRYSTALHD_DECODER(x, X)
Definition: crystalhd.c:894
AVOptions.
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:202
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:271
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:755
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:325
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:598
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:857
#define AVERROR(e)
Definition: error.h:43
CopyRet
Definition: crystalhd.c:77
#define FALSE
Definition: windows2linux.h:37
static void flush(AVCodecContext *avctx)
Definition: crystalhd.c:275
const char * name
Name of the codec implementation.
Definition: avcodec.h:3688
#define fail()
Definition: checkasm.h:89
uint32_t sps_pps_size
Definition: crystalhd.c:101
int extradata_size
Size of the extradata content in bytes.
Definition: avcodec.h:4084
static void print_frame_info(CHDContext *priv, BC_DTS_PROC_OUT *output)
Definition: crystalhd.c:148
uint8_t interlaced
Definition: mxfenc.c:1822
#define width
static const AVOption options[]
Definition: crystalhd.c:114
int width
picture width / height.
Definition: avcodec.h:1919
PVOID HANDLE
static int filter_packet(AVFormatContext *avf, ConcatStream *cs, AVPacket *pkt)
Definition: concatdec.c:525
OpaqueList * head
Definition: crystalhd.c:106
uint8_t * sps_pps_buf
Definition: crystalhd.c:100
int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt)
Submit a packet for filtering.
Definition: bsf.c:176
int32_t
void av_frame_set_pkt_pos(AVFrame *frame, int64_t val)
#define TRUE
Definition: windows2linux.h:33
uint64_t reordered_opaque
Definition: crystalhd.c:86
uint64_t fake_timestamp
Definition: crystalhd.c:85
#define AVERROR_BSF_NOT_FOUND
Bitstream filter not found.
Definition: error.h:49
uint8_t draining
Definition: crystalhd.c:104
preferred ID for MPEG-1/2 video decoding
Definition: avcodec.h:219
HANDLE dev
Definition: crystalhd.c:92
struct OpaqueList * next
Definition: crystalhd.c:84
#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:329
Libavcodec external API header.
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:218
uint32_t orig_extradata_size
Definition: crystalhd.c:95
#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:589
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: utils.c:953
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition: pixfmt.h:63
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:128
uint8_t need_second_field
Definition: crystalhd.c:103
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:4207
#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:99
static CopyRet copy_frame(AVCodecContext *avctx, BC_DTS_PROC_OUT *output, AVFrame *frame, int *got_frame)
Definition: crystalhd.c:510
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:201
attribute_deprecated int64_t pkt_pts
PTS copied from the AVPacket that was decoded to produce this frame.
Definition: frame.h:279
AVClass * av_class
Definition: crystalhd.c:90
#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:194
#define OUTPUT_PROC_TIMEOUT
Timeout parameter passed to DtsProcOutput() in us.
Definition: crystalhd.c:68
AVBSFContext * bsfc
Definition: crystalhd.c:97
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
Definition: avcodec.h:769
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:330
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: avcodec.h:4080
#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
This structure stores compressed data.
Definition: avcodec.h:1634
AVCodecParameters * par_in
Parameters of the input stream.
Definition: avcodec.h:5858
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