@@ -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;
}