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