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       FF_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             uint32_t orig_data_size = avctx->extradata_size;
00406             uint8_t *orig_data = av_malloc(orig_data_size);
00407             if (!orig_data) {
00408                 av_log(avctx, AV_LOG_ERROR,
00409                        "Failed to allocate copy of extradata\n");
00410                 return AVERROR(ENOMEM);
00411             }
00412             memcpy(orig_data, avctx->extradata, orig_data_size);
00413 
00414 
00415             priv->bsfc = av_bitstream_filter_init("h264_mp4toannexb");
00416             if (!priv->bsfc) {
00417                 av_log(avctx, AV_LOG_ERROR,
00418                        "Cannot open the h264_mp4toannexb BSF!\n");
00419                 av_free(orig_data);
00420                 return AVERROR_BSF_NOT_FOUND;
00421             }
00422             av_bitstream_filter_filter(priv->bsfc, avctx, NULL, &dummy_p,
00423                                        &dummy_int, NULL, 0, 0);
00424 
00425             priv->sps_pps_buf     = avctx->extradata;
00426             priv->sps_pps_size    = avctx->extradata_size;
00427             avctx->extradata      = orig_data;
00428             avctx->extradata_size = orig_data_size;
00429 
00430             format.pMetaData   = priv->sps_pps_buf;
00431             format.metaDataSz  = priv->sps_pps_size;
00432             format.startCodeSz = (avctx->extradata[4] & 0x03) + 1;
00433         }
00434         break;
00435     case BC_MSUBTYPE_H264:
00436         format.startCodeSz = 4;
00437         
00438     case BC_MSUBTYPE_VC1:
00439     case BC_MSUBTYPE_WVC1:
00440     case BC_MSUBTYPE_WMV3:
00441     case BC_MSUBTYPE_WMVA:
00442     case BC_MSUBTYPE_MPEG2VIDEO:
00443     case BC_MSUBTYPE_DIVX:
00444     case BC_MSUBTYPE_DIVX311:
00445         format.pMetaData  = avctx->extradata;
00446         format.metaDataSz = avctx->extradata_size;
00447         break;
00448     default:
00449         av_log(avctx, AV_LOG_ERROR, "CrystalHD: Unknown codec name\n");
00450         return AVERROR(EINVAL);
00451     }
00452     format.mSubtype = subtype;
00453 
00454     if (priv->sWidth) {
00455         format.bEnableScaling = 1;
00456         format.ScalingParams.sWidth = priv->sWidth;
00457     }
00458 
00459     
00460     av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: starting up\n");
00461     
00462     ret = DtsDeviceOpen(&priv->dev, mode);
00463     if (ret != BC_STS_SUCCESS) {
00464         av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: DtsDeviceOpen failed\n");
00465         goto fail;
00466     }
00467 
00468     ret = DtsCrystalHDVersion(priv->dev, &version);
00469     if (ret != BC_STS_SUCCESS) {
00470         av_log(avctx, AV_LOG_VERBOSE,
00471                "CrystalHD: DtsCrystalHDVersion failed\n");
00472         goto fail;
00473     }
00474     priv->is_70012 = version.device == 0;
00475 
00476     if (priv->is_70012 &&
00477         (subtype == BC_MSUBTYPE_DIVX || subtype == BC_MSUBTYPE_DIVX311)) {
00478         av_log(avctx, AV_LOG_VERBOSE,
00479                "CrystalHD: BCM70012 doesn't support MPEG4-ASP/DivX/Xvid\n");
00480         goto fail;
00481     }
00482 
00483     ret = DtsSetInputFormat(priv->dev, &format);
00484     if (ret != BC_STS_SUCCESS) {
00485         av_log(avctx, AV_LOG_ERROR, "CrystalHD: SetInputFormat failed\n");
00486         goto fail;
00487     }
00488 
00489     ret = DtsOpenDecoder(priv->dev, BC_STREAM_TYPE_ES);
00490     if (ret != BC_STS_SUCCESS) {
00491         av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsOpenDecoder failed\n");
00492         goto fail;
00493     }
00494 
00495     ret = DtsSetColorSpace(priv->dev, OUTPUT_MODE422_YUY2);
00496     if (ret != BC_STS_SUCCESS) {
00497         av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsSetColorSpace failed\n");
00498         goto fail;
00499     }
00500     ret = DtsStartDecoder(priv->dev);
00501     if (ret != BC_STS_SUCCESS) {
00502         av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsStartDecoder failed\n");
00503         goto fail;
00504     }
00505     ret = DtsStartCapture(priv->dev);
00506     if (ret != BC_STS_SUCCESS) {
00507         av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsStartCapture failed\n");
00508         goto fail;
00509     }
00510 
00511     if (avctx->codec->id == CODEC_ID_H264) {
00512         priv->parser = av_parser_init(avctx->codec->id);
00513         if (!priv->parser)
00514             av_log(avctx, AV_LOG_WARNING,
00515                    "Cannot open the h.264 parser! Interlaced h.264 content "
00516                    "will not be detected reliably.\n");
00517         priv->parser->flags = PARSER_FLAG_COMPLETE_FRAMES;
00518     }
00519     av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Init complete.\n");
00520 
00521     return 0;
00522 
00523  fail:
00524     uninit(avctx);
00525     return -1;
00526 }
00527 
00528 
00529 static inline CopyRet copy_frame(AVCodecContext *avctx,
00530                                  BC_DTS_PROC_OUT *output,
00531                                  void *data, int *data_size)
00532 {
00533     BC_STATUS ret;
00534     BC_DTS_STATUS decoder_status;
00535     uint8_t trust_interlaced;
00536     uint8_t interlaced;
00537 
00538     CHDContext *priv = avctx->priv_data;
00539     int64_t pkt_pts  = AV_NOPTS_VALUE;
00540     uint8_t pic_type = 0;
00541 
00542     uint8_t bottom_field = (output->PicInfo.flags & VDEC_FLAG_BOTTOMFIELD) ==
00543                            VDEC_FLAG_BOTTOMFIELD;
00544     uint8_t bottom_first = !!(output->PicInfo.flags & VDEC_FLAG_BOTTOM_FIRST);
00545 
00546     int width    = output->PicInfo.width;
00547     int height   = output->PicInfo.height;
00548     int bwidth;
00549     uint8_t *src = output->Ybuff;
00550     int sStride;
00551     uint8_t *dst;
00552     int dStride;
00553 
00554     if (output->PicInfo.timeStamp != 0) {
00555         OpaqueList *node = opaque_list_pop(priv, output->PicInfo.timeStamp);
00556         if (node) {
00557             pkt_pts = node->reordered_opaque;
00558             pic_type = node->pic_type;
00559             av_free(node);
00560         } else {
00561             
00562 
00563 
00564 
00565 
00566 
00567 
00568 
00569             pic_type = PICT_BOTTOM_FIELD;
00570         }
00571         av_log(avctx, AV_LOG_VERBOSE, "output \"pts\": %"PRIu64"\n",
00572                output->PicInfo.timeStamp);
00573         av_log(avctx, AV_LOG_VERBOSE, "output picture type %d\n",
00574                pic_type);
00575     }
00576 
00577     ret = DtsGetDriverStatus(priv->dev, &decoder_status);
00578     if (ret != BC_STS_SUCCESS) {
00579         av_log(avctx, AV_LOG_ERROR,
00580                "CrystalHD: GetDriverStatus failed: %u\n", ret);
00581        return RET_ERROR;
00582     }
00583 
00584     
00585 
00586 
00587 
00588 
00589 
00590 
00591 
00592 
00593 
00594 
00595 
00596 
00597 
00598 
00599 
00600     trust_interlaced = avctx->codec->id != CODEC_ID_H264 ||
00601                        !(output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) ||
00602                        priv->need_second_field ||
00603                        (decoder_status.picNumFlags & ~0x40000000) ==
00604                        output->PicInfo.picture_number;
00605 
00606     
00607 
00608 
00609 
00610 
00611 
00612     if (output->PicInfo.picture_number == priv->last_picture && !priv->need_second_field) {
00613         av_log(avctx, AV_LOG_WARNING,
00614                "Incorrectly guessed progressive frame. Discarding second field\n");
00615         
00616         return RET_OK;
00617     }
00618 
00619     interlaced = (output->PicInfo.flags & VDEC_FLAG_INTERLACED_SRC) &&
00620                  trust_interlaced;
00621 
00622     if (!trust_interlaced && (decoder_status.picNumFlags & ~0x40000000) == 0) {
00623         av_log(avctx, AV_LOG_VERBOSE,
00624                "Next picture number unknown. Assuming progressive frame.\n");
00625     }
00626 
00627     av_log(avctx, AV_LOG_VERBOSE, "Interlaced state: %d | trust_interlaced %d\n",
00628            interlaced, trust_interlaced);
00629 
00630     if (priv->pic.data[0] && !priv->need_second_field)
00631         avctx->release_buffer(avctx, &priv->pic);
00632 
00633     priv->need_second_field = interlaced && !priv->need_second_field;
00634 
00635     priv->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
00636                              FF_BUFFER_HINTS_REUSABLE;
00637     if (!priv->pic.data[0]) {
00638         if (avctx->get_buffer(avctx, &priv->pic) < 0) {
00639             av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00640             return RET_ERROR;
00641         }
00642     }
00643 
00644     bwidth = av_image_get_linesize(avctx->pix_fmt, width, 0);
00645     if (priv->is_70012) {
00646         int pStride;
00647 
00648         if (width <= 720)
00649             pStride = 720;
00650         else if (width <= 1280)
00651             pStride = 1280;
00652         else if (width <= 1080)
00653             pStride = 1080;
00654         sStride = av_image_get_linesize(avctx->pix_fmt, pStride, 0);
00655     } else {
00656         sStride = bwidth;
00657     }
00658 
00659     dStride = priv->pic.linesize[0];
00660     dst     = priv->pic.data[0];
00661 
00662     av_log(priv->avctx, AV_LOG_VERBOSE, "CrystalHD: Copying out frame\n");
00663 
00664     if (interlaced) {
00665         int dY = 0;
00666         int sY = 0;
00667 
00668         height /= 2;
00669         if (bottom_field) {
00670             av_log(priv->avctx, AV_LOG_VERBOSE, "Interlaced: bottom field\n");
00671             dY = 1;
00672         } else {
00673             av_log(priv->avctx, AV_LOG_VERBOSE, "Interlaced: top field\n");
00674             dY = 0;
00675         }
00676 
00677         for (sY = 0; sY < height; dY++, sY++) {
00678             memcpy(&(dst[dY * dStride]), &(src[sY * sStride]), bwidth);
00679             dY++;
00680         }
00681     } else {
00682         av_image_copy_plane(dst, dStride, src, sStride, bwidth, height);
00683     }
00684 
00685     priv->pic.interlaced_frame = interlaced;
00686     if (interlaced)
00687         priv->pic.top_field_first = !bottom_first;
00688 
00689     priv->pic.pkt_pts = pkt_pts;
00690 
00691     if (!priv->need_second_field) {
00692         *data_size       = sizeof(AVFrame);
00693         *(AVFrame *)data = priv->pic;
00694     }
00695 
00696     
00697 
00698 
00699 
00700 
00701 
00702 
00703     if (!interlaced && (output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) &&
00704         (pic_type == PICT_TOP_FIELD || pic_type == PICT_BOTTOM_FIELD)) {
00705         av_log(priv->avctx, AV_LOG_VERBOSE, "Fieldpair from two packets.\n");
00706         return RET_SKIP_NEXT_COPY;
00707     }
00708 
00709     
00710 
00711 
00712 
00713     return priv->need_second_field &&
00714            !(output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) ?
00715            RET_COPY_NEXT_FIELD : RET_OK;
00716 }
00717 
00718 
00719 static inline CopyRet receive_frame(AVCodecContext *avctx,
00720                                     void *data, int *data_size)
00721 {
00722     BC_STATUS ret;
00723     BC_DTS_PROC_OUT output = {
00724         .PicInfo.width  = avctx->width,
00725         .PicInfo.height = avctx->height,
00726     };
00727     CHDContext *priv = avctx->priv_data;
00728     HANDLE dev       = priv->dev;
00729 
00730     *data_size = 0;
00731 
00732     
00733     ret = DtsProcOutputNoCopy(dev, OUTPUT_PROC_TIMEOUT, &output);
00734     if (ret == BC_STS_FMT_CHANGE) {
00735         av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Initial format change\n");
00736         avctx->width  = output.PicInfo.width;
00737         avctx->height = output.PicInfo.height;
00738         return RET_COPY_AGAIN;
00739     } else if (ret == BC_STS_SUCCESS) {
00740         int copy_ret = -1;
00741         if (output.PoutFlags & BC_POUT_FLAGS_PIB_VALID) {
00742             if (priv->last_picture == -1) {
00743                 
00744 
00745 
00746 
00747                 priv->last_picture = output.PicInfo.picture_number - 1;
00748             }
00749 
00750             if (avctx->codec->id == CODEC_ID_MPEG4 &&
00751                 output.PicInfo.timeStamp == 0 && priv->bframe_bug) {
00752                 av_log(avctx, AV_LOG_VERBOSE,
00753                        "CrystalHD: Not returning packed frame twice.\n");
00754                 priv->last_picture++;
00755                 DtsReleaseOutputBuffs(dev, NULL, FALSE);
00756                 return RET_COPY_AGAIN;
00757             }
00758 
00759             print_frame_info(priv, &output);
00760 
00761             if (priv->last_picture + 1 < output.PicInfo.picture_number) {
00762                 av_log(avctx, AV_LOG_WARNING,
00763                        "CrystalHD: Picture Number discontinuity\n");
00764                 
00765 
00766 
00767 
00768 
00769 
00770 
00771 
00772 
00773 
00774                priv->last_picture = output.PicInfo.picture_number - 1;
00775             }
00776 
00777             copy_ret = copy_frame(avctx, &output, data, data_size);
00778             if (*data_size > 0) {
00779                 avctx->has_b_frames--;
00780                 priv->last_picture++;
00781                 av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Pipeline length: %u\n",
00782                        avctx->has_b_frames);
00783             }
00784         } else {
00785             
00786 
00787 
00788             av_log(avctx, AV_LOG_ERROR, "CrystalHD: ProcOutput succeeded with "
00789                                         "invalid PIB\n");
00790             avctx->has_b_frames--;
00791             copy_ret = RET_OK;
00792         }
00793         DtsReleaseOutputBuffs(dev, NULL, FALSE);
00794 
00795         return copy_ret;
00796     } else if (ret == BC_STS_BUSY) {
00797         return RET_COPY_AGAIN;
00798     } else {
00799         av_log(avctx, AV_LOG_ERROR, "CrystalHD: ProcOutput failed %d\n", ret);
00800         return RET_ERROR;
00801     }
00802 }
00803 
00804 
00805 static int decode(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt)
00806 {
00807     BC_STATUS ret;
00808     BC_DTS_STATUS decoder_status;
00809     CopyRet rec_ret;
00810     CHDContext *priv   = avctx->priv_data;
00811     HANDLE dev         = priv->dev;
00812     int len            = avpkt->size;
00813     uint8_t pic_type   = 0;
00814 
00815     av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: decode_frame\n");
00816 
00817     if (avpkt->size == 7 && !priv->bframe_bug) {
00818         
00819 
00820 
00821         av_log(avctx, AV_LOG_INFO,
00822                "CrystalHD: Enabling work-around for packed b-frame bug\n");
00823         priv->bframe_bug = 1;
00824     } else if (avpkt->size == 8 && priv->bframe_bug) {
00825         
00826 
00827 
00828         av_log(avctx, AV_LOG_INFO,
00829                "CrystalHD: Disabling work-around for packed b-frame bug\n");
00830         priv->bframe_bug = 0;
00831     }
00832 
00833     if (len) {
00834         int32_t tx_free = (int32_t)DtsTxFreeSize(dev);
00835 
00836         if (priv->parser) {
00837             uint8_t *in_data = avpkt->data;
00838             int in_len = len;
00839             int ret = 0;
00840 
00841             if (priv->bsfc) {
00842                 ret = av_bitstream_filter_filter(priv->bsfc, avctx, NULL,
00843                                                  &in_data, &in_len,
00844                                                  avpkt->data, len, 0);
00845             }
00846 
00847             if (ret >= 0) {
00848                 uint8_t *pout;
00849                 int psize;
00850                 int index;
00851                 H264Context *h = priv->parser->priv_data;
00852 
00853                 index = av_parser_parse2(priv->parser, avctx, &pout, &psize,
00854                                          in_data, in_len, avctx->pkt->pts,
00855                                          avctx->pkt->dts, 0);
00856                 if (index < 0) {
00857                     av_log(avctx, AV_LOG_WARNING,
00858                            "CrystalHD: Failed to parse h.264 packet to "
00859                            "detect interlacing.\n");
00860                 } else if (index != in_len) {
00861                     av_log(avctx, AV_LOG_WARNING,
00862                            "CrystalHD: Failed to parse h.264 packet "
00863                            "completely. Interlaced frames may be "
00864                            "incorrectly detected\n.");
00865                 } else {
00866                     av_log(avctx, AV_LOG_VERBOSE,
00867                            "CrystalHD: parser picture type %d\n",
00868                            h->s.picture_structure);
00869                     pic_type = h->s.picture_structure;
00870                 }
00871             } else {
00872                 av_log(avctx, AV_LOG_WARNING,
00873                        "CrystalHD: mp4toannexb filter failed to filter "
00874                        "packet. Interlaced frames may be incorrectly "
00875                        "detected.\n");
00876             }
00877             if (ret > 0) {
00878                 av_freep(&in_data);
00879             }
00880         }
00881 
00882         if (len < tx_free - 1024) {
00883             
00884 
00885 
00886 
00887 
00888 
00889 
00890 
00891 
00892             uint64_t pts = opaque_list_push(priv, avctx->pkt->pts, pic_type);
00893             if (!pts) {
00894                 return AVERROR(ENOMEM);
00895             }
00896             av_log(priv->avctx, AV_LOG_VERBOSE,
00897                    "input \"pts\": %"PRIu64"\n", pts);
00898             ret = DtsProcInput(dev, avpkt->data, len, pts, 0);
00899             if (ret == BC_STS_BUSY) {
00900                 av_log(avctx, AV_LOG_WARNING,
00901                        "CrystalHD: ProcInput returned busy\n");
00902                 usleep(BASE_WAIT);
00903                 return AVERROR(EBUSY);
00904             } else if (ret != BC_STS_SUCCESS) {
00905                 av_log(avctx, AV_LOG_ERROR,
00906                        "CrystalHD: ProcInput failed: %u\n", ret);
00907                 return -1;
00908             }
00909             avctx->has_b_frames++;
00910         } else {
00911             av_log(avctx, AV_LOG_WARNING, "CrystalHD: Input buffer full\n");
00912             len = 0; 
00913         }
00914     } else {
00915         av_log(avctx, AV_LOG_INFO, "CrystalHD: No more input data\n");
00916     }
00917 
00918     if (priv->skip_next_output) {
00919         av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Skipping next output.\n");
00920         priv->skip_next_output = 0;
00921         avctx->has_b_frames--;
00922         return len;
00923     }
00924 
00925     ret = DtsGetDriverStatus(dev, &decoder_status);
00926     if (ret != BC_STS_SUCCESS) {
00927         av_log(avctx, AV_LOG_ERROR, "CrystalHD: GetDriverStatus failed\n");
00928         return -1;
00929     }
00930 
00931     
00932 
00933 
00934 
00935 
00936 
00937 
00938 
00939     if (priv->output_ready < 2) {
00940         if (decoder_status.ReadyListCount != 0)
00941             priv->output_ready++;
00942         usleep(BASE_WAIT);
00943         av_log(avctx, AV_LOG_INFO, "CrystalHD: Filling pipeline.\n");
00944         return len;
00945     } else if (decoder_status.ReadyListCount == 0) {
00946         
00947 
00948 
00949 
00950 
00951 
00952         usleep(BASE_WAIT);
00953         priv->decode_wait += WAIT_UNIT;
00954         av_log(avctx, AV_LOG_INFO, "CrystalHD: No frames ready. Returning\n");
00955         return len;
00956     }
00957 
00958     do {
00959         rec_ret = receive_frame(avctx, data, data_size);
00960         if (rec_ret == RET_OK && *data_size == 0) {
00961             
00962 
00963 
00964 
00965 
00966 
00967 
00968             av_log(avctx, AV_LOG_VERBOSE, "Returning after first field.\n");
00969             avctx->has_b_frames--;
00970         } else if (rec_ret == RET_COPY_NEXT_FIELD) {
00971             
00972 
00973 
00974 
00975 
00976 
00977 
00978 
00979             av_log(avctx, AV_LOG_VERBOSE, "Trying to get second field.\n");
00980             while (1) {
00981                 usleep(priv->decode_wait);
00982                 ret = DtsGetDriverStatus(dev, &decoder_status);
00983                 if (ret == BC_STS_SUCCESS &&
00984                     decoder_status.ReadyListCount > 0) {
00985                     rec_ret = receive_frame(avctx, data, data_size);
00986                     if ((rec_ret == RET_OK && *data_size > 0) ||
00987                         rec_ret == RET_ERROR)
00988                         break;
00989                 }
00990             }
00991             av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Got second field.\n");
00992         } else if (rec_ret == RET_SKIP_NEXT_COPY) {
00993             
00994 
00995 
00996             av_log(avctx, AV_LOG_VERBOSE,
00997                    "Don't output on next decode call.\n");
00998             priv->skip_next_output = 1;
00999         }
01000         
01001 
01002 
01003 
01004 
01005 
01006 
01007 
01008     } while (rec_ret == RET_COPY_AGAIN);
01009     usleep(priv->decode_wait);
01010     return len;
01011 }
01012 
01013 
01014 #if CONFIG_H264_CRYSTALHD_DECODER
01015 static AVClass h264_class = {
01016     "h264_crystalhd",
01017     av_default_item_name,
01018     options,
01019     LIBAVUTIL_VERSION_INT,
01020 };
01021 
01022 AVCodec ff_h264_crystalhd_decoder = {
01023     .name           = "h264_crystalhd",
01024     .type           = AVMEDIA_TYPE_VIDEO,
01025     .id             = CODEC_ID_H264,
01026     .priv_data_size = sizeof(CHDContext),
01027     .init           = init,
01028     .close          = uninit,
01029     .decode         = decode,
01030     .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
01031     .flush          = flush,
01032     .long_name      = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (CrystalHD acceleration)"),
01033     .pix_fmts       = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
01034     .priv_class     = &h264_class,
01035 };
01036 #endif
01037 
01038 #if CONFIG_MPEG2_CRYSTALHD_DECODER
01039 static AVClass mpeg2_class = {
01040     "mpeg2_crystalhd",
01041     av_default_item_name,
01042     options,
01043     LIBAVUTIL_VERSION_INT,
01044 };
01045 
01046 AVCodec ff_mpeg2_crystalhd_decoder = {
01047     .name           = "mpeg2_crystalhd",
01048     .type           = AVMEDIA_TYPE_VIDEO,
01049     .id             = CODEC_ID_MPEG2VIDEO,
01050     .priv_data_size = sizeof(CHDContext),
01051     .init           = init,
01052     .close          = uninit,
01053     .decode         = decode,
01054     .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
01055     .flush          = flush,
01056     .long_name      = NULL_IF_CONFIG_SMALL("MPEG-2 Video (CrystalHD acceleration)"),
01057     .pix_fmts       = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
01058     .priv_class     = &mpeg2_class,
01059 };
01060 #endif
01061 
01062 #if CONFIG_MPEG4_CRYSTALHD_DECODER
01063 static AVClass mpeg4_class = {
01064     "mpeg4_crystalhd",
01065     av_default_item_name,
01066     options,
01067     LIBAVUTIL_VERSION_INT,
01068 };
01069 
01070 AVCodec ff_mpeg4_crystalhd_decoder = {
01071     .name           = "mpeg4_crystalhd",
01072     .type           = AVMEDIA_TYPE_VIDEO,
01073     .id             = CODEC_ID_MPEG4,
01074     .priv_data_size = sizeof(CHDContext),
01075     .init           = init,
01076     .close          = uninit,
01077     .decode         = decode,
01078     .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
01079     .flush          = flush,
01080     .long_name      = NULL_IF_CONFIG_SMALL("MPEG-4 Part 2 (CrystalHD acceleration)"),
01081     .pix_fmts       = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
01082     .priv_class     = &mpeg4_class,
01083 };
01084 #endif
01085 
01086 #if CONFIG_MSMPEG4_CRYSTALHD_DECODER
01087 static AVClass msmpeg4_class = {
01088     "msmpeg4_crystalhd",
01089     av_default_item_name,
01090     options,
01091     LIBAVUTIL_VERSION_INT,
01092 };
01093 
01094 AVCodec ff_msmpeg4_crystalhd_decoder = {
01095     .name           = "msmpeg4_crystalhd",
01096     .type           = AVMEDIA_TYPE_VIDEO,
01097     .id             = CODEC_ID_MSMPEG4V3,
01098     .priv_data_size = sizeof(CHDContext),
01099     .init           = init,
01100     .close          = uninit,
01101     .decode         = decode,
01102     .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
01103     .flush          = flush,
01104     .long_name      = NULL_IF_CONFIG_SMALL("MPEG-4 Part 2 Microsoft variant version 3 (CrystalHD acceleration)"),
01105     .pix_fmts       = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
01106     .priv_class     = &msmpeg4_class,
01107 };
01108 #endif
01109 
01110 #if CONFIG_VC1_CRYSTALHD_DECODER
01111 static AVClass vc1_class = {
01112     "vc1_crystalhd",
01113     av_default_item_name,
01114     options,
01115     LIBAVUTIL_VERSION_INT,
01116 };
01117 
01118 AVCodec ff_vc1_crystalhd_decoder = {
01119     .name           = "vc1_crystalhd",
01120     .type           = AVMEDIA_TYPE_VIDEO,
01121     .id             = CODEC_ID_VC1,
01122     .priv_data_size = sizeof(CHDContext),
01123     .init           = init,
01124     .close          = uninit,
01125     .decode         = decode,
01126     .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
01127     .flush          = flush,
01128     .long_name      = NULL_IF_CONFIG_SMALL("SMPTE VC-1 (CrystalHD acceleration)"),
01129     .pix_fmts       = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
01130     .priv_class     = &vc1_class,
01131 };
01132 #endif
01133 
01134 #if CONFIG_WMV3_CRYSTALHD_DECODER
01135 static AVClass wmv3_class = {
01136     "wmv3_crystalhd",
01137     av_default_item_name,
01138     options,
01139     LIBAVUTIL_VERSION_INT,
01140 };
01141 
01142 AVCodec ff_wmv3_crystalhd_decoder = {
01143     .name           = "wmv3_crystalhd",
01144     .type           = AVMEDIA_TYPE_VIDEO,
01145     .id             = CODEC_ID_WMV3,
01146     .priv_data_size = sizeof(CHDContext),
01147     .init           = init,
01148     .close          = uninit,
01149     .decode         = decode,
01150     .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
01151     .flush          = flush,
01152     .long_name      = NULL_IF_CONFIG_SMALL("Windows Media Video 9 (CrystalHD acceleration)"),
01153     .pix_fmts       = (const enum PixelFormat[]){PIX_FMT_YUYV422, PIX_FMT_NONE},
01154     .priv_class     = &wmv3_class,
01155 };
01156 #endif