--- ffmpeg-dmo-0.10.3/libavcodec/crystalhd.c.53 2012-12-27 15:56:05.000000000 +0100 +++ ffmpeg-dmo-0.10.3/libavcodec/crystalhd.c.54-bpo 2012-12-27 16:46:52.000000000 +0100 @@ -43,7 +43,7 @@ * on testing, the code will wait until 3 pictures are ready before starting * to copy out - and this has the effect of extending the pipeline. * - * Finally, while it is tempting to say that once the decoder starts outputing + * Finally, while it is tempting to say that once the decoder starts outputting * frames, the software should never fail to return a frame from a decode(), * this is a hard assertion to make, because the stream may switch between * differently encoded content (number of b-frames, interlacing, etc) which @@ -85,6 +85,7 @@ #include "avcodec.h" #include "h264.h" +#include "internal.h" #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" #include "libavutil/opt.h" @@ -153,7 +154,7 @@ { "crystalhd_downscale_width", "Turn on downscaling to the specified width", offsetof(CHDContext, sWidth), - AV_OPT_TYPE_INT, 0, 0, UINT32_MAX, + AV_OPT_TYPE_INT, {.i64 = 0}, 0, UINT32_MAX, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM, }, { NULL, }, }; @@ -535,7 +536,7 @@ static inline CopyRet copy_frame(AVCodecContext *avctx, BC_DTS_PROC_OUT *output, - void *data, int *data_size) + void *data, int *got_frame) { BC_STATUS ret; BC_DTS_STATUS decoder_status = { 0, }; @@ -656,8 +657,7 @@ pStride = 720; else if (width <= 1280) pStride = 1280; - else if (width <= 1080) - pStride = 1080; + else pStride = 1920; sStride = av_image_get_linesize(avctx->pix_fmt, pStride, 0); } else { sStride = bwidth; @@ -696,7 +696,7 @@ priv->pic.pkt_pts = pkt_pts; if (!priv->need_second_field) { - *data_size = sizeof(AVFrame); + *got_frame = 1; *(AVFrame *)data = priv->pic; } @@ -714,17 +714,26 @@ } /* - * Testing has shown that in all cases where we don't want to return the - * full frame immediately, VDEC_FLAG_UNKNOWN_SRC is set. + * The logic here is purely based on empirical testing with samples. + * If we need a second field, it could come from a second input packet, + * or it could come from the same field-pair input packet at the current + * field. In the first case, we should return and wait for the next time + * round to get the second field, while in the second case, we should + * ask the decoder for it immediately. + * + * Testing has shown that we are dealing with the fieldpair -> two fields + * case if the VDEC_FLAG_UNKNOWN_SRC is not set or if the input picture + * type was PICT_FRAME (in this second case, the flag might still be set) */ return priv->need_second_field && - !(output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) ? + (!(output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) || + pic_type == PICT_FRAME) ? RET_COPY_NEXT_FIELD : RET_OK; } static inline CopyRet receive_frame(AVCodecContext *avctx, - void *data, int *data_size) + void *data, int *got_frame) { BC_STATUS ret; BC_DTS_PROC_OUT output = { @@ -734,7 +743,7 @@ CHDContext *priv = avctx->priv_data; HANDLE dev = priv->dev; - *data_size = 0; + *got_frame = 0; // Request decoded data from the driver ret = DtsProcOutputNoCopy(dev, OUTPUT_PROC_TIMEOUT, &output); @@ -742,6 +751,56 @@ av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Initial format change\n"); avctx->width = output.PicInfo.width; avctx->height = output.PicInfo.height; + switch ( output.PicInfo.aspect_ratio ) { + case vdecAspectRatioSquare: + avctx->sample_aspect_ratio = (AVRational) { 1, 1}; + break; + case vdecAspectRatio12_11: + avctx->sample_aspect_ratio = (AVRational) { 12, 11}; + break; + case vdecAspectRatio10_11: + avctx->sample_aspect_ratio = (AVRational) { 10, 11}; + break; + case vdecAspectRatio16_11: + avctx->sample_aspect_ratio = (AVRational) { 16, 11}; + break; + case vdecAspectRatio40_33: + avctx->sample_aspect_ratio = (AVRational) { 40, 33}; + break; + case vdecAspectRatio24_11: + avctx->sample_aspect_ratio = (AVRational) { 24, 11}; + break; + case vdecAspectRatio20_11: + avctx->sample_aspect_ratio = (AVRational) { 20, 11}; + break; + case vdecAspectRatio32_11: + avctx->sample_aspect_ratio = (AVRational) { 32, 11}; + break; + case vdecAspectRatio80_33: + avctx->sample_aspect_ratio = (AVRational) { 80, 33}; + break; + case vdecAspectRatio18_11: + avctx->sample_aspect_ratio = (AVRational) { 18, 11}; + break; + case vdecAspectRatio15_11: + avctx->sample_aspect_ratio = (AVRational) { 15, 11}; + break; + case vdecAspectRatio64_33: + avctx->sample_aspect_ratio = (AVRational) { 64, 33}; + break; + case vdecAspectRatio160_99: + avctx->sample_aspect_ratio = (AVRational) {160, 99}; + break; + case vdecAspectRatio4_3: + avctx->sample_aspect_ratio = (AVRational) { 4, 3}; + break; + case vdecAspectRatio16_9: + avctx->sample_aspect_ratio = (AVRational) { 16, 9}; + break; + case vdecAspectRatio221_1: + avctx->sample_aspect_ratio = (AVRational) {221, 1}; + break; + } return RET_COPY_AGAIN; } else if (ret == BC_STS_SUCCESS) { int copy_ret = -1; @@ -781,8 +840,8 @@ priv->last_picture = output.PicInfo.picture_number - 1; } - copy_ret = copy_frame(avctx, &output, data, data_size); - if (*data_size > 0) { + copy_ret = copy_frame(avctx, &output, data, got_frame); + if (*got_frame > 0) { avctx->has_b_frames--; priv->last_picture++; av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Pipeline length: %u\n", @@ -809,7 +868,7 @@ } -static int decode(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) +static int decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { BC_STATUS ret; BC_DTS_STATUS decoder_status = { 0, }; @@ -869,7 +928,7 @@ av_log(avctx, AV_LOG_WARNING, "CrystalHD: Failed to parse h.264 packet " "completely. Interlaced frames may be " - "incorrectly detected\n."); + "incorrectly detected.\n"); } else { av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: parser picture type %d\n", @@ -967,8 +1026,8 @@ } do { - rec_ret = receive_frame(avctx, data, data_size); - if (rec_ret == RET_OK && *data_size == 0) { + rec_ret = receive_frame(avctx, data, got_frame); + if (rec_ret == RET_OK && *got_frame == 0) { /* * This case is for when the encoded fields are stored * separately and we get a separate avpkt for each one. To keep @@ -993,8 +1052,8 @@ ret = DtsGetDriverStatus(dev, &decoder_status); if (ret == BC_STS_SUCCESS && decoder_status.ReadyListCount > 0) { - rec_ret = receive_frame(avctx, data, data_size); - if ((rec_ret == RET_OK && *data_size > 0) || + rec_ret = receive_frame(avctx, data, got_frame); + if ((rec_ret == RET_OK && *got_frame > 0) || rec_ret == RET_ERROR) break; }