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 pStride = 1920;
00660 sStride = av_image_get_linesize(avctx->pix_fmt, pStride, 0);
00661 } else {
00662 sStride = bwidth;
00663 }
00664
00665 dStride = priv->pic.linesize[0];
00666 dst = priv->pic.data[0];
00667
00668 av_log(priv->avctx, AV_LOG_VERBOSE, "CrystalHD: Copying out frame\n");
00669
00670 if (interlaced) {
00671 int dY = 0;
00672 int sY = 0;
00673
00674 height /= 2;
00675 if (bottom_field) {
00676 av_log(priv->avctx, AV_LOG_VERBOSE, "Interlaced: bottom field\n");
00677 dY = 1;
00678 } else {
00679 av_log(priv->avctx, AV_LOG_VERBOSE, "Interlaced: top field\n");
00680 dY = 0;
00681 }
00682
00683 for (sY = 0; sY < height; dY++, sY++) {
00684 memcpy(&(dst[dY * dStride]), &(src[sY * sStride]), bwidth);
00685 dY++;
00686 }
00687 } else {
00688 av_image_copy_plane(dst, dStride, src, sStride, bwidth, height);
00689 }
00690
00691 priv->pic.interlaced_frame = interlaced;
00692 if (interlaced)
00693 priv->pic.top_field_first = !bottom_first;
00694
00695 priv->pic.pkt_pts = pkt_pts;
00696
00697 if (!priv->need_second_field) {
00698 *data_size = sizeof(AVFrame);
00699 *(AVFrame *)data = priv->pic;
00700 }
00701
00702
00703
00704
00705
00706
00707
00708
00709 if (!interlaced && (output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) &&
00710 (pic_type == PICT_TOP_FIELD || pic_type == PICT_BOTTOM_FIELD)) {
00711 av_log(priv->avctx, AV_LOG_VERBOSE, "Fieldpair from two packets.\n");
00712 return RET_SKIP_NEXT_COPY;
00713 }
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727 return priv->need_second_field &&
00728 (!(output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) ||
00729 pic_type == PICT_FRAME) ?
00730 RET_COPY_NEXT_FIELD : RET_OK;
00731 }
00732
00733
00734 static inline CopyRet receive_frame(AVCodecContext *avctx,
00735 void *data, int *data_size)
00736 {
00737 BC_STATUS ret;
00738 BC_DTS_PROC_OUT output = {
00739 .PicInfo.width = avctx->width,
00740 .PicInfo.height = avctx->height,
00741 };
00742 CHDContext *priv = avctx->priv_data;
00743 HANDLE dev = priv->dev;
00744
00745 *data_size = 0;
00746
00747
00748 ret = DtsProcOutputNoCopy(dev, OUTPUT_PROC_TIMEOUT, &output);
00749 if (ret == BC_STS_FMT_CHANGE) {
00750 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Initial format change\n");
00751 avctx->width = output.PicInfo.width;
00752 avctx->height = output.PicInfo.height;
00753 switch ( output.PicInfo.aspect_ratio ) {
00754 case vdecAspectRatioSquare:
00755 avctx->sample_aspect_ratio = (AVRational) { 1, 1};
00756 break;
00757 case vdecAspectRatio12_11:
00758 avctx->sample_aspect_ratio = (AVRational) { 12, 11};
00759 break;
00760 case vdecAspectRatio10_11:
00761 avctx->sample_aspect_ratio = (AVRational) { 10, 11};
00762 break;
00763 case vdecAspectRatio16_11:
00764 avctx->sample_aspect_ratio = (AVRational) { 16, 11};
00765 break;
00766 case vdecAspectRatio40_33:
00767 avctx->sample_aspect_ratio = (AVRational) { 40, 33};
00768 break;
00769 case vdecAspectRatio24_11:
00770 avctx->sample_aspect_ratio = (AVRational) { 24, 11};
00771 break;
00772 case vdecAspectRatio20_11:
00773 avctx->sample_aspect_ratio = (AVRational) { 20, 11};
00774 break;
00775 case vdecAspectRatio32_11:
00776 avctx->sample_aspect_ratio = (AVRational) { 32, 11};
00777 break;
00778 case vdecAspectRatio80_33:
00779 avctx->sample_aspect_ratio = (AVRational) { 80, 33};
00780 break;
00781 case vdecAspectRatio18_11:
00782 avctx->sample_aspect_ratio = (AVRational) { 18, 11};
00783 break;
00784 case vdecAspectRatio15_11:
00785 avctx->sample_aspect_ratio = (AVRational) { 15, 11};
00786 break;
00787 case vdecAspectRatio64_33:
00788 avctx->sample_aspect_ratio = (AVRational) { 64, 33};
00789 break;
00790 case vdecAspectRatio160_99:
00791 avctx->sample_aspect_ratio = (AVRational) {160, 99};
00792 break;
00793 case vdecAspectRatio4_3:
00794 avctx->sample_aspect_ratio = (AVRational) { 4, 3};
00795 break;
00796 case vdecAspectRatio16_9:
00797 avctx->sample_aspect_ratio = (AVRational) { 16, 9};
00798 break;
00799 case vdecAspectRatio221_1:
00800 avctx->sample_aspect_ratio = (AVRational) {221, 1};
00801 break;
00802 }
00803 return RET_COPY_AGAIN;
00804 } else if (ret == BC_STS_SUCCESS) {
00805 int copy_ret = -1;
00806 if (output.PoutFlags & BC_POUT_FLAGS_PIB_VALID) {
00807 if (priv->last_picture == -1) {
00808
00809
00810
00811
00812 priv->last_picture = output.PicInfo.picture_number - 1;
00813 }
00814
00815 if (avctx->codec->id == CODEC_ID_MPEG4 &&
00816 output.PicInfo.timeStamp == 0 && priv->bframe_bug) {
00817 av_log(avctx, AV_LOG_VERBOSE,
00818 "CrystalHD: Not returning packed frame twice.\n");
00819 priv->last_picture++;
00820 DtsReleaseOutputBuffs(dev, NULL, FALSE);
00821 return RET_COPY_AGAIN;
00822 }
00823
00824 print_frame_info(priv, &output);
00825
00826 if (priv->last_picture + 1 < output.PicInfo.picture_number) {
00827 av_log(avctx, AV_LOG_WARNING,
00828 "CrystalHD: Picture Number discontinuity\n");
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839 priv->last_picture = output.PicInfo.picture_number - 1;
00840 }
00841
00842 copy_ret = copy_frame(avctx, &output, data, data_size);
00843 if (*data_size > 0) {
00844 avctx->has_b_frames--;
00845 priv->last_picture++;
00846 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Pipeline length: %u\n",
00847 avctx->has_b_frames);
00848 }
00849 } else {
00850
00851
00852
00853 av_log(avctx, AV_LOG_ERROR, "CrystalHD: ProcOutput succeeded with "
00854 "invalid PIB\n");
00855 avctx->has_b_frames--;
00856 copy_ret = RET_OK;
00857 }
00858 DtsReleaseOutputBuffs(dev, NULL, FALSE);
00859
00860 return copy_ret;
00861 } else if (ret == BC_STS_BUSY) {
00862 return RET_COPY_AGAIN;
00863 } else {
00864 av_log(avctx, AV_LOG_ERROR, "CrystalHD: ProcOutput failed %d\n", ret);
00865 return RET_ERROR;
00866 }
00867 }
00868
00869
00870 static int decode(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt)
00871 {
00872 BC_STATUS ret;
00873 BC_DTS_STATUS decoder_status = { 0, };
00874 CopyRet rec_ret;
00875 CHDContext *priv = avctx->priv_data;
00876 HANDLE dev = priv->dev;
00877 uint8_t *in_data = avpkt->data;
00878 int len = avpkt->size;
00879 int free_data = 0;
00880 uint8_t pic_type = 0;
00881
00882 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: decode_frame\n");
00883
00884 if (avpkt->size == 7 && !priv->bframe_bug) {
00885
00886
00887
00888 av_log(avctx, AV_LOG_INFO,
00889 "CrystalHD: Enabling work-around for packed b-frame bug\n");
00890 priv->bframe_bug = 1;
00891 } else if (avpkt->size == 8 && priv->bframe_bug) {
00892
00893
00894
00895 av_log(avctx, AV_LOG_INFO,
00896 "CrystalHD: Disabling work-around for packed b-frame bug\n");
00897 priv->bframe_bug = 0;
00898 }
00899
00900 if (len) {
00901 int32_t tx_free = (int32_t)DtsTxFreeSize(dev);
00902
00903 if (priv->parser) {
00904 int ret = 0;
00905
00906 if (priv->bsfc) {
00907 ret = av_bitstream_filter_filter(priv->bsfc, avctx, NULL,
00908 &in_data, &len,
00909 avpkt->data, len, 0);
00910 }
00911 free_data = ret > 0;
00912
00913 if (ret >= 0) {
00914 uint8_t *pout;
00915 int psize;
00916 int index;
00917 H264Context *h = priv->parser->priv_data;
00918
00919 index = av_parser_parse2(priv->parser, avctx, &pout, &psize,
00920 in_data, len, avctx->pkt->pts,
00921 avctx->pkt->dts, 0);
00922 if (index < 0) {
00923 av_log(avctx, AV_LOG_WARNING,
00924 "CrystalHD: Failed to parse h.264 packet to "
00925 "detect interlacing.\n");
00926 } else if (index != len) {
00927 av_log(avctx, AV_LOG_WARNING,
00928 "CrystalHD: Failed to parse h.264 packet "
00929 "completely. Interlaced frames may be "
00930 "incorrectly detected\n.");
00931 } else {
00932 av_log(avctx, AV_LOG_VERBOSE,
00933 "CrystalHD: parser picture type %d\n",
00934 h->s.picture_structure);
00935 pic_type = h->s.picture_structure;
00936 }
00937 } else {
00938 av_log(avctx, AV_LOG_WARNING,
00939 "CrystalHD: mp4toannexb filter failed to filter "
00940 "packet. Interlaced frames may be incorrectly "
00941 "detected.\n");
00942 }
00943 }
00944
00945 if (len < tx_free - 1024) {
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955 uint64_t pts = opaque_list_push(priv, avctx->pkt->pts, pic_type);
00956 if (!pts) {
00957 if (free_data) {
00958 av_freep(&in_data);
00959 }
00960 return AVERROR(ENOMEM);
00961 }
00962 av_log(priv->avctx, AV_LOG_VERBOSE,
00963 "input \"pts\": %"PRIu64"\n", pts);
00964 ret = DtsProcInput(dev, in_data, len, pts, 0);
00965 if (free_data) {
00966 av_freep(&in_data);
00967 }
00968 if (ret == BC_STS_BUSY) {
00969 av_log(avctx, AV_LOG_WARNING,
00970 "CrystalHD: ProcInput returned busy\n");
00971 usleep(BASE_WAIT);
00972 return AVERROR(EBUSY);
00973 } else if (ret != BC_STS_SUCCESS) {
00974 av_log(avctx, AV_LOG_ERROR,
00975 "CrystalHD: ProcInput failed: %u\n", ret);
00976 return -1;
00977 }
00978 avctx->has_b_frames++;
00979 } else {
00980 av_log(avctx, AV_LOG_WARNING, "CrystalHD: Input buffer full\n");
00981 len = 0;
00982 }
00983 } else {
00984 av_log(avctx, AV_LOG_INFO, "CrystalHD: No more input data\n");
00985 }
00986
00987 if (priv->skip_next_output) {
00988 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Skipping next output.\n");
00989 priv->skip_next_output = 0;
00990 avctx->has_b_frames--;
00991 return len;
00992 }
00993
00994 ret = DtsGetDriverStatus(dev, &decoder_status);
00995 if (ret != BC_STS_SUCCESS) {
00996 av_log(avctx, AV_LOG_ERROR, "CrystalHD: GetDriverStatus failed\n");
00997 return -1;
00998 }
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008 if (priv->output_ready < 2) {
01009 if (decoder_status.ReadyListCount != 0)
01010 priv->output_ready++;
01011 usleep(BASE_WAIT);
01012 av_log(avctx, AV_LOG_INFO, "CrystalHD: Filling pipeline.\n");
01013 return len;
01014 } else if (decoder_status.ReadyListCount == 0) {
01015
01016
01017
01018
01019
01020
01021 usleep(BASE_WAIT);
01022 priv->decode_wait += WAIT_UNIT;
01023 av_log(avctx, AV_LOG_INFO, "CrystalHD: No frames ready. Returning\n");
01024 return len;
01025 }
01026
01027 do {
01028 rec_ret = receive_frame(avctx, data, data_size);
01029 if (rec_ret == RET_OK && *data_size == 0) {
01030
01031
01032
01033
01034
01035
01036
01037 av_log(avctx, AV_LOG_VERBOSE, "Returning after first field.\n");
01038 avctx->has_b_frames--;
01039 } else if (rec_ret == RET_COPY_NEXT_FIELD) {
01040
01041
01042
01043
01044
01045
01046
01047
01048 av_log(avctx, AV_LOG_VERBOSE, "Trying to get second field.\n");
01049 while (1) {
01050 usleep(priv->decode_wait);
01051 ret = DtsGetDriverStatus(dev, &decoder_status);
01052 if (ret == BC_STS_SUCCESS &&
01053 decoder_status.ReadyListCount > 0) {
01054 rec_ret = receive_frame(avctx, data, data_size);
01055 if ((rec_ret == RET_OK && *data_size > 0) ||
01056 rec_ret == RET_ERROR)
01057 break;
01058 }
01059 }
01060 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Got second field.\n");
01061 } else if (rec_ret == RET_SKIP_NEXT_COPY) {
01062
01063
01064
01065 av_log(avctx, AV_LOG_VERBOSE,
01066 "Don't output on next decode call.\n");
01067 priv->skip_next_output = 1;
01068 }
01069
01070
01071
01072
01073
01074
01075
01076
01077 } while (rec_ret == RET_COPY_AGAIN);
01078 usleep(priv->decode_wait);
01079 return len;
01080 }
01081
01082
01083 #if CONFIG_H264_CRYSTALHD_DECODER
01084 static AVClass h264_class = {
01085 "h264_crystalhd",
01086 av_default_item_name,
01087 options,
01088 LIBAVUTIL_VERSION_INT,
01089 };
01090
01091 AVCodec ff_h264_crystalhd_decoder = {
01092 .name = "h264_crystalhd",
01093 .type = AVMEDIA_TYPE_VIDEO,
01094 .id = CODEC_ID_H264,
01095 .priv_data_size = sizeof(CHDContext),
01096 .init = init,
01097 .close = uninit,
01098 .decode = decode,
01099 .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY,
01100 .flush = flush,
01101 .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (CrystalHD acceleration)"),
01102 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
01103 .priv_class = &h264_class,
01104 };
01105 #endif
01106
01107 #if CONFIG_MPEG2_CRYSTALHD_DECODER
01108 static AVClass mpeg2_class = {
01109 "mpeg2_crystalhd",
01110 av_default_item_name,
01111 options,
01112 LIBAVUTIL_VERSION_INT,
01113 };
01114
01115 AVCodec ff_mpeg2_crystalhd_decoder = {
01116 .name = "mpeg2_crystalhd",
01117 .type = AVMEDIA_TYPE_VIDEO,
01118 .id = CODEC_ID_MPEG2VIDEO,
01119 .priv_data_size = sizeof(CHDContext),
01120 .init = init,
01121 .close = uninit,
01122 .decode = decode,
01123 .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY,
01124 .flush = flush,
01125 .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 Video (CrystalHD acceleration)"),
01126 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
01127 .priv_class = &mpeg2_class,
01128 };
01129 #endif
01130
01131 #if CONFIG_MPEG4_CRYSTALHD_DECODER
01132 static AVClass mpeg4_class = {
01133 "mpeg4_crystalhd",
01134 av_default_item_name,
01135 options,
01136 LIBAVUTIL_VERSION_INT,
01137 };
01138
01139 AVCodec ff_mpeg4_crystalhd_decoder = {
01140 .name = "mpeg4_crystalhd",
01141 .type = AVMEDIA_TYPE_VIDEO,
01142 .id = CODEC_ID_MPEG4,
01143 .priv_data_size = sizeof(CHDContext),
01144 .init = init,
01145 .close = uninit,
01146 .decode = decode,
01147 .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY,
01148 .flush = flush,
01149 .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 Part 2 (CrystalHD acceleration)"),
01150 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
01151 .priv_class = &mpeg4_class,
01152 };
01153 #endif
01154
01155 #if CONFIG_MSMPEG4_CRYSTALHD_DECODER
01156 static AVClass msmpeg4_class = {
01157 "msmpeg4_crystalhd",
01158 av_default_item_name,
01159 options,
01160 LIBAVUTIL_VERSION_INT,
01161 };
01162
01163 AVCodec ff_msmpeg4_crystalhd_decoder = {
01164 .name = "msmpeg4_crystalhd",
01165 .type = AVMEDIA_TYPE_VIDEO,
01166 .id = CODEC_ID_MSMPEG4V3,
01167 .priv_data_size = sizeof(CHDContext),
01168 .init = init,
01169 .close = uninit,
01170 .decode = decode,
01171 .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
01172 .flush = flush,
01173 .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 Part 2 Microsoft variant version 3 (CrystalHD acceleration)"),
01174 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
01175 .priv_class = &msmpeg4_class,
01176 };
01177 #endif
01178
01179 #if CONFIG_VC1_CRYSTALHD_DECODER
01180 static AVClass vc1_class = {
01181 "vc1_crystalhd",
01182 av_default_item_name,
01183 options,
01184 LIBAVUTIL_VERSION_INT,
01185 };
01186
01187 AVCodec ff_vc1_crystalhd_decoder = {
01188 .name = "vc1_crystalhd",
01189 .type = AVMEDIA_TYPE_VIDEO,
01190 .id = CODEC_ID_VC1,
01191 .priv_data_size = sizeof(CHDContext),
01192 .init = init,
01193 .close = uninit,
01194 .decode = decode,
01195 .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY,
01196 .flush = flush,
01197 .long_name = NULL_IF_CONFIG_SMALL("SMPTE VC-1 (CrystalHD acceleration)"),
01198 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
01199 .priv_class = &vc1_class,
01200 };
01201 #endif
01202
01203 #if CONFIG_WMV3_CRYSTALHD_DECODER
01204 static AVClass wmv3_class = {
01205 "wmv3_crystalhd",
01206 av_default_item_name,
01207 options,
01208 LIBAVUTIL_VERSION_INT,
01209 };
01210
01211 AVCodec ff_wmv3_crystalhd_decoder = {
01212 .name = "wmv3_crystalhd",
01213 .type = AVMEDIA_TYPE_VIDEO,
01214 .id = CODEC_ID_WMV3,
01215 .priv_data_size = sizeof(CHDContext),
01216 .init = init,
01217 .close = uninit,
01218 .decode = decode,
01219 .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY,
01220 .flush = flush,
01221 .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9 (CrystalHD acceleration)"),
01222 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
01223 .priv_class = &wmv3_class,
01224 };
01225 #endif