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 "libavutil/imgutils.h"
00088 #include "libavutil/intreadwrite.h"
00089
00091 #define OUTPUT_PROC_TIMEOUT 50
00092
00093 #define TIMESTAMP_UNIT 100000
00094
00095 #define BASE_WAIT 10000
00096
00097 #define WAIT_UNIT 1000
00098
00099
00100
00101
00102
00103
00104 typedef enum {
00105 RET_ERROR = -1,
00106 RET_OK = 0,
00107 RET_COPY_AGAIN = 1,
00108 RET_SKIP_NEXT_COPY = 2,
00109 } CopyRet;
00110
00111 typedef struct OpaqueList {
00112 struct OpaqueList *next;
00113 uint64_t fake_timestamp;
00114 uint64_t reordered_opaque;
00115 } OpaqueList;
00116
00117 typedef struct {
00118 AVCodecContext *avctx;
00119 AVFrame pic;
00120 HANDLE dev;
00121
00122 uint8_t is_70012;
00123 uint8_t *sps_pps_buf;
00124 uint32_t sps_pps_size;
00125 uint8_t is_nal;
00126 uint8_t output_ready;
00127 uint8_t need_second_field;
00128 uint8_t skip_next_output;
00129 uint64_t decode_wait;
00130
00131 uint64_t last_picture;
00132
00133 OpaqueList *head;
00134 OpaqueList *tail;
00135 } CHDContext;
00136
00137
00138
00139
00140
00141
00142 static inline BC_MEDIA_SUBTYPE id2subtype(CHDContext *priv, enum CodecID id)
00143 {
00144 switch (id) {
00145 case CODEC_ID_MPEG4:
00146 return BC_MSUBTYPE_DIVX;
00147 case CODEC_ID_MSMPEG4V3:
00148 return BC_MSUBTYPE_DIVX311;
00149 case CODEC_ID_MPEG2VIDEO:
00150 return BC_MSUBTYPE_MPEG2VIDEO;
00151 case CODEC_ID_VC1:
00152 return BC_MSUBTYPE_VC1;
00153 case CODEC_ID_WMV3:
00154 return BC_MSUBTYPE_WMV3;
00155 case CODEC_ID_H264:
00156 return priv->is_nal ? BC_MSUBTYPE_AVC1 : BC_MSUBTYPE_H264;
00157 default:
00158 return BC_MSUBTYPE_INVALID;
00159 }
00160 }
00161
00162 static inline void print_frame_info(CHDContext *priv, BC_DTS_PROC_OUT *output)
00163 {
00164 av_log(priv->avctx, AV_LOG_VERBOSE, "\tYBuffSz: %u\n", output->YbuffSz);
00165 av_log(priv->avctx, AV_LOG_VERBOSE, "\tYBuffDoneSz: %u\n",
00166 output->YBuffDoneSz);
00167 av_log(priv->avctx, AV_LOG_VERBOSE, "\tUVBuffDoneSz: %u\n",
00168 output->UVBuffDoneSz);
00169 av_log(priv->avctx, AV_LOG_VERBOSE, "\tTimestamp: %"PRIu64"\n",
00170 output->PicInfo.timeStamp);
00171 av_log(priv->avctx, AV_LOG_VERBOSE, "\tPicture Number: %u\n",
00172 output->PicInfo.picture_number);
00173 av_log(priv->avctx, AV_LOG_VERBOSE, "\tWidth: %u\n",
00174 output->PicInfo.width);
00175 av_log(priv->avctx, AV_LOG_VERBOSE, "\tHeight: %u\n",
00176 output->PicInfo.height);
00177 av_log(priv->avctx, AV_LOG_VERBOSE, "\tChroma: 0x%03x\n",
00178 output->PicInfo.chroma_format);
00179 av_log(priv->avctx, AV_LOG_VERBOSE, "\tPulldown: %u\n",
00180 output->PicInfo.pulldown);
00181 av_log(priv->avctx, AV_LOG_VERBOSE, "\tFlags: 0x%08x\n",
00182 output->PicInfo.flags);
00183 av_log(priv->avctx, AV_LOG_VERBOSE, "\tFrame Rate/Res: %u\n",
00184 output->PicInfo.frame_rate);
00185 av_log(priv->avctx, AV_LOG_VERBOSE, "\tAspect Ratio: %u\n",
00186 output->PicInfo.aspect_ratio);
00187 av_log(priv->avctx, AV_LOG_VERBOSE, "\tColor Primaries: %u\n",
00188 output->PicInfo.colour_primaries);
00189 av_log(priv->avctx, AV_LOG_VERBOSE, "\tMetaData: %u\n",
00190 output->PicInfo.picture_meta_payload);
00191 av_log(priv->avctx, AV_LOG_VERBOSE, "\tSession Number: %u\n",
00192 output->PicInfo.sess_num);
00193 av_log(priv->avctx, AV_LOG_VERBOSE, "\tycom: %u\n",
00194 output->PicInfo.ycom);
00195 av_log(priv->avctx, AV_LOG_VERBOSE, "\tCustom Aspect: %u\n",
00196 output->PicInfo.custom_aspect_ratio_width_height);
00197 av_log(priv->avctx, AV_LOG_VERBOSE, "\tFrames to Drop: %u\n",
00198 output->PicInfo.n_drop);
00199 av_log(priv->avctx, AV_LOG_VERBOSE, "\tH264 Valid Fields: 0x%08x\n",
00200 output->PicInfo.other.h264.valid);
00201 }
00202
00203
00204
00205
00206
00207
00208 static uint64_t opaque_list_push(CHDContext *priv, uint64_t reordered_opaque)
00209 {
00210 OpaqueList *newNode = av_mallocz(sizeof (OpaqueList));
00211 if (!newNode) {
00212 av_log(priv->avctx, AV_LOG_ERROR,
00213 "Unable to allocate new node in OpaqueList.\n");
00214 return 0;
00215 }
00216 if (!priv->head) {
00217 newNode->fake_timestamp = TIMESTAMP_UNIT;
00218 priv->head = newNode;
00219 } else {
00220 newNode->fake_timestamp = priv->tail->fake_timestamp + TIMESTAMP_UNIT;
00221 priv->tail->next = newNode;
00222 }
00223 priv->tail = newNode;
00224 newNode->reordered_opaque = reordered_opaque;
00225
00226 return newNode->fake_timestamp;
00227 }
00228
00229
00230
00231
00232
00233
00234 static uint64_t opaque_list_pop(CHDContext *priv, uint64_t fake_timestamp)
00235 {
00236 OpaqueList *node = priv->head;
00237
00238 if (!priv->head) {
00239 av_log(priv->avctx, AV_LOG_ERROR,
00240 "CrystalHD: Attempted to query non-existent timestamps.\n");
00241 return AV_NOPTS_VALUE;
00242 }
00243
00244
00245
00246
00247
00248 if (priv->head->fake_timestamp == fake_timestamp) {
00249 uint64_t reordered_opaque = node->reordered_opaque;
00250 priv->head = node->next;
00251 av_free(node);
00252
00253 if (!priv->head->next)
00254 priv->tail = priv->head;
00255
00256 return reordered_opaque;
00257 }
00258
00259
00260
00261
00262
00263 while (node->next) {
00264 OpaqueList *next = node->next;
00265 if (next->fake_timestamp == fake_timestamp) {
00266 uint64_t reordered_opaque = next->reordered_opaque;
00267 node->next = next->next;
00268 av_free(next);
00269
00270 if (!node->next)
00271 priv->tail = node;
00272
00273 return reordered_opaque;
00274 } else {
00275 node = next;
00276 }
00277 }
00278
00279 av_log(priv->avctx, AV_LOG_VERBOSE,
00280 "CrystalHD: Couldn't match fake_timestamp.\n");
00281 return AV_NOPTS_VALUE;
00282 }
00283
00284
00285
00286
00287
00288
00289 static void flush(AVCodecContext *avctx)
00290 {
00291 CHDContext *priv = avctx->priv_data;
00292
00293 avctx->has_b_frames = 0;
00294 priv->last_picture = -1;
00295 priv->output_ready = 0;
00296 priv->need_second_field = 0;
00297 priv->skip_next_output = 0;
00298 priv->decode_wait = BASE_WAIT;
00299
00300 if (priv->pic.data[0])
00301 avctx->release_buffer(avctx, &priv->pic);
00302
00303
00304 DtsFlushInput(priv->dev, 4);
00305 }
00306
00307
00308 static av_cold int uninit(AVCodecContext *avctx)
00309 {
00310 CHDContext *priv = avctx->priv_data;
00311 HANDLE device;
00312
00313 device = priv->dev;
00314 DtsStopDecoder(device);
00315 DtsCloseDecoder(device);
00316 DtsDeviceClose(device);
00317
00318 av_free(priv->sps_pps_buf);
00319
00320 if (priv->pic.data[0])
00321 avctx->release_buffer(avctx, &priv->pic);
00322
00323 if (priv->head) {
00324 OpaqueList *node = priv->head;
00325 while (node) {
00326 OpaqueList *next = node->next;
00327 av_free(node);
00328 node = next;
00329 }
00330 }
00331
00332 return 0;
00333 }
00334
00335
00336 static av_cold int init(AVCodecContext *avctx)
00337 {
00338 CHDContext* priv;
00339 BC_STATUS ret;
00340 BC_INFO_CRYSTAL version;
00341 BC_INPUT_FORMAT format = {
00342 .FGTEnable = FALSE,
00343 .Progressive = TRUE,
00344 .OptFlags = 0x80000000 | vdecFrameRate59_94 | 0x40,
00345 .width = avctx->width,
00346 .height = avctx->height,
00347 };
00348
00349 BC_MEDIA_SUBTYPE subtype;
00350
00351 uint32_t mode = DTS_PLAYBACK_MODE |
00352 DTS_LOAD_FILE_PLAY_FW |
00353 DTS_SKIP_TX_CHK_CPB |
00354 DTS_PLAYBACK_DROP_RPT_MODE |
00355 DTS_SINGLE_THREADED_MODE |
00356 DTS_DFLT_RESOLUTION(vdecRESOLUTION_1080p23_976);
00357
00358 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD Init for %s\n",
00359 avctx->codec->name);
00360
00361 avctx->pix_fmt = PIX_FMT_YUYV422;
00362
00363
00364 priv = avctx->priv_data;
00365 priv->avctx = avctx;
00366 priv->is_nal = avctx->extradata_size > 0 && *(avctx->extradata) == 1;
00367 priv->last_picture = -1;
00368 priv->decode_wait = BASE_WAIT;
00369
00370 subtype = id2subtype(priv, avctx->codec->id);
00371 switch (subtype) {
00372 case BC_MSUBTYPE_AVC1:
00373 {
00374 uint8_t *dummy_p;
00375 int dummy_int;
00376 AVBitStreamFilterContext *bsfc;
00377
00378 uint32_t orig_data_size = avctx->extradata_size;
00379 uint8_t *orig_data = av_malloc(orig_data_size);
00380 if (!orig_data) {
00381 av_log(avctx, AV_LOG_ERROR,
00382 "Failed to allocate copy of extradata\n");
00383 return AVERROR(ENOMEM);
00384 }
00385 memcpy(orig_data, avctx->extradata, orig_data_size);
00386
00387
00388 bsfc = av_bitstream_filter_init("h264_mp4toannexb");
00389 if (!bsfc) {
00390 av_log(avctx, AV_LOG_ERROR,
00391 "Cannot open the h264_mp4toannexb BSF!\n");
00392 av_free(orig_data);
00393 return AVERROR_BSF_NOT_FOUND;
00394 }
00395 av_bitstream_filter_filter(bsfc, avctx, NULL, &dummy_p,
00396 &dummy_int, NULL, 0, 0);
00397 av_bitstream_filter_close(bsfc);
00398
00399 priv->sps_pps_buf = avctx->extradata;
00400 priv->sps_pps_size = avctx->extradata_size;
00401 avctx->extradata = orig_data;
00402 avctx->extradata_size = orig_data_size;
00403
00404 format.pMetaData = priv->sps_pps_buf;
00405 format.metaDataSz = priv->sps_pps_size;
00406 format.startCodeSz = (avctx->extradata[4] & 0x03) + 1;
00407 }
00408 break;
00409 case BC_MSUBTYPE_H264:
00410 format.startCodeSz = 4;
00411
00412 case BC_MSUBTYPE_VC1:
00413 case BC_MSUBTYPE_WVC1:
00414 case BC_MSUBTYPE_WMV3:
00415 case BC_MSUBTYPE_WMVA:
00416 case BC_MSUBTYPE_MPEG2VIDEO:
00417 case BC_MSUBTYPE_DIVX:
00418 case BC_MSUBTYPE_DIVX311:
00419 format.pMetaData = avctx->extradata;
00420 format.metaDataSz = avctx->extradata_size;
00421 break;
00422 default:
00423 av_log(avctx, AV_LOG_ERROR, "CrystalHD: Unknown codec name\n");
00424 return AVERROR(EINVAL);
00425 }
00426 format.mSubtype = subtype;
00427
00428
00429 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: starting up\n");
00430
00431 ret = DtsDeviceOpen(&priv->dev, mode);
00432 if (ret != BC_STS_SUCCESS) {
00433 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: DtsDeviceOpen failed\n");
00434 goto fail;
00435 }
00436
00437 ret = DtsCrystalHDVersion(priv->dev, &version);
00438 if (ret != BC_STS_SUCCESS) {
00439 av_log(avctx, AV_LOG_VERBOSE,
00440 "CrystalHD: DtsCrystalHDVersion failed\n");
00441 goto fail;
00442 }
00443 priv->is_70012 = version.device == 0;
00444
00445 if (priv->is_70012 &&
00446 (subtype == BC_MSUBTYPE_DIVX || subtype == BC_MSUBTYPE_DIVX311)) {
00447 av_log(avctx, AV_LOG_VERBOSE,
00448 "CrystalHD: BCM70012 doesn't support MPEG4-ASP/DivX/Xvid\n");
00449 goto fail;
00450 }
00451
00452 ret = DtsSetInputFormat(priv->dev, &format);
00453 if (ret != BC_STS_SUCCESS) {
00454 av_log(avctx, AV_LOG_ERROR, "CrystalHD: SetInputFormat failed\n");
00455 goto fail;
00456 }
00457
00458 ret = DtsOpenDecoder(priv->dev, BC_STREAM_TYPE_ES);
00459 if (ret != BC_STS_SUCCESS) {
00460 av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsOpenDecoder failed\n");
00461 goto fail;
00462 }
00463
00464 ret = DtsSetColorSpace(priv->dev, OUTPUT_MODE422_YUY2);
00465 if (ret != BC_STS_SUCCESS) {
00466 av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsSetColorSpace failed\n");
00467 goto fail;
00468 }
00469 ret = DtsStartDecoder(priv->dev);
00470 if (ret != BC_STS_SUCCESS) {
00471 av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsStartDecoder failed\n");
00472 goto fail;
00473 }
00474 ret = DtsStartCapture(priv->dev);
00475 if (ret != BC_STS_SUCCESS) {
00476 av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsStartCapture failed\n");
00477 goto fail;
00478 }
00479
00480 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Init complete.\n");
00481
00482 return 0;
00483
00484 fail:
00485 uninit(avctx);
00486 return -1;
00487 }
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505 #define ASSUME_PAFF_OVER_MBAFF 0
00506 #define ASSUME_TWO_INPUTS_ONE_OUTPUT 0
00507 static inline CopyRet copy_frame(AVCodecContext *avctx,
00508 BC_DTS_PROC_OUT *output,
00509 void *data, int *data_size,
00510 uint8_t second_field)
00511 {
00512 BC_STATUS ret;
00513 BC_DTS_STATUS decoder_status;
00514 uint8_t is_paff;
00515 uint8_t next_frame_same;
00516 uint8_t interlaced;
00517
00518 CHDContext *priv = avctx->priv_data;
00519
00520 uint8_t bottom_field = (output->PicInfo.flags & VDEC_FLAG_BOTTOMFIELD) ==
00521 VDEC_FLAG_BOTTOMFIELD;
00522 uint8_t bottom_first = !!(output->PicInfo.flags & VDEC_FLAG_BOTTOM_FIRST);
00523
00524 int width = output->PicInfo.width;
00525 int height = output->PicInfo.height;
00526 int bwidth;
00527 uint8_t *src = output->Ybuff;
00528 int sStride;
00529 uint8_t *dst;
00530 int dStride;
00531
00532 ret = DtsGetDriverStatus(priv->dev, &decoder_status);
00533 if (ret != BC_STS_SUCCESS) {
00534 av_log(avctx, AV_LOG_ERROR,
00535 "CrystalHD: GetDriverStatus failed: %u\n", ret);
00536 return RET_ERROR;
00537 }
00538
00539 is_paff = ASSUME_PAFF_OVER_MBAFF ||
00540 !(output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC);
00541 next_frame_same = output->PicInfo.picture_number ==
00542 (decoder_status.picNumFlags & ~0x40000000);
00543 interlaced = ((output->PicInfo.flags &
00544 VDEC_FLAG_INTERLACED_SRC) && is_paff) ||
00545 next_frame_same || bottom_field || second_field;
00546
00547 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: next_frame_same: %u | %u | %u\n",
00548 next_frame_same, output->PicInfo.picture_number,
00549 decoder_status.picNumFlags & ~0x40000000);
00550
00551 if (priv->pic.data[0] && !priv->need_second_field)
00552 avctx->release_buffer(avctx, &priv->pic);
00553
00554 priv->need_second_field = interlaced && !priv->need_second_field;
00555
00556 priv->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
00557 FF_BUFFER_HINTS_REUSABLE;
00558 if (!priv->pic.data[0]) {
00559 if (avctx->get_buffer(avctx, &priv->pic) < 0) {
00560 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00561 return RET_ERROR;
00562 }
00563 }
00564
00565 bwidth = av_image_get_linesize(avctx->pix_fmt, width, 0);
00566 if (priv->is_70012) {
00567 int pStride;
00568
00569 if (width <= 720)
00570 pStride = 720;
00571 else if (width <= 1280)
00572 pStride = 1280;
00573 else if (width <= 1080)
00574 pStride = 1080;
00575 sStride = av_image_get_linesize(avctx->pix_fmt, pStride, 0);
00576 } else {
00577 sStride = bwidth;
00578 }
00579
00580 dStride = priv->pic.linesize[0];
00581 dst = priv->pic.data[0];
00582
00583 av_log(priv->avctx, AV_LOG_VERBOSE, "CrystalHD: Copying out frame\n");
00584
00585 if (interlaced) {
00586 int dY = 0;
00587 int sY = 0;
00588
00589 height /= 2;
00590 if (bottom_field) {
00591 av_log(priv->avctx, AV_LOG_VERBOSE, "Interlaced: bottom field\n");
00592 dY = 1;
00593 } else {
00594 av_log(priv->avctx, AV_LOG_VERBOSE, "Interlaced: top field\n");
00595 dY = 0;
00596 }
00597
00598 for (sY = 0; sY < height; dY++, sY++) {
00599 memcpy(&(dst[dY * dStride]), &(src[sY * sStride]), bwidth);
00600 if (interlaced)
00601 dY++;
00602 }
00603 } else {
00604 av_image_copy_plane(dst, dStride, src, sStride, bwidth, height);
00605 }
00606
00607 priv->pic.interlaced_frame = interlaced;
00608 if (interlaced)
00609 priv->pic.top_field_first = !bottom_first;
00610
00611 if (output->PicInfo.timeStamp != 0) {
00612 priv->pic.pkt_pts = opaque_list_pop(priv, output->PicInfo.timeStamp);
00613 av_log(avctx, AV_LOG_VERBOSE, "output \"pts\": %"PRIu64"\n",
00614 priv->pic.pkt_pts);
00615 }
00616
00617 if (!priv->need_second_field) {
00618 *data_size = sizeof(AVFrame);
00619 *(AVFrame *)data = priv->pic;
00620 }
00621
00622 if (ASSUME_TWO_INPUTS_ONE_OUTPUT &&
00623 output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) {
00624 av_log(priv->avctx, AV_LOG_VERBOSE, "Fieldpair from two packets.\n");
00625 return RET_SKIP_NEXT_COPY;
00626 }
00627
00628 return RET_OK;
00629 }
00630
00631
00632 static inline CopyRet receive_frame(AVCodecContext *avctx,
00633 void *data, int *data_size,
00634 uint8_t second_field)
00635 {
00636 BC_STATUS ret;
00637 BC_DTS_PROC_OUT output = {
00638 .PicInfo.width = avctx->width,
00639 .PicInfo.height = avctx->height,
00640 };
00641 CHDContext *priv = avctx->priv_data;
00642 HANDLE dev = priv->dev;
00643
00644 *data_size = 0;
00645
00646
00647 ret = DtsProcOutputNoCopy(dev, OUTPUT_PROC_TIMEOUT, &output);
00648 if (ret == BC_STS_FMT_CHANGE) {
00649 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Initial format change\n");
00650 avctx->width = output.PicInfo.width;
00651 avctx->height = output.PicInfo.height;
00652 return RET_COPY_AGAIN;
00653 } else if (ret == BC_STS_SUCCESS) {
00654 int copy_ret = -1;
00655 if (output.PoutFlags & BC_POUT_FLAGS_PIB_VALID) {
00656 if (priv->last_picture == -1) {
00657
00658
00659
00660
00661 priv->last_picture = output.PicInfo.picture_number - 1;
00662 }
00663
00664 if (avctx->codec->id == CODEC_ID_MPEG4 &&
00665 output.PicInfo.timeStamp == 0) {
00666 av_log(avctx, AV_LOG_VERBOSE,
00667 "CrystalHD: Not returning packed frame twice.\n");
00668 priv->last_picture++;
00669 DtsReleaseOutputBuffs(dev, NULL, FALSE);
00670 return RET_COPY_AGAIN;
00671 }
00672
00673 print_frame_info(priv, &output);
00674
00675 if (priv->last_picture + 1 < output.PicInfo.picture_number) {
00676 av_log(avctx, AV_LOG_WARNING,
00677 "CrystalHD: Picture Number discontinuity\n");
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688 priv->last_picture = output.PicInfo.picture_number - 1;
00689 }
00690
00691 copy_ret = copy_frame(avctx, &output, data, data_size, second_field);
00692 if (*data_size > 0) {
00693 avctx->has_b_frames--;
00694 priv->last_picture++;
00695 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Pipeline length: %u\n",
00696 avctx->has_b_frames);
00697 }
00698 } else {
00699
00700
00701
00702 av_log(avctx, AV_LOG_ERROR, "CrystalHD: ProcOutput succeeded with "
00703 "invalid PIB\n");
00704 avctx->has_b_frames--;
00705 copy_ret = RET_OK;
00706 }
00707 DtsReleaseOutputBuffs(dev, NULL, FALSE);
00708
00709 return copy_ret;
00710 } else if (ret == BC_STS_BUSY) {
00711 return RET_COPY_AGAIN;
00712 } else {
00713 av_log(avctx, AV_LOG_ERROR, "CrystalHD: ProcOutput failed %d\n", ret);
00714 return RET_ERROR;
00715 }
00716 }
00717
00718
00719 static int decode(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt)
00720 {
00721 BC_STATUS ret;
00722 BC_DTS_STATUS decoder_status;
00723 CopyRet rec_ret;
00724 CHDContext *priv = avctx->priv_data;
00725 HANDLE dev = priv->dev;
00726 int len = avpkt->size;
00727
00728 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: decode_frame\n");
00729
00730 if (len) {
00731 int32_t tx_free = (int32_t)DtsTxFreeSize(dev);
00732 if (len < tx_free - 1024) {
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742 uint64_t pts = opaque_list_push(priv, avctx->pkt->pts);
00743 if (!pts) {
00744 return AVERROR(ENOMEM);
00745 }
00746 av_log(priv->avctx, AV_LOG_VERBOSE,
00747 "input \"pts\": %"PRIu64"\n", pts);
00748 ret = DtsProcInput(dev, avpkt->data, len, pts, 0);
00749 if (ret == BC_STS_BUSY) {
00750 av_log(avctx, AV_LOG_WARNING,
00751 "CrystalHD: ProcInput returned busy\n");
00752 usleep(BASE_WAIT);
00753 return AVERROR(EBUSY);
00754 } else if (ret != BC_STS_SUCCESS) {
00755 av_log(avctx, AV_LOG_ERROR,
00756 "CrystalHD: ProcInput failed: %u\n", ret);
00757 return -1;
00758 }
00759 avctx->has_b_frames++;
00760 } else {
00761 av_log(avctx, AV_LOG_WARNING, "CrystalHD: Input buffer full\n");
00762 len = 0;
00763 }
00764 } else {
00765 av_log(avctx, AV_LOG_INFO, "CrystalHD: No more input data\n");
00766 }
00767
00768 if (priv->skip_next_output) {
00769 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Skipping next output.\n");
00770 priv->skip_next_output = 0;
00771 avctx->has_b_frames--;
00772 return len;
00773 }
00774
00775 ret = DtsGetDriverStatus(dev, &decoder_status);
00776 if (ret != BC_STS_SUCCESS) {
00777 av_log(avctx, AV_LOG_ERROR, "CrystalHD: GetDriverStatus failed\n");
00778 return -1;
00779 }
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789 if (priv->output_ready < 2) {
00790 if (decoder_status.ReadyListCount != 0)
00791 priv->output_ready++;
00792 usleep(BASE_WAIT);
00793 av_log(avctx, AV_LOG_INFO, "CrystalHD: Filling pipeline.\n");
00794 return len;
00795 } else if (decoder_status.ReadyListCount == 0) {
00796
00797
00798
00799
00800
00801
00802 usleep(BASE_WAIT);
00803 priv->decode_wait += WAIT_UNIT;
00804 av_log(avctx, AV_LOG_INFO, "CrystalHD: No frames ready. Returning\n");
00805 return len;
00806 }
00807
00808 do {
00809 rec_ret = receive_frame(avctx, data, data_size, 0);
00810 if (rec_ret == 0 && *data_size == 0) {
00811 if (avctx->codec->id == CODEC_ID_H264) {
00812
00813
00814
00815
00816
00817
00818
00819 av_log(avctx, AV_LOG_VERBOSE, "Returning after first field.\n");
00820 avctx->has_b_frames--;
00821 } else {
00822
00823
00824
00825
00826
00827
00828
00829
00830 av_log(avctx, AV_LOG_VERBOSE, "Trying to get second field.\n");
00831 while (1) {
00832 usleep(priv->decode_wait);
00833 ret = DtsGetDriverStatus(dev, &decoder_status);
00834 if (ret == BC_STS_SUCCESS &&
00835 decoder_status.ReadyListCount > 0) {
00836 rec_ret = receive_frame(avctx, data, data_size, 1);
00837 if ((rec_ret == 0 && *data_size > 0) ||
00838 rec_ret == RET_ERROR)
00839 break;
00840 }
00841 }
00842 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Got second field.\n");
00843 }
00844 } else if (rec_ret == RET_SKIP_NEXT_COPY) {
00845
00846
00847
00848 av_log(avctx, AV_LOG_VERBOSE,
00849 "Don't output on next decode call.\n");
00850 priv->skip_next_output = 1;
00851 }
00852
00853
00854
00855
00856
00857
00858
00859
00860 } while (rec_ret == RET_COPY_AGAIN);
00861 usleep(priv->decode_wait);
00862 return len;
00863 }
00864
00865
00866 #if CONFIG_H264_CRYSTALHD_DECODER
00867 AVCodec ff_h264_crystalhd_decoder = {
00868 .name = "h264_crystalhd",
00869 .type = AVMEDIA_TYPE_VIDEO,
00870 .id = CODEC_ID_H264,
00871 .priv_data_size = sizeof(CHDContext),
00872 .init = init,
00873 .close = uninit,
00874 .decode = decode,
00875 .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
00876 .flush = flush,
00877 .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (CrystalHD acceleration)"),
00878 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
00879 };
00880 #endif
00881
00882 #if CONFIG_MPEG2_CRYSTALHD_DECODER
00883 AVCodec ff_mpeg2_crystalhd_decoder = {
00884 .name = "mpeg2_crystalhd",
00885 .type = AVMEDIA_TYPE_VIDEO,
00886 .id = CODEC_ID_MPEG2VIDEO,
00887 .priv_data_size = sizeof(CHDContext),
00888 .init = init,
00889 .close = uninit,
00890 .decode = decode,
00891 .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
00892 .flush = flush,
00893 .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 Video (CrystalHD acceleration)"),
00894 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
00895 };
00896 #endif
00897
00898 #if CONFIG_MPEG4_CRYSTALHD_DECODER
00899 AVCodec ff_mpeg4_crystalhd_decoder = {
00900 .name = "mpeg4_crystalhd",
00901 .type = AVMEDIA_TYPE_VIDEO,
00902 .id = CODEC_ID_MPEG4,
00903 .priv_data_size = sizeof(CHDContext),
00904 .init = init,
00905 .close = uninit,
00906 .decode = decode,
00907 .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
00908 .flush = flush,
00909 .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 Part 2 (CrystalHD acceleration)"),
00910 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
00911 };
00912 #endif
00913
00914 #if CONFIG_MSMPEG4_CRYSTALHD_DECODER
00915 AVCodec ff_msmpeg4_crystalhd_decoder = {
00916 .name = "msmpeg4_crystalhd",
00917 .type = AVMEDIA_TYPE_VIDEO,
00918 .id = CODEC_ID_MSMPEG4V3,
00919 .priv_data_size = sizeof(CHDContext),
00920 .init = init,
00921 .close = uninit,
00922 .decode = decode,
00923 .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
00924 .flush = flush,
00925 .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 Part 2 Microsoft variant version 3 (CrystalHD acceleration)"),
00926 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
00927 };
00928 #endif
00929
00930 #if CONFIG_VC1_CRYSTALHD_DECODER
00931 AVCodec ff_vc1_crystalhd_decoder = {
00932 .name = "vc1_crystalhd",
00933 .type = AVMEDIA_TYPE_VIDEO,
00934 .id = CODEC_ID_VC1,
00935 .priv_data_size = sizeof(CHDContext),
00936 .init = init,
00937 .close = uninit,
00938 .decode = decode,
00939 .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
00940 .flush = flush,
00941 .long_name = NULL_IF_CONFIG_SMALL("SMPTE VC-1 (CrystalHD acceleration)"),
00942 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
00943 };
00944 #endif
00945
00946 #if CONFIG_WMV3_CRYSTALHD_DECODER
00947 AVCodec ff_wmv3_crystalhd_decoder = {
00948 .name = "wmv3_crystalhd",
00949 .type = AVMEDIA_TYPE_VIDEO,
00950 .id = CODEC_ID_WMV3,
00951 .priv_data_size = sizeof(CHDContext),
00952 .init = init,
00953 .close = uninit,
00954 .decode = decode,
00955 .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
00956 .flush = flush,
00957 .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9 (CrystalHD acceleration)"),
00958 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
00959 };
00960 #endif