00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 #define _XOPEN_SOURCE 600
00077 #include <inttypes.h>
00078 #include <stdio.h>
00079 #include <stdlib.h>
00080 #include <unistd.h>
00081
00082 #include <libcrystalhd/bc_dts_types.h>
00083 #include <libcrystalhd/bc_dts_defs.h>
00084 #include <libcrystalhd/libcrystalhd_if.h>
00085
00086 #include "avcodec.h"
00087 #include "h264.h"
00088 #include "libavutil/imgutils.h"
00089 #include "libavutil/intreadwrite.h"
00090 #include "libavutil/opt.h"
00091
00093 #define OUTPUT_PROC_TIMEOUT 50
00094
00095 #define TIMESTAMP_UNIT 100000
00096
00097 #define BASE_WAIT 10000
00098
00099 #define WAIT_UNIT 1000
00100
00101
00102
00103
00104
00105
00106 typedef enum {
00107 RET_ERROR = -1,
00108 RET_OK = 0,
00109 RET_COPY_AGAIN = 1,
00110 RET_SKIP_NEXT_COPY = 2,
00111 RET_COPY_NEXT_FIELD = 3,
00112 } CopyRet;
00113
00114 typedef struct OpaqueList {
00115 struct OpaqueList *next;
00116 uint64_t fake_timestamp;
00117 uint64_t reordered_opaque;
00118 uint8_t pic_type;
00119 } OpaqueList;
00120
00121 typedef struct {
00122 AVClass *av_class;
00123 AVCodecContext *avctx;
00124 AVFrame pic;
00125 HANDLE dev;
00126
00127 AVBitStreamFilterContext *bsfc;
00128 AVCodecParserContext *parser;
00129
00130 uint8_t is_70012;
00131 uint8_t *sps_pps_buf;
00132 uint32_t sps_pps_size;
00133 uint8_t is_nal;
00134 uint8_t output_ready;
00135 uint8_t need_second_field;
00136 uint8_t skip_next_output;
00137 uint64_t decode_wait;
00138
00139 uint64_t last_picture;
00140
00141 OpaqueList *head;
00142 OpaqueList *tail;
00143
00144
00145 uint32_t sWidth;
00146 uint8_t bframe_bug;
00147 } CHDContext;
00148
00149 static const AVOption options[] = {
00150 { "crystalhd_downscale_width",
00151 "Turn on downscaling to the specified width",
00152 offsetof(CHDContext, sWidth),
00153 AV_OPT_TYPE_INT, 0, 0, UINT32_MAX,
00154 AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM, },
00155 { NULL, },
00156 };
00157
00158
00159
00160
00161
00162
00163 static inline BC_MEDIA_SUBTYPE id2subtype(CHDContext *priv, enum CodecID id)
00164 {
00165 switch (id) {
00166 case CODEC_ID_MPEG4:
00167 return BC_MSUBTYPE_DIVX;
00168 case CODEC_ID_MSMPEG4V3:
00169 return BC_MSUBTYPE_DIVX311;
00170 case CODEC_ID_MPEG2VIDEO:
00171 return BC_MSUBTYPE_MPEG2VIDEO;
00172 case CODEC_ID_VC1:
00173 return BC_MSUBTYPE_VC1;
00174 case CODEC_ID_WMV3:
00175 return BC_MSUBTYPE_WMV3;
00176 case CODEC_ID_H264:
00177 return priv->is_nal ? BC_MSUBTYPE_AVC1 : BC_MSUBTYPE_H264;
00178 default:
00179 return BC_MSUBTYPE_INVALID;
00180 }
00181 }
00182
00183 static inline void print_frame_info(CHDContext *priv, BC_DTS_PROC_OUT *output)
00184 {
00185 av_log(priv->avctx, AV_LOG_VERBOSE, "\tYBuffSz: %u\n", output->YbuffSz);
00186 av_log(priv->avctx, AV_LOG_VERBOSE, "\tYBuffDoneSz: %u\n",
00187 output->YBuffDoneSz);
00188 av_log(priv->avctx, AV_LOG_VERBOSE, "\tUVBuffDoneSz: %u\n",
00189 output->UVBuffDoneSz);
00190 av_log(priv->avctx, AV_LOG_VERBOSE, "\tTimestamp: %"PRIu64"\n",
00191 output->PicInfo.timeStamp);
00192 av_log(priv->avctx, AV_LOG_VERBOSE, "\tPicture Number: %u\n",
00193 output->PicInfo.picture_number);
00194 av_log(priv->avctx, AV_LOG_VERBOSE, "\tWidth: %u\n",
00195 output->PicInfo.width);
00196 av_log(priv->avctx, AV_LOG_VERBOSE, "\tHeight: %u\n",
00197 output->PicInfo.height);
00198 av_log(priv->avctx, AV_LOG_VERBOSE, "\tChroma: 0x%03x\n",
00199 output->PicInfo.chroma_format);
00200 av_log(priv->avctx, AV_LOG_VERBOSE, "\tPulldown: %u\n",
00201 output->PicInfo.pulldown);
00202 av_log(priv->avctx, AV_LOG_VERBOSE, "\tFlags: 0x%08x\n",
00203 output->PicInfo.flags);
00204 av_log(priv->avctx, AV_LOG_VERBOSE, "\tFrame Rate/Res: %u\n",
00205 output->PicInfo.frame_rate);
00206 av_log(priv->avctx, AV_LOG_VERBOSE, "\tAspect Ratio: %u\n",
00207 output->PicInfo.aspect_ratio);
00208 av_log(priv->avctx, AV_LOG_VERBOSE, "\tColor Primaries: %u\n",
00209 output->PicInfo.colour_primaries);
00210 av_log(priv->avctx, AV_LOG_VERBOSE, "\tMetaData: %u\n",
00211 output->PicInfo.picture_meta_payload);
00212 av_log(priv->avctx, AV_LOG_VERBOSE, "\tSession Number: %u\n",
00213 output->PicInfo.sess_num);
00214 av_log(priv->avctx, AV_LOG_VERBOSE, "\tycom: %u\n",
00215 output->PicInfo.ycom);
00216 av_log(priv->avctx, AV_LOG_VERBOSE, "\tCustom Aspect: %u\n",
00217 output->PicInfo.custom_aspect_ratio_width_height);
00218 av_log(priv->avctx, AV_LOG_VERBOSE, "\tFrames to Drop: %u\n",
00219 output->PicInfo.n_drop);
00220 av_log(priv->avctx, AV_LOG_VERBOSE, "\tH264 Valid Fields: 0x%08x\n",
00221 output->PicInfo.other.h264.valid);
00222 }
00223
00224
00225
00226
00227
00228
00229 static uint64_t opaque_list_push(CHDContext *priv, uint64_t reordered_opaque,
00230 uint8_t pic_type)
00231 {
00232 OpaqueList *newNode = av_mallocz(sizeof (OpaqueList));
00233 if (!newNode) {
00234 av_log(priv->avctx, AV_LOG_ERROR,
00235 "Unable to allocate new node in OpaqueList.\n");
00236 return 0;
00237 }
00238 if (!priv->head) {
00239 newNode->fake_timestamp = TIMESTAMP_UNIT;
00240 priv->head = newNode;
00241 } else {
00242 newNode->fake_timestamp = priv->tail->fake_timestamp + TIMESTAMP_UNIT;
00243 priv->tail->next = newNode;
00244 }
00245 priv->tail = newNode;
00246 newNode->reordered_opaque = reordered_opaque;
00247 newNode->pic_type = pic_type;
00248
00249 return newNode->fake_timestamp;
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259 static OpaqueList *opaque_list_pop(CHDContext *priv, uint64_t fake_timestamp)
00260 {
00261 OpaqueList *node = priv->head;
00262
00263 if (!priv->head) {
00264 av_log(priv->avctx, AV_LOG_ERROR,
00265 "CrystalHD: Attempted to query non-existent timestamps.\n");
00266 return NULL;
00267 }
00268
00269
00270
00271
00272
00273 if (priv->head->fake_timestamp == fake_timestamp) {
00274 priv->head = node->next;
00275
00276 if (!priv->head->next)
00277 priv->tail = priv->head;
00278
00279 node->next = NULL;
00280 return node;
00281 }
00282
00283
00284
00285
00286
00287 while (node->next) {
00288 OpaqueList *current = node->next;
00289 if (current->fake_timestamp == fake_timestamp) {
00290 node->next = current->next;
00291
00292 if (!node->next)
00293 priv->tail = node;
00294
00295 current->next = NULL;
00296 return current;
00297 } else {
00298 node = current;
00299 }
00300 }
00301
00302 av_log(priv->avctx, AV_LOG_VERBOSE,
00303 "CrystalHD: Couldn't match fake_timestamp.\n");
00304 return NULL;
00305 }
00306
00307
00308
00309
00310
00311
00312 static void flush(AVCodecContext *avctx)
00313 {
00314 CHDContext *priv = avctx->priv_data;
00315
00316 avctx->has_b_frames = 0;
00317 priv->last_picture = -1;
00318 priv->output_ready = 0;
00319 priv->need_second_field = 0;
00320 priv->skip_next_output = 0;
00321 priv->decode_wait = BASE_WAIT;
00322
00323 if (priv->pic.data[0])
00324 avctx->release_buffer(avctx, &priv->pic);
00325
00326
00327 DtsFlushInput(priv->dev, 4);
00328 }
00329
00330
00331 static av_cold int uninit(AVCodecContext *avctx)
00332 {
00333 CHDContext *priv = avctx->priv_data;
00334 HANDLE device;
00335
00336 device = priv->dev;
00337 DtsStopDecoder(device);
00338 DtsCloseDecoder(device);
00339 DtsDeviceClose(device);
00340
00341 av_parser_close(priv->parser);
00342 if (priv->bsfc) {
00343 av_bitstream_filter_close(priv->bsfc);
00344 }
00345
00346 av_free(priv->sps_pps_buf);
00347
00348 if (priv->pic.data[0])
00349 avctx->release_buffer(avctx, &priv->pic);
00350
00351 if (priv->head) {
00352 OpaqueList *node = priv->head;
00353 while (node) {
00354 OpaqueList *next = node->next;
00355 av_free(node);
00356 node = next;
00357 }
00358 }
00359
00360 return 0;
00361 }
00362
00363
00364 static av_cold int init(AVCodecContext *avctx)
00365 {
00366 CHDContext* priv;
00367 BC_STATUS ret;
00368 BC_INFO_CRYSTAL version;
00369 BC_INPUT_FORMAT format = {
00370 .FGTEnable = FALSE,
00371 .Progressive = TRUE,
00372 .OptFlags = 0x80000000 | vdecFrameRate59_94 | 0x40,
00373 .width = avctx->width,
00374 .height = avctx->height,
00375 };
00376
00377 BC_MEDIA_SUBTYPE subtype;
00378
00379 uint32_t mode = DTS_PLAYBACK_MODE |
00380 DTS_LOAD_FILE_PLAY_FW |
00381 DTS_SKIP_TX_CHK_CPB |
00382 DTS_PLAYBACK_DROP_RPT_MODE |
00383 DTS_SINGLE_THREADED_MODE |
00384 DTS_DFLT_RESOLUTION(vdecRESOLUTION_1080p23_976);
00385
00386 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD Init for %s\n",
00387 avctx->codec->name);
00388
00389 avctx->pix_fmt = PIX_FMT_YUYV422;
00390
00391
00392 priv = avctx->priv_data;
00393 priv->avctx = avctx;
00394 priv->is_nal = avctx->extradata_size > 0 && *(avctx->extradata) == 1;
00395 priv->last_picture = -1;
00396 priv->decode_wait = BASE_WAIT;
00397
00398 subtype = id2subtype(priv, avctx->codec->id);
00399 switch (subtype) {
00400 case BC_MSUBTYPE_AVC1:
00401 {
00402 uint8_t *dummy_p;
00403 int dummy_int;
00404
00405 priv->bsfc = av_bitstream_filter_init("h264_mp4toannexb");
00406 if (!priv->bsfc) {
00407 av_log(avctx, AV_LOG_ERROR,
00408 "Cannot open the h264_mp4toannexb BSF!\n");
00409 return AVERROR_BSF_NOT_FOUND;
00410 }
00411 av_bitstream_filter_filter(priv->bsfc, avctx, NULL, &dummy_p,
00412 &dummy_int, NULL, 0, 0);
00413 }
00414 subtype = BC_MSUBTYPE_H264;
00415
00416 case BC_MSUBTYPE_H264:
00417 format.startCodeSz = 4;
00418
00419 case BC_MSUBTYPE_VC1:
00420 case BC_MSUBTYPE_WVC1:
00421 case BC_MSUBTYPE_WMV3:
00422 case BC_MSUBTYPE_WMVA:
00423 case BC_MSUBTYPE_MPEG2VIDEO:
00424 case BC_MSUBTYPE_DIVX:
00425 case BC_MSUBTYPE_DIVX311:
00426 format.pMetaData = avctx->extradata;
00427 format.metaDataSz = avctx->extradata_size;
00428 break;
00429 default:
00430 av_log(avctx, AV_LOG_ERROR, "CrystalHD: Unknown codec name\n");
00431 return AVERROR(EINVAL);
00432 }
00433 format.mSubtype = subtype;
00434
00435 if (priv->sWidth) {
00436 format.bEnableScaling = 1;
00437 format.ScalingParams.sWidth = priv->sWidth;
00438 }
00439
00440
00441 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: starting up\n");
00442
00443 ret = DtsDeviceOpen(&priv->dev, mode);
00444 if (ret != BC_STS_SUCCESS) {
00445 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: DtsDeviceOpen failed\n");
00446 goto fail;
00447 }
00448
00449 ret = DtsCrystalHDVersion(priv->dev, &version);
00450 if (ret != BC_STS_SUCCESS) {
00451 av_log(avctx, AV_LOG_VERBOSE,
00452 "CrystalHD: DtsCrystalHDVersion failed\n");
00453 goto fail;
00454 }
00455 priv->is_70012 = version.device == 0;
00456
00457 if (priv->is_70012 &&
00458 (subtype == BC_MSUBTYPE_DIVX || subtype == BC_MSUBTYPE_DIVX311)) {
00459 av_log(avctx, AV_LOG_VERBOSE,
00460 "CrystalHD: BCM70012 doesn't support MPEG4-ASP/DivX/Xvid\n");
00461 goto fail;
00462 }
00463
00464 ret = DtsSetInputFormat(priv->dev, &format);
00465 if (ret != BC_STS_SUCCESS) {
00466 av_log(avctx, AV_LOG_ERROR, "CrystalHD: SetInputFormat failed\n");
00467 goto fail;
00468 }
00469
00470 ret = DtsOpenDecoder(priv->dev, BC_STREAM_TYPE_ES);
00471 if (ret != BC_STS_SUCCESS) {
00472 av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsOpenDecoder failed\n");
00473 goto fail;
00474 }
00475
00476 ret = DtsSetColorSpace(priv->dev, OUTPUT_MODE422_YUY2);
00477 if (ret != BC_STS_SUCCESS) {
00478 av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsSetColorSpace failed\n");
00479 goto fail;
00480 }
00481 ret = DtsStartDecoder(priv->dev);
00482 if (ret != BC_STS_SUCCESS) {
00483 av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsStartDecoder failed\n");
00484 goto fail;
00485 }
00486 ret = DtsStartCapture(priv->dev);
00487 if (ret != BC_STS_SUCCESS) {
00488 av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsStartCapture failed\n");
00489 goto fail;
00490 }
00491
00492 if (avctx->codec->id == CODEC_ID_H264) {
00493 priv->parser = av_parser_init(avctx->codec->id);
00494 if (!priv->parser)
00495 av_log(avctx, AV_LOG_WARNING,
00496 "Cannot open the h.264 parser! Interlaced h.264 content "
00497 "will not be detected reliably.\n");
00498 priv->parser->flags = PARSER_FLAG_COMPLETE_FRAMES;
00499 }
00500 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Init complete.\n");
00501
00502 return 0;
00503
00504 fail:
00505 uninit(avctx);
00506 return -1;
00507 }
00508
00509
00510 static inline CopyRet copy_frame(AVCodecContext *avctx,
00511 BC_DTS_PROC_OUT *output,
00512 void *data, int *data_size)
00513 {
00514 BC_STATUS ret;
00515 BC_DTS_STATUS decoder_status;
00516 uint8_t trust_interlaced;
00517 uint8_t interlaced;
00518
00519 CHDContext *priv = avctx->priv_data;
00520 int64_t pkt_pts = AV_NOPTS_VALUE;
00521 uint8_t pic_type = 0;
00522
00523 uint8_t bottom_field = (output->PicInfo.flags & VDEC_FLAG_BOTTOMFIELD) ==
00524 VDEC_FLAG_BOTTOMFIELD;
00525 uint8_t bottom_first = !!(output->PicInfo.flags & VDEC_FLAG_BOTTOM_FIRST);
00526
00527 int width = output->PicInfo.width;
00528 int height = output->PicInfo.height;
00529 int bwidth;
00530 uint8_t *src = output->Ybuff;
00531 int sStride;
00532 uint8_t *dst;
00533 int dStride;
00534
00535 if (output->PicInfo.timeStamp != 0) {
00536 OpaqueList *node = opaque_list_pop(priv, output->PicInfo.timeStamp);
00537 if (node) {
00538 pkt_pts = node->reordered_opaque;
00539 pic_type = node->pic_type;
00540 av_free(node);
00541 } else {
00542
00543
00544
00545
00546
00547
00548
00549
00550 pic_type = PICT_BOTTOM_FIELD;
00551 }
00552 av_log(avctx, AV_LOG_VERBOSE, "output \"pts\": %"PRIu64"\n",
00553 output->PicInfo.timeStamp);
00554 av_log(avctx, AV_LOG_VERBOSE, "output picture type %d\n",
00555 pic_type);
00556 }
00557
00558 ret = DtsGetDriverStatus(priv->dev, &decoder_status);
00559 if (ret != BC_STS_SUCCESS) {
00560 av_log(avctx, AV_LOG_ERROR,
00561 "CrystalHD: GetDriverStatus failed: %u\n", ret);
00562 return RET_ERROR;
00563 }
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581 trust_interlaced = avctx->codec->id != CODEC_ID_H264 ||
00582 !(output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) ||
00583 priv->need_second_field ||
00584 (decoder_status.picNumFlags & ~0x40000000) ==
00585 output->PicInfo.picture_number;
00586
00587
00588
00589
00590
00591
00592
00593 if (output->PicInfo.picture_number == priv->last_picture && !priv->need_second_field) {
00594 av_log(avctx, AV_LOG_WARNING,
00595 "Incorrectly guessed progressive frame. Discarding second field\n");
00596
00597 return RET_OK;
00598 }
00599
00600 interlaced = (output->PicInfo.flags & VDEC_FLAG_INTERLACED_SRC) &&
00601 trust_interlaced;
00602
00603 if (!trust_interlaced && (decoder_status.picNumFlags & ~0x40000000) == 0) {
00604 av_log(avctx, AV_LOG_VERBOSE,
00605 "Next picture number unknown. Assuming progressive frame.\n");
00606 }
00607
00608 av_log(avctx, AV_LOG_VERBOSE, "Interlaced state: %d | trust_interlaced %d\n",
00609 interlaced, trust_interlaced);
00610
00611 if (priv->pic.data[0] && !priv->need_second_field)
00612 avctx->release_buffer(avctx, &priv->pic);
00613
00614 priv->need_second_field = interlaced && !priv->need_second_field;
00615
00616 priv->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
00617 FF_BUFFER_HINTS_REUSABLE;
00618 if (!priv->pic.data[0]) {
00619 if (avctx->get_buffer(avctx, &priv->pic) < 0) {
00620 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00621 return RET_ERROR;
00622 }
00623 }
00624
00625 bwidth = av_image_get_linesize(avctx->pix_fmt, width, 0);
00626 if (priv->is_70012) {
00627 int pStride;
00628
00629 if (width <= 720)
00630 pStride = 720;
00631 else if (width <= 1280)
00632 pStride = 1280;
00633 else if (width <= 1080)
00634 pStride = 1080;
00635 sStride = av_image_get_linesize(avctx->pix_fmt, pStride, 0);
00636 } else {
00637 sStride = bwidth;
00638 }
00639
00640 dStride = priv->pic.linesize[0];
00641 dst = priv->pic.data[0];
00642
00643 av_log(priv->avctx, AV_LOG_VERBOSE, "CrystalHD: Copying out frame\n");
00644
00645 if (interlaced) {
00646 int dY = 0;
00647 int sY = 0;
00648
00649 height /= 2;
00650 if (bottom_field) {
00651 av_log(priv->avctx, AV_LOG_VERBOSE, "Interlaced: bottom field\n");
00652 dY = 1;
00653 } else {
00654 av_log(priv->avctx, AV_LOG_VERBOSE, "Interlaced: top field\n");
00655 dY = 0;
00656 }
00657
00658 for (sY = 0; sY < height; dY++, sY++) {
00659 memcpy(&(dst[dY * dStride]), &(src[sY * sStride]), bwidth);
00660 dY++;
00661 }
00662 } else {
00663 av_image_copy_plane(dst, dStride, src, sStride, bwidth, height);
00664 }
00665
00666 priv->pic.interlaced_frame = interlaced;
00667 if (interlaced)
00668 priv->pic.top_field_first = !bottom_first;
00669
00670 priv->pic.pkt_pts = pkt_pts;
00671
00672 if (!priv->need_second_field) {
00673 *data_size = sizeof(AVFrame);
00674 *(AVFrame *)data = priv->pic;
00675 }
00676
00677
00678
00679
00680
00681
00682
00683
00684 if (!interlaced && (output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) &&
00685 (pic_type == PICT_TOP_FIELD || pic_type == PICT_BOTTOM_FIELD)) {
00686 av_log(priv->avctx, AV_LOG_VERBOSE, "Fieldpair from two packets.\n");
00687 return RET_SKIP_NEXT_COPY;
00688 }
00689
00690
00691
00692
00693
00694 return priv->need_second_field &&
00695 !(output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) ?
00696 RET_COPY_NEXT_FIELD : RET_OK;
00697 }
00698
00699
00700 static inline CopyRet receive_frame(AVCodecContext *avctx,
00701 void *data, int *data_size)
00702 {
00703 BC_STATUS ret;
00704 BC_DTS_PROC_OUT output = {
00705 .PicInfo.width = avctx->width,
00706 .PicInfo.height = avctx->height,
00707 };
00708 CHDContext *priv = avctx->priv_data;
00709 HANDLE dev = priv->dev;
00710
00711 *data_size = 0;
00712
00713
00714 ret = DtsProcOutputNoCopy(dev, OUTPUT_PROC_TIMEOUT, &output);
00715 if (ret == BC_STS_FMT_CHANGE) {
00716 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Initial format change\n");
00717 avctx->width = output.PicInfo.width;
00718 avctx->height = output.PicInfo.height;
00719 return RET_COPY_AGAIN;
00720 } else if (ret == BC_STS_SUCCESS) {
00721 int copy_ret = -1;
00722 if (output.PoutFlags & BC_POUT_FLAGS_PIB_VALID) {
00723 if (priv->last_picture == -1) {
00724
00725
00726
00727
00728 priv->last_picture = output.PicInfo.picture_number - 1;
00729 }
00730
00731 if (avctx->codec->id == CODEC_ID_MPEG4 &&
00732 output.PicInfo.timeStamp == 0 && priv->bframe_bug) {
00733 av_log(avctx, AV_LOG_VERBOSE,
00734 "CrystalHD: Not returning packed frame twice.\n");
00735 priv->last_picture++;
00736 DtsReleaseOutputBuffs(dev, NULL, FALSE);
00737 return RET_COPY_AGAIN;
00738 }
00739
00740 print_frame_info(priv, &output);
00741
00742 if (priv->last_picture + 1 < output.PicInfo.picture_number) {
00743 av_log(avctx, AV_LOG_WARNING,
00744 "CrystalHD: Picture Number discontinuity\n");
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755 priv->last_picture = output.PicInfo.picture_number - 1;
00756 }
00757
00758 copy_ret = copy_frame(avctx, &output, data, data_size);
00759 if (*data_size > 0) {
00760 avctx->has_b_frames--;
00761 priv->last_picture++;
00762 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Pipeline length: %u\n",
00763 avctx->has_b_frames);
00764 }
00765 } else {
00766
00767
00768
00769 av_log(avctx, AV_LOG_ERROR, "CrystalHD: ProcOutput succeeded with "
00770 "invalid PIB\n");
00771 avctx->has_b_frames--;
00772 copy_ret = RET_OK;
00773 }
00774 DtsReleaseOutputBuffs(dev, NULL, FALSE);
00775
00776 return copy_ret;
00777 } else if (ret == BC_STS_BUSY) {
00778 return RET_COPY_AGAIN;
00779 } else {
00780 av_log(avctx, AV_LOG_ERROR, "CrystalHD: ProcOutput failed %d\n", ret);
00781 return RET_ERROR;
00782 }
00783 }
00784
00785
00786 static int decode(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt)
00787 {
00788 BC_STATUS ret;
00789 BC_DTS_STATUS decoder_status;
00790 CopyRet rec_ret;
00791 CHDContext *priv = avctx->priv_data;
00792 HANDLE dev = priv->dev;
00793 uint8_t *in_data = avpkt->data;
00794 int len = avpkt->size;
00795 int free_data = 0;
00796 uint8_t pic_type = 0;
00797
00798 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: decode_frame\n");
00799
00800 if (avpkt->size == 7 && !priv->bframe_bug) {
00801
00802
00803
00804 av_log(avctx, AV_LOG_INFO,
00805 "CrystalHD: Enabling work-around for packed b-frame bug\n");
00806 priv->bframe_bug = 1;
00807 } else if (avpkt->size == 8 && priv->bframe_bug) {
00808
00809
00810
00811 av_log(avctx, AV_LOG_INFO,
00812 "CrystalHD: Disabling work-around for packed b-frame bug\n");
00813 priv->bframe_bug = 0;
00814 }
00815
00816 if (len) {
00817 int32_t tx_free = (int32_t)DtsTxFreeSize(dev);
00818
00819 if (priv->parser) {
00820 int ret = 0;
00821
00822 if (priv->bsfc) {
00823 ret = av_bitstream_filter_filter(priv->bsfc, avctx, NULL,
00824 &in_data, &len,
00825 avpkt->data, len, 0);
00826 }
00827 free_data = ret > 0;
00828
00829 if (ret >= 0) {
00830 uint8_t *pout;
00831 int psize;
00832 int index;
00833 H264Context *h = priv->parser->priv_data;
00834
00835 index = av_parser_parse2(priv->parser, avctx, &pout, &psize,
00836 in_data, len, avctx->pkt->pts,
00837 avctx->pkt->dts, 0);
00838 if (index < 0) {
00839 av_log(avctx, AV_LOG_WARNING,
00840 "CrystalHD: Failed to parse h.264 packet to "
00841 "detect interlacing.\n");
00842 } else if (index != len) {
00843 av_log(avctx, AV_LOG_WARNING,
00844 "CrystalHD: Failed to parse h.264 packet "
00845 "completely. Interlaced frames may be "
00846 "incorrectly detected\n.");
00847 } else {
00848 av_log(avctx, AV_LOG_VERBOSE,
00849 "CrystalHD: parser picture type %d\n",
00850 h->s.picture_structure);
00851 pic_type = h->s.picture_structure;
00852 }
00853 } else {
00854 av_log(avctx, AV_LOG_WARNING,
00855 "CrystalHD: mp4toannexb filter failed to filter "
00856 "packet. Interlaced frames may be incorrectly "
00857 "detected.\n");
00858 }
00859 }
00860
00861 if (len < tx_free - 1024) {
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871 uint64_t pts = opaque_list_push(priv, avctx->pkt->pts, pic_type);
00872 if (!pts) {
00873 if (free_data) {
00874 av_freep(&in_data);
00875 }
00876 return AVERROR(ENOMEM);
00877 }
00878 av_log(priv->avctx, AV_LOG_VERBOSE,
00879 "input \"pts\": %"PRIu64"\n", pts);
00880 ret = DtsProcInput(dev, in_data, len, pts, 0);
00881 if (free_data) {
00882 av_freep(&in_data);
00883 }
00884 if (ret == BC_STS_BUSY) {
00885 av_log(avctx, AV_LOG_WARNING,
00886 "CrystalHD: ProcInput returned busy\n");
00887 usleep(BASE_WAIT);
00888 return AVERROR(EBUSY);
00889 } else if (ret != BC_STS_SUCCESS) {
00890 av_log(avctx, AV_LOG_ERROR,
00891 "CrystalHD: ProcInput failed: %u\n", ret);
00892 return -1;
00893 }
00894 avctx->has_b_frames++;
00895 } else {
00896 av_log(avctx, AV_LOG_WARNING, "CrystalHD: Input buffer full\n");
00897 len = 0;
00898 }
00899 } else {
00900 av_log(avctx, AV_LOG_INFO, "CrystalHD: No more input data\n");
00901 }
00902
00903 if (priv->skip_next_output) {
00904 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Skipping next output.\n");
00905 priv->skip_next_output = 0;
00906 avctx->has_b_frames--;
00907 return len;
00908 }
00909
00910 ret = DtsGetDriverStatus(dev, &decoder_status);
00911 if (ret != BC_STS_SUCCESS) {
00912 av_log(avctx, AV_LOG_ERROR, "CrystalHD: GetDriverStatus failed\n");
00913 return -1;
00914 }
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924 if (priv->output_ready < 2) {
00925 if (decoder_status.ReadyListCount != 0)
00926 priv->output_ready++;
00927 usleep(BASE_WAIT);
00928 av_log(avctx, AV_LOG_INFO, "CrystalHD: Filling pipeline.\n");
00929 return len;
00930 } else if (decoder_status.ReadyListCount == 0) {
00931
00932
00933
00934
00935
00936
00937 usleep(BASE_WAIT);
00938 priv->decode_wait += WAIT_UNIT;
00939 av_log(avctx, AV_LOG_INFO, "CrystalHD: No frames ready. Returning\n");
00940 return len;
00941 }
00942
00943 do {
00944 rec_ret = receive_frame(avctx, data, data_size);
00945 if (rec_ret == RET_OK && *data_size == 0) {
00946
00947
00948
00949
00950
00951
00952
00953 av_log(avctx, AV_LOG_VERBOSE, "Returning after first field.\n");
00954 avctx->has_b_frames--;
00955 } else if (rec_ret == RET_COPY_NEXT_FIELD) {
00956
00957
00958
00959
00960
00961
00962
00963
00964 av_log(avctx, AV_LOG_VERBOSE, "Trying to get second field.\n");
00965 while (1) {
00966 usleep(priv->decode_wait);
00967 ret = DtsGetDriverStatus(dev, &decoder_status);
00968 if (ret == BC_STS_SUCCESS &&
00969 decoder_status.ReadyListCount > 0) {
00970 rec_ret = receive_frame(avctx, data, data_size);
00971 if ((rec_ret == RET_OK && *data_size > 0) ||
00972 rec_ret == RET_ERROR)
00973 break;
00974 }
00975 }
00976 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Got second field.\n");
00977 } else if (rec_ret == RET_SKIP_NEXT_COPY) {
00978
00979
00980
00981 av_log(avctx, AV_LOG_VERBOSE,
00982 "Don't output on next decode call.\n");
00983 priv->skip_next_output = 1;
00984 }
00985
00986
00987
00988
00989
00990
00991
00992
00993 } while (rec_ret == RET_COPY_AGAIN);
00994 usleep(priv->decode_wait);
00995 return len;
00996 }
00997
00998
00999 #if CONFIG_H264_CRYSTALHD_DECODER
01000 static AVClass h264_class = {
01001 "h264_crystalhd",
01002 av_default_item_name,
01003 options,
01004 LIBAVUTIL_VERSION_INT,
01005 };
01006
01007 AVCodec ff_h264_crystalhd_decoder = {
01008 .name = "h264_crystalhd",
01009 .type = AVMEDIA_TYPE_VIDEO,
01010 .id = CODEC_ID_H264,
01011 .priv_data_size = sizeof(CHDContext),
01012 .init = init,
01013 .close = uninit,
01014 .decode = decode,
01015 .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
01016 .flush = flush,
01017 .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (CrystalHD acceleration)"),
01018 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
01019 .priv_class = &h264_class,
01020 };
01021 #endif
01022
01023 #if CONFIG_MPEG2_CRYSTALHD_DECODER
01024 static AVClass mpeg2_class = {
01025 "mpeg2_crystalhd",
01026 av_default_item_name,
01027 options,
01028 LIBAVUTIL_VERSION_INT,
01029 };
01030
01031 AVCodec ff_mpeg2_crystalhd_decoder = {
01032 .name = "mpeg2_crystalhd",
01033 .type = AVMEDIA_TYPE_VIDEO,
01034 .id = CODEC_ID_MPEG2VIDEO,
01035 .priv_data_size = sizeof(CHDContext),
01036 .init = init,
01037 .close = uninit,
01038 .decode = decode,
01039 .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
01040 .flush = flush,
01041 .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 Video (CrystalHD acceleration)"),
01042 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
01043 .priv_class = &mpeg2_class,
01044 };
01045 #endif
01046
01047 #if CONFIG_MPEG4_CRYSTALHD_DECODER
01048 static AVClass mpeg4_class = {
01049 "mpeg4_crystalhd",
01050 av_default_item_name,
01051 options,
01052 LIBAVUTIL_VERSION_INT,
01053 };
01054
01055 AVCodec ff_mpeg4_crystalhd_decoder = {
01056 .name = "mpeg4_crystalhd",
01057 .type = AVMEDIA_TYPE_VIDEO,
01058 .id = CODEC_ID_MPEG4,
01059 .priv_data_size = sizeof(CHDContext),
01060 .init = init,
01061 .close = uninit,
01062 .decode = decode,
01063 .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
01064 .flush = flush,
01065 .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 Part 2 (CrystalHD acceleration)"),
01066 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
01067 .priv_class = &mpeg4_class,
01068 };
01069 #endif
01070
01071 #if CONFIG_MSMPEG4_CRYSTALHD_DECODER
01072 static AVClass msmpeg4_class = {
01073 "msmpeg4_crystalhd",
01074 av_default_item_name,
01075 options,
01076 LIBAVUTIL_VERSION_INT,
01077 };
01078
01079 AVCodec ff_msmpeg4_crystalhd_decoder = {
01080 .name = "msmpeg4_crystalhd",
01081 .type = AVMEDIA_TYPE_VIDEO,
01082 .id = CODEC_ID_MSMPEG4V3,
01083 .priv_data_size = sizeof(CHDContext),
01084 .init = init,
01085 .close = uninit,
01086 .decode = decode,
01087 .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
01088 .flush = flush,
01089 .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 Part 2 Microsoft variant version 3 (CrystalHD acceleration)"),
01090 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
01091 .priv_class = &msmpeg4_class,
01092 };
01093 #endif
01094
01095 #if CONFIG_VC1_CRYSTALHD_DECODER
01096 static AVClass vc1_class = {
01097 "vc1_crystalhd",
01098 av_default_item_name,
01099 options,
01100 LIBAVUTIL_VERSION_INT,
01101 };
01102
01103 AVCodec ff_vc1_crystalhd_decoder = {
01104 .name = "vc1_crystalhd",
01105 .type = AVMEDIA_TYPE_VIDEO,
01106 .id = CODEC_ID_VC1,
01107 .priv_data_size = sizeof(CHDContext),
01108 .init = init,
01109 .close = uninit,
01110 .decode = decode,
01111 .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
01112 .flush = flush,
01113 .long_name = NULL_IF_CONFIG_SMALL("SMPTE VC-1 (CrystalHD acceleration)"),
01114 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
01115 .priv_class = &vc1_class,
01116 };
01117 #endif
01118
01119 #if CONFIG_WMV3_CRYSTALHD_DECODER
01120 static AVClass wmv3_class = {
01121 "wmv3_crystalhd",
01122 av_default_item_name,
01123 options,
01124 LIBAVUTIL_VERSION_INT,
01125 };
01126
01127 AVCodec ff_wmv3_crystalhd_decoder = {
01128 .name = "wmv3_crystalhd",
01129 .type = AVMEDIA_TYPE_VIDEO,
01130 .id = CODEC_ID_WMV3,
01131 .priv_data_size = sizeof(CHDContext),
01132 .init = init,
01133 .close = uninit,
01134 .decode = decode,
01135 .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
01136 .flush = flush,
01137 .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9 (CrystalHD acceleration)"),
01138 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
01139 .priv_class = &wmv3_class,
01140 };
01141 #endif