Commit 3019b4f6 authored by Philip Langdale's avatar Philip Langdale

crystalhd: Loop for a frame internally where possible.

It's not possible to return EAGAIN when we've passed input EOF and are
in draining mode. If do return EAGAIN, we're saying there's no way to
get any more output - which isn't true in many cases.

So let's handled these cases in an internal loop as best we can.
parent 0eb83694
...@@ -105,6 +105,7 @@ ...@@ -105,6 +105,7 @@
typedef enum { typedef enum {
RET_ERROR = -1, RET_ERROR = -1,
RET_OK = 0, RET_OK = 0,
RET_COPY_AGAIN = 1,
} CopyRet; } CopyRet;
typedef struct OpaqueList { typedef struct OpaqueList {
...@@ -129,6 +130,7 @@ typedef struct { ...@@ -129,6 +130,7 @@ typedef struct {
uint32_t sps_pps_size; uint32_t sps_pps_size;
uint8_t is_nal; uint8_t is_nal;
uint8_t need_second_field; uint8_t need_second_field;
uint8_t draining;
OpaqueList *head; OpaqueList *head;
OpaqueList *tail; OpaqueList *tail;
...@@ -304,6 +306,7 @@ static void flush(AVCodecContext *avctx) ...@@ -304,6 +306,7 @@ static void flush(AVCodecContext *avctx)
CHDContext *priv = avctx->priv_data; CHDContext *priv = avctx->priv_data;
priv->need_second_field = 0; priv->need_second_field = 0;
priv->draining = 0;
av_frame_unref (priv->pic); av_frame_unref (priv->pic);
...@@ -438,6 +441,7 @@ static av_cold int init(AVCodecContext *avctx) ...@@ -438,6 +441,7 @@ static av_cold int init(AVCodecContext *avctx)
priv->avctx = avctx; priv->avctx = avctx;
priv->is_nal = avctx->extradata_size > 0 && *(avctx->extradata) == 1; priv->is_nal = avctx->extradata_size > 0 && *(avctx->extradata) == 1;
priv->pic = av_frame_alloc(); priv->pic = av_frame_alloc();
priv->draining = 0;
subtype = id2subtype(priv, avctx->codec->id); subtype = id2subtype(priv, avctx->codec->id);
switch (subtype) { switch (subtype) {
...@@ -670,6 +674,8 @@ FF_ENABLE_DEPRECATION_WARNINGS ...@@ -670,6 +674,8 @@ FF_ENABLE_DEPRECATION_WARNINGS
if ((ret = av_frame_ref(data, priv->pic)) < 0) { if ((ret = av_frame_ref(data, priv->pic)) < 0) {
return ret; return ret;
} }
} else {
return RET_COPY_AGAIN;
} }
return RET_OK; return RET_OK;
...@@ -745,7 +751,7 @@ static inline CopyRet receive_frame(AVCodecContext *avctx, ...@@ -745,7 +751,7 @@ static inline CopyRet receive_frame(AVCodecContext *avctx,
avctx->sample_aspect_ratio = (AVRational) {221, 1}; avctx->sample_aspect_ratio = (AVRational) {221, 1};
break; break;
} }
return RET_OK; return RET_COPY_AGAIN;
} else if (ret == BC_STS_SUCCESS) { } else if (ret == BC_STS_SUCCESS) {
int copy_ret = -1; int copy_ret = -1;
if (output.PoutFlags & BC_POUT_FLAGS_PIB_VALID) { if (output.PoutFlags & BC_POUT_FLAGS_PIB_VALID) {
...@@ -768,13 +774,13 @@ static inline CopyRet receive_frame(AVCodecContext *avctx, ...@@ -768,13 +774,13 @@ static inline CopyRet receive_frame(AVCodecContext *avctx,
*/ */
av_log(avctx, AV_LOG_ERROR, "CrystalHD: ProcOutput succeeded with " av_log(avctx, AV_LOG_ERROR, "CrystalHD: ProcOutput succeeded with "
"invalid PIB\n"); "invalid PIB\n");
copy_ret = RET_OK; copy_ret = RET_COPY_AGAIN;
} }
DtsReleaseOutputBuffs(dev, NULL, FALSE); DtsReleaseOutputBuffs(dev, NULL, FALSE);
return copy_ret; return copy_ret;
} else if (ret == BC_STS_BUSY) { } else if (ret == BC_STS_BUSY) {
return RET_OK; return RET_COPY_AGAIN;
} else { } else {
av_log(avctx, AV_LOG_ERROR, "CrystalHD: ProcOutput failed %d\n", ret); av_log(avctx, AV_LOG_ERROR, "CrystalHD: ProcOutput failed %d\n", ret);
return RET_ERROR; return RET_ERROR;
...@@ -874,6 +880,7 @@ static int crystalhd_decode_packet(AVCodecContext *avctx, const AVPacket *avpkt) ...@@ -874,6 +880,7 @@ static int crystalhd_decode_packet(AVCodecContext *avctx, const AVPacket *avpkt)
} }
} else { } else {
av_log(avctx, AV_LOG_INFO, "CrystalHD: No more input data\n"); av_log(avctx, AV_LOG_INFO, "CrystalHD: No more input data\n");
priv->draining = 1;
ret = AVERROR_EOF; ret = AVERROR_EOF;
goto exit; goto exit;
} }
...@@ -893,22 +900,27 @@ static int crystalhd_receive_frame(AVCodecContext *avctx, AVFrame *frame) ...@@ -893,22 +900,27 @@ static int crystalhd_receive_frame(AVCodecContext *avctx, AVFrame *frame)
av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: receive_frame\n"); av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: receive_frame\n");
bc_ret = DtsGetDriverStatus(dev, &decoder_status); do {
if (bc_ret != BC_STS_SUCCESS) { bc_ret = DtsGetDriverStatus(dev, &decoder_status);
av_log(avctx, AV_LOG_ERROR, "CrystalHD: GetDriverStatus failed\n"); if (bc_ret != BC_STS_SUCCESS) {
return -1; av_log(avctx, AV_LOG_ERROR, "CrystalHD: GetDriverStatus failed\n");
} return -1;
}
if (decoder_status.ReadyListCount == 0) { if (decoder_status.ReadyListCount == 0) {
av_log(avctx, AV_LOG_INFO, "CrystalHD: Insufficient frames ready. Returning\n"); av_log(avctx, AV_LOG_INFO, "CrystalHD: Insufficient frames ready. Returning\n");
return AVERROR(EAGAIN); got_frame = 0;
} rec_ret = RET_OK;
break;
}
rec_ret = receive_frame(avctx, frame, &got_frame);
} while (rec_ret == RET_COPY_AGAIN);
rec_ret = receive_frame(avctx, frame, &got_frame);
if (rec_ret == RET_ERROR) { if (rec_ret == RET_ERROR) {
return -1; return -1;
} else if (got_frame == 0) { } else if (got_frame == 0) {
return AVERROR(EAGAIN); return priv->draining ? AVERROR_EOF : AVERROR(EAGAIN);
} else { } else {
return 0; return 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment